请求参数的绑定
- 请求参数的绑定说明
- 绑定机制
- 表单提交的数据都是k=v格式的 username=xxx&password=111
- SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的
- 要求:提交表单的name和参数的名称是相同的
- 绑定机制
- 支持的数据类型
- 基本数据类型和字符串类型
- 实体类型(JavaBean)
- 集合数据类型(List、map集合等)
基本数据类型和字符串类型
- 提交表单的name和参数的名称是相同的
- 区分大小写
- 代码示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--请求参数绑定--%>
<a href="param/testParam?username=xxx&password=111">测试普通参数</a>
</body>
</html>
package cn.org.zhang;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(path = "/param")
public class ParamController {
@RequestMapping(path = "/testParam")
//参数名和请求参数保持一致,否则输入的则是null
public String testParam(String username,String password){
System.out.println("执行了...");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
return "success";
}
}
. 实体类型(JavaBean)
- 提交表单的name和JavaBean中的属性名称需要一致
- 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:
user.name
- 代码示例
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2021/2/3
Time: 15:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--把数据封装Account类中--%>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="user.uname" /><br/>
用户年龄:<input type="text" name="user.age" /><br/>
<input type="submit" value="提交" />
</form>
</body>
</html>
package cn.org.zhang;
import cn.org.zhang.domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(path = "/param")
public class ParamController {
@RequestMapping(path = "/saveAccount")
public String testParam(Account account){
System.out.println("执行了...");
System.out.println(account);
return "success";
}
}
package cn.org.zhang.domain;
import cn.org.zhang.until.User;
public class Account {
private String username;
private String password;
private Integer money;
private User user;
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", user=" + user +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
package cn.org.zhang.until;
public class User {
private String uname;
private Integer age;
@Override
public String toString() {
return "User{" +
"uname='" + uname + '\'' +
", age=" + age +
'}';
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
给集合属性数据封装
- JSP页面编写方式:list[0].属性
- 代码示例
<%--把数据封装Account类中,类中存在list和map的集合--%>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="username" /><br/>
密码:<input type="text" name="password" /><br/>
金额:<input type="text" name="money" /><br/>
用户姓名:<input type="text" name="list[0].uname" /><br/>
用户年龄:<input type="text" name="list[0].age" /><br/>
用户姓名:<input type="text" name="map['one'].uname" /><br/>
用户年龄:<input type="text" name="map['one'].age" /><br/>
<input type="submit" value="提交" />
</form>
package cn.org.zhang.domain;
import cn.org.zhang.until.User;
import java.util.List;
import java.util.Map;
public class Account {
private String username;
private String password;
private Integer money;
// private User user;
private List<User> list;
private Map<String,User> map;
@Override
public String toString() {
return "Account{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", money=" + money +
", list=" + list +
", map=" + map +
'}';
}
public List<User> getList() {
return list;
}
public void setList(List<User> list) {
this.list = list;
}
public Map<String, User> getMap() {
return map;
}
public void setMap(Map<String, User> map) {
this.map = map;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
}
其他代码和上一个步骤一样,结果运行如下
请求参数中文乱码的解决
- 测试中文是否乱码
<%--把数据封装Account类中,类中存在list和map的集合--%>
<form action="param/saveAccount" method="post">
姓名:<input type="text" name="uname" /><br/>
年龄:<input type="text" name="age" /><br/>
<input type="submit" value="提交" />
</form>
@RequestMapping(path = "/saveAccount")
public String testParam(User user){
System.out.println("执行了...");
System.out.println(user);
return "success";
}
- 在web.xml中配置Spring提供的过滤器类
<!-- 配置过滤器,解决中文乱码的问题 -->
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
结果如下
自定义类型转换器
- 表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明
Spring框架内部会默认进行数据类型转换。 - 如果想自定义数据类型转换,可以实现Converter的接口
- 自定义类型转换器
package cn.org.zhang.until;
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
//字符串转换为日期格式
public class StringtoDateConverter implements Converter<String, Date> {
//进行类型转换的方法
@Override
public Date convert(String source) {
if(source==null){
throw new RuntimeException("参数不能为空");
}
try {
DateFormat dateFormat=new SimpleDateFormat("yy-mm-dd");
Date date= dateFormat.parse(source);
return date;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
- 注册自定义类型转换器,在springmvc.xml配置文件中编写配置
<!-- 注册自定义类型转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="cn.org.zhang.until.StringtoDateConverter"/>
</set>
</property>
</bean>
<!-- 开启Spring对MVC注解的支持 -->
<mvc:annotation-driven conversion-service="conversionService"/>
在控制器中使用原生的ServletAPI对象
- 只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象
/**
* 原生的API
* @return
*/
@RequestMapping("/testServlet")
public String testServlet(HttpServletRequest request, HttpServletResponse response){
System.out.println("执行了...");
System.out.println(request);
HttpSession session = request.getSession();
System.out.println(session);
ServletContext servletContext = session.getServletContext();
System.out.println(servletContext);
System.out.println(response);
return "success";
}
springMvc常用注解
RequestParam注解
- 作用:
把请求中指定名称的参数给控制器中的形参赋值。 - 属性:
value:请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错
jsp代码
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a>
控制器代码
@RequestMapping(path = "useRequestParam")
public String useRequestParam(@RequestParam(value = "name") String username, @RequestParam(value = "age",required = false) Integer age){
System.out.println(username+","+age);
return "success";
}
RequestBody注解
- 作用:
用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。
get 请求方式不适用。 - 属性:
required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值
为 false,get 请求得到是 null
jsp代码
<form action="springmvc/useRequestBody" method="post">
用户名称:<input type="text" name="username" ><br/>
用户密码:<input type="password" name="password" ><br/>
用户年龄:<input type="text" name="age" ><br/>
<input type="submit" value=" 保存 ">
</form>
<a href="springmvc/useRequestBody?body=test">requestBody 注解 get 请求</a>
控制器代码
@RequestMapping(path="useRequestBody")
public String useRequestBody(@RequestBody(required = false) String body){
System.out.println(body);
return "success";
}
PathVaribale注解
- 作用:
用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。 - 属性:
value:用于指定 url 中占位符名称。
required:是否必须提供占位符
jsp代码
<!-- PathVariable 注解 -->
<a href="springmvc/usePathVariable/100">pathVariable 注解</a>
控制器代码
@RequestMapping(path = "usePathVariable/{sid}")
public String usePathVariable(@PathVariable(name = "sid") String id){
System.out.println(id);
return "success";
}
RequestHeader注解
- 作用:
用于获取请求消息头。 - 属性:
value:提供消息头名称
required:是否必须有此消息头
注:
在实际开发中一般不怎么用。
jsp代码
<!-- RequestHeader 注解 -->
<a href="springmvc/useRequestHeader">获取请求消息头</a>
控制器代码
@RequestMapping("/useRequestHeader")
public String useRequestHeader(@RequestHeader(value="Accept-Language") String requestHeader){
System.out.println(requestHeader);
return "success";
}
CookieValue注解
- 作用:
用于把指定 cookie 名称的值传入控制器方法参数。 - 属性:
value:指定 cookie 的名称。
required:是否必须有此 cookie。
jsp代码
<!-- CookieValue 注解 -->
<a href="springmvc/useCookieValue">绑定 cookie 的值</a>
控制器代码
@RequestMapping("/useCookieValue")
public String useCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
System.out.println(cookieValue);
return "success";
}
ModelAttribute注解
- 作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可
以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值。 - 属性:
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
应用场景: - 当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数
据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题
基于 POJO 属性的基本使用
jsp代码
<!-- ModelAttribute 注解的基本使用 -->
<a href="springmvc/testModelAttribute?uname=test">测试 modelattribute</a>
控制器代码
@ModelAttribute
public void showModel(User user) {
System.out.println("执行了 showModel 方法"+user.getUname());
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user) {
System.out.println("执行了控制器的方法"+user.getUname());
return "success";
}
基于 Map 的应用场景示例 1 :ModelAttribute 修饰方法带返回值
jsp代码
<!-- ModelAttribute 注解的基本使用 -->
<a href="springmvc/testModelAttribute?uname=test">测试 modelattribute</a>
<form action="springmvc/updateUser" method="post">
用户名称:<input type="text" name="uname" ><br/>
用户年龄:<input type="text" name="age" ><br/>
<input type="submit" value=" 保存 ">
</form>
当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据
private User findUserByName(String username) {
User user = new User();
user.setUname(username);
user.setAge(19);
user.setDate(new Date());
return user;
}
@ModelAttribute
public User showModel(String uname) {
//模拟去数据库查询
User abc = findUserByName(uname);
System.out.println("执行了 showModel 方法"+abc);
return abc;
}
@RequestMapping("/updateUser")
public String testModelAttribute2(User user) {
System.out.println("控制器中处理请求的方法:修改用户:"+user);
return "success";
}
基于 Map 的应用场景示例 2:ModelAttribute 修饰方法不带返回值
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key,作用在无返回值
private User findUserByName(String username) {
User user = new User();
user.setUname(username);
user.setAge(19);
user.setDate(new Date());
return user;
}
@ModelAttribute
public void showModel(String uname, Map<String,User>map) {
//模拟去数据库查询
User abc = findUserByName(uname);
System.out.println("执行了 showModel 方法"+abc);
map.put("abc", abc);
}
@RequestMapping("/updateUser")
public String testModelAttribute2(@ModelAttribute("abc") User user) {
System.out.println("控制器中处理请求的方法:修改用户:"+user);
return "success";
}
SessionAttribute
- 作用:
用于多次执行控制器方法间的参数共享。 - 属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。
jsp代码
<!-- SessionAttribute 注解的使用 -->
<a href="springmvc/testPut">存入 SessionAttribute</a>
<hr/>
<a href="springmvc/testGet">取出 SessionAttribute</a>
<hr/>
<a href="springmvc/testClean">清除 SessionAttribute</a>
控制器代码
@RequestMapping("/testPut")
public String testPut(ModelMap modelMap) {
modelMap.addAttribute("msg", "dalao");
return "success";
}
@RequestMapping("/testGet")
public String testGet(ModelMap modelMap) {
String msg=(String) modelMap.get("msg");
System.out.println(msg);
return "success";
}
@RequestMapping("/testClean")
public String testClean(SessionStatus sessionStatus) {
sessionStatus.setComplete();
return "success";
}