ControllerAdvice 除了可以完成全局异常的处理,同时也可以在真正调用方法之前对body 中的请求参数进行处理,以及在对body 数据相应写回之前对数据进行处理;
只需要增加@ControllerAdvice 注解 并实现RequestBodyAdvice,ResponseBodyAdvice 覆盖其中的方法即可;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.io.IOException;
import java.lang.reflect.Type;
@Component
@ControllerAdvice
public class AdviceController implements RequestBodyAdvice,ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
// 返回true ,beforeBodyRead 和 afterBodyRead 才会起作用
return true;
}
// 在读取body 数据之前,可以对数据进行一些验证和加工
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
// 在body 数据解析完成之后,调用方法。可以对读取到的数据进行加工
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return null;
}
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
// 返回true ,beforeBodyWrite 才会起作用
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 请求的数据相应之前 可以对数据进行加工
return body;
}
}
在使用方面需要注意一下几个方面:
@ControllerAdvice 注解的解析在 RequestMappingHandlerAdapter bean 初始化之后的afterPropertiesSet 方法中
public void afterPropertiesSet() {
// 对 @ControllerAdvice 进行了解析
this.initControllerAdviceCache();
List handlers;
if (this.argumentResolvers == null) {
handlers = this.getDefaultArgumentResolvers();
this.argumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.initBinderArgumentResolvers == null) {
handlers = this.getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = (new HandlerMethodArgumentResolverComposite()).addResolvers(handlers);
}
if (this.returnValueHandlers == null) {
handlers = this.getDefaultReturnValueHandlers();
this.returnValueHandlers = (new HandlerMethodReturnValueHandlerComposite()).addHandlers(handlers);
}
}
initControllerAdviceCache 解析
private void initControllerAdviceCache() {
if (this.getApplicationContext() != null) {
// 获取所有类上有 ControllerAdvice 注解的bean
List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(this.getApplicationContext());
List<Object> requestResponseBodyAdviceBeans = new ArrayList();
Iterator var3 = adviceBeans.iterator();
while(var3.hasNext()) {
ControllerAdviceBean adviceBean = (ControllerAdviceBean)var3.next();
Class<?> beanType = adviceBean.getBeanType();
if (beanType == null) {
throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);
}
Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS);
if (!attrMethods.isEmpty()) {
this.modelAttributeAdviceCache.put(adviceBean, attrMethods);
}
Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS);
if (!binderMethods.isEmpty()) {
this.initBinderAdviceCache.put(adviceBean, binderMethods);
}
if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) {
requestResponseBodyAdviceBeans.add(adviceBean);
}
}
if (!requestResponseBodyAdviceBeans.isEmpty()) {
// 最终加入到 List