前言
由@InitBinder注解修饰的方法用于初始化WebDataBinder对象,能够实现:从request获取到handler方法中由@RequestParam注解或@PathVariable注解修饰的参数后,假如获取到的参数类型与handler方法上的参数类型不匹配,此时可以使用初始化好的WebDataBinder对获取到的参数进行类型处理。
一个经典的例子就是handler方法上的参数类型为Date,而从request中获取到的参数类型是字符串,SpringMVC在默认情况下无法实现字符串转Date,此时可以在由@InitBinder注解修饰的方法中为WebDataBinder对象注册CustomDateEditor,从而使得WebDataBinder能将从request中获取到的字符串再转换为Date对象。
通常,如果在@ControllerAdvice注解修饰的类中使用@InitBinder注解,此时@InitBinder注解修饰的方法所做的事情全局生效(前提是@ControllerAdvice注解没有设置basePackages字段);如果在@Controller注解修饰的类中使用@InitBinder注解,此时@InitBinder注解修饰的方法所做的事情仅对当前Controller生效。本篇文章将结合简单例子,对@InitBinder注解的使用,原理进行学习。
SpringBoot版本:2.4.1
正文
一. @InitBinder注解使用说明
以前言中提到的字符串转Date为例,对@InitBinder的使用进行说明。
@RestController
public class DateController {
private static final String SUCCESS = "success";
private static final String FAILED = "failed";
private final List<Date> dates = new ArrayList<>();
@RequestMapping(value = "/api/v1/date/add", method = RequestMethod.GET)
public ResponseEntity<String> addDate(@RequestParam("date") Date date) {
ResponseEntity<String> response;
try {
dates.add(date);
response = new ResponseEntity<>(SUCCESS, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
response = new ResponseEntity<>(FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
}
return response;
}
}
复制代码
上面写好了一个简单的Controller,用于获取Date并存储。然后在单元测试中使用TestRestTemplate模拟客户端向服务端发起请求,程序如下。
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DateControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void 测试Date字符串转换为Date对象() {
ResponseEntity<String> response = restTemplate
.getForEntity("/api/v1/date/add?date=20200620", String.class);
assertThat(response.getStatusCodeValue(), is(HttpStatus.OK.value()));
}
}
复制代码
由于此时并没有使用@InitBinder注解修饰的方法向WebDataBinder注册CustomDateEditor对象,运行测试程序时断言会无法通过,报错会包含如下信息。
Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'
由于无法将字符串转换为Date,导致了参数类型不匹配的异常。
下面使用@ControllerAdvice注解和@InitBinder注解为WebDataBinder添加CustomDateEditor对象,使SpringMVC框架为我们实现字符串转Date。
@ControllerAdvice
public class GlobalControllerAdvice {
@InitBinder
public void setDateEditor(WebDataBinder binder) {