自定义 Converter 原理
# 270.自定义 Converter 原理
上一篇博客,我们仅仅是讲了原理,接下来就来讲讲如何自定义 Converter,并且深入源码来分析原理
# 前端的修改
之前我们是通过级联属性(也就是通过小数点的方式)来传递宠物的信息:
<form action="/saveUser" method="post">
姓名:<input name="userName" value="zhangsan"><br/>
年龄:<input name="age" value="18"><br/>
生日:<input name="birth" value="2022/05/20"><br/>
宠物姓名:<input name="pet.name" value="阿猫"><br/>
宠物年龄:<input name="pet.age" value="5"><br/>
<input type="submit" value="保存"><br/>
</form>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
如果有这样的需求,将宠物名字和年龄,作为一个字符串传入呢?例如:
宠物:<input name="pet" value="阿猫,3"><br/>
1
毫无疑问,是会绑定失败的:typeMismatch,类型不匹配问题
除了这种需求之外,有时候入前端会传来时间数据(但是分隔符是短信),或者传过来货币数据(例如 123,456.00 这种有逗号的数据),此时都需要我们自定义转换器,其转换。
# 自定义 Converter
我们在 WebConfig 中,添加一个转换器(第 35~51 行):
package com.peterjxl.boot.config;
import com.peterjxl.boot.bean.Pet2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;
@Configuration(proxyBeanMethods = false)
public class WebConfig {
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
HiddenHttpMethodFilter filter = new HiddenHttpMethodFilter();
filter.setMethodParam("_m");
return filter;
}
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
//配置路径参数的分隔符
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
//不移除;后面的内容。矩阵变量功能就可以生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new Converter<String, Pet2>(){
@Override
public Pet2 convert(String source) {
//字符串:name,age
if(!StringUtils.isEmpty(source)) {
Pet2 pet2 = new Pet2();
String[] split = source.split(",");
pet2.setName(split[0]);
pet2.setAge(split[1]);
return pet2;
}
return null;
}
});
}
};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 测试
此时我们重启项目,能正常封装数据了:
# 原理
通过上一节课的讲解,原理我们应该也能猜到。我们以 debug 方式启动,然后 debug 到绑定参数的时候(ModelAttributeMethodProcessor 类中):首先会多一个 converter:
我们展开来找,能看到最后一个就是我们刚刚定义的:
然后我们放行请求,能看到会执行到我们自定义的 converter:
然后就绑定结束了,返回宠物对象
# 源码
已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo15,读者可以通过切换分支来查看本文的示例代码
上次更新: 2024/10/3 10:01:52