Spring MVC 数据绑定
数据绑定:在后端的业务方法中直接获取客户端 HTTP 请求中的参数,将请求参数映射到业务方法的形参中, Spring MVC 中数据绑定的工作是由 HandlerAdapter 来完成的。
- 基本数据类型
package org.westos.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author lwj
* @date 2020/12/19 16:44
*/
@Controller
@RequestMapping("/data")
public class DataBindHandler {
@ResponseBody
@RequestMapping("/baseType")
public String baseType(int id) {
return id + "";
}
}
@ResponseBody:表示 Spring MVC 会直接将业务方法的返回值响应给客户端,如果不加 @ResponseBody 注解,Spring MVC 会将业务方法的返回值传递给 DispatcherServlet,再由 DispatcherServlet 调用 ViewResolver 对返回值进行解析,映射到一个 JSP 资源。
http://localhost:8080/data/baseType?id=1
缺陷:基本数据类型不能接收Null值。
- 包装类
@ResponseBody
@RequestMapping("/packageType")
public String packageType(@RequestParam(value = "num", required = false, defaultValue = "0") Integer id) {
return id + "";
}
包装类可以接收 null ,当 HTTP 请求没有参数时,使用包装类定义形参的数据类型,程序不会抛出异常。(响应客户端null)
@RequestParam
value = “num”:将 HTTP 请求中名为 num 的参数赋给形参 id。
required:设置 num 是否为必填项,true 表示必填,false 表示非必填,可省略。
defaultValue = “0”:如果 HTTP 请求中没有 num 参数,默认值为0。
http://localhost:8080/data/packageType
客户端显示0。
http://localhost:8080/data/packageType?num=10
客户端显示10。
- 数组
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/array")
public String array(String[] num) {
String str = Arrays.toString(num);
return str;
}
}
@RestController 表示该控制器会直接将业务方法的返回值响应给客户端,不进行视图解析。
@Controller 表示该控制器的每一个业务方法的返回值都会交给视图解析器进行解析,如果只需要将数据响应给客户端,而不需要进行视图解析,则需要在对应的业务方法定义处添加 @ResponseBody 。
http://localhost:8080/data/array?num=1&num=2&num=3
等同于
@Controller
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/array")
@ResponseBody
public String array(String[] num) {
String str = Arrays.toString(num);
return str;
}
}
- List
Spring MVC 不支持 List 类型的直接转换,需要对 List 集合进行包装。
集合封装类
@Data
public class UserList {
private List<User> users;
}
JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/data/list" method="post">
用户1编号:<input type="text" name="users[0].id">
姓名:<input type="text" name="users[0].name">
地址:<input type="text" name="users[0].address.value"> <br>
用户2编号:<input type="text" name="users[1].id">
姓名:<input type="text" name="users[1].name">
地址:<input type="text" name="users[1].address.value"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
业务方法
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/list")
public String list(UserList userList) {
StringBuilder str = new StringBuilder();
for (User user : userList.getUsers()) {
System.out.println(user);
str.append(user);
}
return str.toString();
}
}
此时从前台到后台的数据绑定是没有问题的。但是从后台向前台传递时出现了中文乱码问题。
处理 @ResponseBody 的中文乱码,在 springmvc.xml 中配置消息转换器。
<mvc:annotation-driven>
<!--在注解驱动中配置消息转换器-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
- Map
自定义封装类
@Data
public class UserMap {
private Map<String, User> users;
}
业务方法
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/map")
public String map(UserMap userMap) {
StringBuilder str = new StringBuilder();
for (String s : userMap.getUsers().keySet()) {
User user = userMap.getUsers().get(s);
str.append(user);
}
return str.toString();
}
}
JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/data/map" method="post">
用户1编号:<input type="text" name="users['ab'].id">
姓名:<input type="text" name="users['ab'].name">
地址:<input type="text" name="users['ab'].address.value"> <br>
用户2编号:<input type="text" name="users['ba'].id">
姓名:<input type="text" name="users['ba'].name">
地址:<input type="text" name="users['ba'].address.value"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
- JSON
客户端发送 JSON 格式的数据,直接通过 Spring MVC 绑定到业务方法的形参中。
处理 Spring MVC 无法加载静态资源,在 web.xml 中添加配置即可。
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<script src="js/jquery-3.5.1.min.js"></script>
<script>
$(function () {
let user = {
id: 1,
name: "张三"
}
$.ajax({
url: "/data/json",
data: JSON.stringify(user),
method: "POST",
contentType: "application/json;charset=UTF-8",
dataType: "JSON",
success: function (data) {
alert(data.id + "---" + data.name);
}
})
});
</script>
</body>
</html>
上面代码中最重要的是contentType属性。
业务方法
@RestController
@RequestMapping("/data")
public class DataBindHandler {
@RequestMapping("/json")
public User user(@RequestBody User user) {
System.out.println(user);
user.setId(2);
user.setName("李四");
return user;
}
}
Spring MVC 中的 JSON 和 JavaBean 的转换需要借助于 fastjson,po.xml中引入相关依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
springmvc.xml 添加 fastjson 配置。
<mvc:annotation-driven>
<!--在注解驱动中配置消息转换器-->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
</bean>
<!--配置fastjson-->
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>