Spring WebDataBinder
什么是WebDataBinder
WebDataBinder
可以:
- 将请求参数(form或query data)绑定到一个模型对象上
- 将基于String的请求值(比如请求参数、路径变量、头、Cookies等)转换为Controller方法参数的目标类型
- 渲染HTML表单时将模型对象值格式化为
String
值
在Web应用中,databinding可以将HTTP请求参数(form data或query parameter)绑定到一个模型对象或它的内嵌对象的属性中。
只有符合JavaBean命名惯例规定的public
属性才会被databinding绑定,比如一个firstName
属性的public String getFirstName()
和public void setFirstName(String)
方法。
尝试
尝试向Model Object中注入属性
下面在一个Controller方法中,我们定义了一个Person
类型的参数,按照官方文档中@RequestMapping方法参数一节的描述,我们知道这个Person
将被作为@ModelAttribute
参数来处理,在没有其它代码的情况下,SpringMVC会调用它的无参构造器创建一个新的Person
对象并加入到Model
中:
@GetMapping("/testInjectToModelObjectProperties")
public String testInjectToModelObjectProperties(
Person person,
Model model
) {
System.out.println("Person: " + person);
System.out.println("Model: " + model);
return "modelTestPage3";
}
根据上面的描述,databinding将HTTP请求的参数绑定到模型对象的属性中,那我们不妨试试,如下是我的请求URL:
http://${webapplicationrootpath}/databinding/testInjectToModelObjectProperties?name=Yudoge&age=12&weight=158.7&height=180&address=%E7%BF%BB%E6%96%97%E5%A4%A7%E8%A1%97%E7%BF%BB%E6%96%97%E8%8A%B1%E5%9B%AD3%E5%8F%B7%E6%A5%BC1001%E5%AE%A4&birthday=2001-04-10
我们将Person中的全部属性都通过URL参数进行了注入,得到的结果是:
尝试向Model Object内嵌的对象中注入属性
构造一个具有内嵌对象的Pojo:
@Data
@NoArgsConstructor
public class NestedPerson {
String testField;
Person person;
}
URL:
http://localhost:8080/databinding/testInjectNestedProperty?testField=hello&person.name=Yudoge
在注入内嵌属性的时候,需要带属性的完整路径,比如person.name
,WebBinder会自动创建嵌套的Person
对象。
配置WebDataBinder
@Controller
、@ControllerAdvice
类都可以有一个@InitBinder
注解标注的方法用来初始化它的WebDataBinder
对象。
@InitBinder
public void initBinder(WebDataBinder binder) {
}
在这个方法中,你可以对本Controller的WebDataBinder
做任何配置。比如你可以注册该Controller特定的PropertyEditor
、Converter
和Formatter
组件。
@InitBinder
方法也支持与@RequestMapping
方法一样的参数,除了@ModelAttribute
参数。
下面通过WebDateBinder
注册了PropertyEditor
、Formatter
和Converter
。WebDataBinder
好像没有直接用于注册Converter
的API,但是它有一个用于获取ConversionService
的API,一般的ConversionService
都同样实现了ConverterRegistry
,所以可以通过这个来注册Converter
:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), false));
binder.addCustomFormatter(new DateFormatter());
FormattingConversionService service = (FormattingConversionService) binder.getConversionService();
service.addConverter(xxx);
}