SpringBoot自定义参数绑定及源码解析
1、实例演示
首页index.html如下:其中pet相关属性用了person类中的级联属性表示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义参数测试</title>
</head>
<body>
<form action="/saveuser" method="post">
<!--name的值与实体类中的命名要保持一致-->
姓名: <input name="userName" value="zhangsan"/> <br/>
年龄: <input name="age" value="18"/> <br/>
生日: <input name="birth" value="2019/12/10"/> <br/>
宠物姓名:<input name="pet.name" value="阿猫"/><br/>
宠物年龄:<input name="pet.age" value="5"/>
<input type="submit" value="保存"/>
</form>
</body>
</html>
复制代码
自定义实体类Person与表单的参数名一一对应:
@Data
public class Person {
private String userName;
private Integer age;
private Date birth;
private Pet pet;
}
复制代码
Pet类:
@Data
public class Pet {
private String name;
private String age;
}
复制代码
测试:返回Person对象查看是否绑定成功
@RestController
public class TestController {
/**
*数据绑定:页面提交的请求数据(GET、 POST) 都可以和对象属性进行绑定
*@param person
*@return
*/
@PostMapping("/saveuser")
public Person saveuser(Person person) {
return person;
}
}
复制代码
结果:访问首页,点击保存,成功出现结果,属性全部封装到Person这个pojo
2、自定义参数的绑定原理
我们先来简单说一下自定义参数的绑定原理:
在SpringMVC的请求参数解析中,我们是在下面这一步决定使用哪一个参数解析器来解析我们请求中的各种参数类型(value属性值)
经过断点分析,最后会发现我们的自定义参数类型是由ServletModelAttributeMethodProcessor
所处理的,ServletModelAttributeMethodProcessor
这个参数解析器支持自定义参数绑定,它在底层使用了WebDataBinder
数据绑定器,而数据绑定器中有一个conversionService
,conversionService
中注册了很多类型转换器converters
,converters
会帮助我们进行类型转换
最后再经过convert方法完成后,再将最后的值设置到实体类中,convert方法很简单:如下
3、自定义converter
3.1、测试
@Data
public class Person {
private String userName;
private Integer age;
private Date birth;
private Pet pet;
}
@Data
public class Pet {
private String name;
private String age;
}
复制代码
index.html:这里,有一个属性pet,value以逗号分割,前面是name,后面是age
<form action="save" method="post">
姓名: <input name="userName" value="admin"/> <br/>
年龄: <input name="age" value="12"/> <br/>
生日: <input name="birth" value="2021/01/01"/> <br/>
宠物姓名:<input name="pet" value="cat,18"/><br/>
<input type="submit" value="保存">
</form>
复制代码
controller:
@PostMapping("save")
@ResponseBody
public Person save(Person person){
return person;
}
复制代码
先进行测试,直接报错了,原因就是字符串属性转成pet属性错误,Springmvc不知道我们你表单传入的参数是以逗号分隔,前面是名字,后面是年龄,所以转换异常
3.2、自定义Converter
在springboot2中,我们对springmvc的组件做一些定制化工作的话,一般需要实现WebMvcConfigurer
接口,仔细找一找,不难发现注册自定义converter的方法:
/**
* Add {@link Converter Converters} and {@link Formatter Formatters} in addition to the ones
* registered by default.
*/
default void addFormatters(FormatterRegistry registry) {
}
复制代码
接下来,我们就可以定制Converter了
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter<String, Pet>(){
//阿猫,3
@Override
public Pet convert(String source) {
if(StringUtils.isEmpty(source)) return null;
String[] split = source.split(",");
Pet pet = new Pet();
pet.setName(split[0]);
pet.setAge(split[1]);
return pet;
}
});
}
}
复制代码
测试:
addFormatters方法源码