SpringMVC(二):参数绑定
文章目录
1. 参数绑定机制
在 SpringMVC 中,提交请求的数据是通过方法形参来接收的。从客户端请求的 key/value 数据,经过参数绑定,将 key/value 数据绑定到 Controller 的形参上,然后在 Controller 就可以直接使用该形参。
2. @RequestParam注解
-
作用:一般来讲,前端请求函数名称和后台参数名称是一致的,如果不一致,需要用请求中指定名称的参数给控制器中的形参赋值。
-
属性:
value: 请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值: true。表示必须提供,如果不提供将报错。 -
演示
前端代码,请求参数是accountId=10
<a href="account/findAccount?accountId=10">查询账户</a>
后台代码(形参名称为id,和请求参数名称accountId不一致)
// 控制器,处理请求的类
@Controller
@RequestMapping("/account")
public class UserController {
@RequestMapping("/findAccount")
public String findAccount(\@RequestParam("accountId",required="true") Integer id){
System.out.println("查询了账户。。"+id)
return "success";
}
}
2.5 搭建环境
搭建springmvc的环境,配置pom.xml,web.xml和spring配置文件,接下来的参数绑定测试默认有这几个文件。
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zmysna</groupId>
<artifactId>springmvc01</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
</project>
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--配置前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!--配置编码过滤器-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--配置注解扫描-->
<context:component-scan base-package="com.zmysna.controller"></context:component-scan>
<!--配置注解支持,同时加载了处理器映射器和处理器适配器-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
- hello.jsp 执行处理方法完成后跳转的页面,放在pages目录下。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hello</title>
</head>
<body>
hello world!!!!!
</body>
</html>
3. 基本数据类型绑定
注意:
- 如果后台参数是基本数据类型,如果从前台页面传递的值为 null 或者 “”的话,那么会出现数据转换的异常,所以尽量使用包装类型。
- 请求参数名称和后台参数名称要一致,需要用@RequestParam把请求中指定名称的参数给控制器中的形参赋值。
// 控制器,处理请求的类
@Controller
// 访问当前类的一级目录。最后访问路径要是一级目录 + 方法的访问路径
@RequestMapping("user")
public class UserController {
// 请求路径: http://localhost:8080/user/save?id=100&name=Jack
@RequestMapping("save.do")
public String save(Integer id, String name) {
System.out.println(id); //100
System.out.println(name);//jack
return "success";
}
// 请求路径: http://localhost:8080/user/update?id=&name=Jack
@RequestMapping("update.do")
public String update(int id, String name) {
System.out.println(id); //产生异常
System.out.println(username);
return "success";
}
}
4. PoJo类型参数绑定
注意:请求参数名称一定要和对象的属性一致(不能使用@RequestParam,因此必须一致)
例如:页面参数绑定User实体类
<input type=text name=“id”/> id 就是 user 对象的属性
<input type=text name=“name”/> name 也是 user 对象的属性
4.1 User类
public class User {
private Integer id;
private String usernamename;
//....get/set省略不写
}
4.2 前台页面
部分代码,提交参数id和username
<form action="/user/userMapping" method="post">
<input type="text" name="id">
<input type="text" name="username">
<input type="submit" value=" 提交">
</form>
4.3 后台代码
@Controller
@RequestMapping("/user")
public class UserController {
// 测试请求路径: http://localhost:8080/user/userMapping?id=100&username=Jack
@RequestMapping(value = "/userMapping")
private String userMapping(User user) {
System.out.println(user);
return "hello";
}
}
结果
user[id=100,username=Jack]
5. 数组和集合类型
注意:
集合类型的请求参数必须在POJO实体类中,作为一个POJO属性存在,并且请求参数名称和实体类中集合属性名称相同。
给List集合中的元素赋值,使用下标。
给Map集合中的元素赋值,是要键值对。
需求:给处理器方法赋值,方法参数是一个有集合属性的实体类。
5.1 实体类
- Address类
public class Address{
private String province;
private String city;
//...get/set方法省略
}
- User类
package com.zmysna.entity;
import java.util.List;
import java.util.Map;
public class User {
private Integer id;
private String name;
private List<Addresss> Int;
private Map<String,String> map;
//...get/set方法省略
}
5.2 index.jsp页面部分代码
<h3>获取请求参数:3.把请求参数封装到对象的集合中</h3>
<form action="/user/update3.do" method="post">
用户 id:<input type="text" name="id"> <br>
用户名称:<input type="text" name="name"> <br>
省份:<input type="text" name="address.province"> <br>
城市:<input type="text" name="address.city"> <br>
省份 list:<input type="text" name="list[0].province"> <br>
城市 list:<input type="text" name="list[0].city"> <br>
省份 list:<input type="text" name="list[1].province"> <br>
城市 list:<input type="text" name="list[1].city"> <br>
省份 map:<input type="text" name="map['one'].province"> <br>
省份 map:<input type="text" name="map['one'].city"> <br>
省份 map:<input type="text" name="map['two'].province"> <br>
省份 map:<input type="text" name="map['two'].city"> <br>
<input type="submit" value="post 提交">
</form>
5.3 控制器代码
//封装请求参数到形参。
@RequestMapping("/multiUser")
private String multiUser(User user) {
System.out.println(user);
return "hello";
}
6.servletApi
SpringMVC 还支持使用原始 ServletAPI 对象作为控制器方法的参数。支持原始 ServletAPI 对象有:
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
我们可以把上述对象,直接写在控制的方法参数中使用
<a href=“user/sevletApi.do”>使用servletApi</a>
@RequestMapping(value = "/servletApi")
private void servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
//转发
// request.getRequestDispatcher("/pages/hello.jsp").forward(request,response);
//重定向
`response.sendRedirect("/pages/hello.jsp");
}
7. 其他类型
为了实现参数绑定,spring默认实现了一些数据类型自动转换。想要实现自定义的类型转换,可以定义类实现Converter接口,并且配置类型转换器工厂(ConversionServiceFactoryBean)。
需求:将页面上的date参数值(字符串)封装到后台的形参上
7.1 index.jsp页面部分代码
<a href="user/searchByDate2.do?date=1998-09-09">日期 2</a>
####7.2 后台部分代码
@RequestMapping("/searchByDate2.do")
private String searchByDate2(Date date) {
System.out.println(date);
return "hello";
}
7.3 自定义类型转换
- 转换类实现Converter接口
package com.zmysna.utils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDateConvert implements Converter<String, Date> {
@Override
public Date convert(String s) {
try {
if (StringUtils.isEmpty(s)) {
throw new RuntimeException("数据源为空");
}
return new SimpleDateFormat("yyyy-MM-dd").parse(s);
} catch (ParseException e) {
throw new RuntimeException("只支持日期类型为 yyyy-MM-dd 的转换!");
}
}
}
- 在springmvc.xml中进行配置
<bean id="serviceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<!-- 指定 set 集合的元素,就是自定义的转换器类 -->
<bean class="com.zmysna.utils.StringToDateConvert"></bean>
</set>
</property>
</bean>
<mvc:annotation-driven conversion-service="serviceFactoryBean"></mvc:annotation-driven>
</beans>