@ControllerAdvice是Spring框架提供的一个注解,用于对控制器提供一些增强功能,主要用于处理全局的异常、数据的绑定以及预处理请求参数等。
具体用法参考:@ControllerAdvice与@RestControllerAdvice
除了上面文章说到了用法,这里再补充下@InitBinder
和@ResponseBodyAdvice
InitBinder
@InitBinder
的来源有两个:
- @ControllerAdvice 中 @InitBinder 标注的方法,由 RequestMappingHandlerAdapter 在初始化时解析并记录
- @Controller 中 @InitBinder 标注的方法,由 RequestMappingHandlerAdapter 会在控制器方法首次执行时解析并记录
所以,在RequestMappingHandlerAdapter执行控制器方法前,肯定要全部解析好@InitBinder,因为要对控制器方法进行增强。
看下RequestMappingHandlerAdapter源码有如下两个属性
private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);
private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();
initBinderCache
:就是用来存储@Controller 中 @InitBinder 标注的方法initBinderAdviceCache
:用来存储@Controller 中 @InitBinder 标注的方法
当解析一个@InitBinder 时,就加到这两个缓存里,后面再遇到,直接从这两个缓存里找即可,不用每次解析了。
下面看一个实例,体会下两种@InitBinder用法的区别
首先沿用上一章的MyDateFormatter:
package com.cys.spring.chapter12;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.Formatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class MyDateFormatter implements Formatter<Date> {
private static final Logger log = LoggerFactory.getLogger(MyDateFormatter.class);
private final String desc;
public MyDateFormatter(String desc) {
this.desc = desc;
}
@Override
public String print(Date date, Locale locale) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy|MM|dd");
return sdf.format(date);
}
@Override
public Date parse(String text, Locale locale) throws ParseException {
log.debug(">>>>>> 进入了: {}", desc);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy|MM|dd");
return sdf.parse(text);
}
}
创建一个WebConfig
package com.cys.spring.chapter12;
import com.cys.spring.chapter12.MyDateFormatter;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
@Configuration
public class WebConfig {
@ControllerAdvice
static class MyControllerAdvice {
@InitBinder
public void binder3(WebDataBinder webDataBinder) {
webDataBinder.addCustomFormatter(new MyDateFormatter("binder3 转换器"));
}
}
@Controller
static class Controller1 {
@InitBinder
public void binder1(WebDataBinder webDataBinder) {
webDataBinder.addCustomFormatter(new MyDateFormatter("binder1 转换器"));
}
public void foo() {
}
}
@Controller
static class Controller2 {
@InitBinder
public void binder21(WebDataBinder webDataBinder) {
webDataBinder.addCustomFormatter(new MyDateFormatter("binder21 转换器"));
}
@InitBinder
public void binder22(WebDataBinder webDataBinder) {
webDataBinder.addCustomFormatter(new MyDateFormatter("binder22 转换器"));
}
public void bar() {
}
}
}
测试类:
package com.cys.spring.chapter12;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org