我们知道无论是 Get 请求还是 Post 请求,Controller 这边都可以定义一个实体类来接收这些参数。而 @ControllerAdvice 结合 @InitBinder 还能实现请求参数预处理,即将表单中的数据绑定到实体类上时进行一些额外处理。
三、请求参数预处理(搭配 @InitBinder)
1,问题描述
(1)假设我们有如下两个实体类 User 和 Book:
1 2 3 4 5 6 7 8 9 10 11 | public class User { private String name; private Integer age; // 省略getter/setter } public class Book { private String name; private Float price; // 省略getter/setter } |
(2)如果在 Contoller 上需要接收两个实体类的数据,接收方法可以这么定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 | package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping ( "/hello" ) public String hello(User user, Book book) { return "name:" + user.getName() + " | age:" + user.getAge() + "<br>" + "name:" + book.getName() + " | price:" + book.getPrice(); } } |
(3)但由于两个实体类中都有 name 属性,那么参数传递时就会发生混淆。
转存失败重新上传取消
2,解决办法
(1)使用 @ControllerAdvice 结合 @InitBinder 即可解决上面的问题,这里我们创建一个全局的参数预处理配置。
代码说明:
- 第一个 @InitBinder("user") 表示该方法是处理 Controller 中 @ModelAttribute("user") 对应的参数。
- 第二个 @InitBinder("book") 表示该方法是处理 Controller 中 @ModelAttribute("book") 对应的参数。
- 这两个方法中给相应的 Filed 设置一个前缀。
补充说明:在 WebDataBinder 对象中,除了可以设置前缀,还可以设置允许、禁止的字段、必填字段以及验证器等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package com.example.demo; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.InitBinder; @ControllerAdvice public class GlobalConfig { @InitBinder ( "user" ) public void init1(WebDataBinder binder) { binder.setFieldDefaultPrefix( "user." ); } @InitBinder ( "book" ) public void init2(WebDataBinder binder) { binder.setFieldDefaultPrefix( "book." ); } } |
(2)然后 Controller 中方法的参数添加 @ModelAttribute 注解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.example.demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping ( "/hello" ) public String hello( @ModelAttribute ( "user" ) User user, @ModelAttribute ( "book" ) Book book) { return "name:" + user.getName() + " | age:" + user.getAge() + "<br>" + "name:" + book.getName() + " | price:" + book.getPrice(); } } |
(3)最后浏览器请求参数中添加相应的前缀,即可成功区分出 name 属性:当然也可以在 Cotroller 里面使用 @InitBinder 来单独定义预处理方法,具体参考我写的另一篇文章:
正在上传…重新上传取消
原文出自:www.hangge.com 转载请保留原文链接:https://www.hangge.com/blog/cache/detail_2483.html