参数处理器(ArgumentResolvers)和返回参数处理器(ReturnValueHandlers)
在我们调用controller层组件时,Springboot实际上是使用代理模式进行调用,springmvc定义了一个DispatcherServlet实现HttpServlet方法,通过DispatcherServlet的doservice()方法处理请求,在doservice方法中,springboot先根据请求的request对象生成包含对应处理此请求的必要信息的对象mapperHandler,再根据mapperHandler对象生成实际处理请求的HandlerAdapter对象,调用HandlerAdapter的handle方法真正对请求进行处理,在执行我们实际定义的处理方法代码之前和之后,HandlerAdapter会调用一些代理增强,其中就包括根据我们方法的定义来选择合适的参数处理器来将请求中的参数封装成一个个对象,拿到对象后再通过反射使用处理好的参数执行我们定义好的Controller层处理逻辑,同理在执行完实际方法之后,在选择合适的返回值处理器真正处理返回。
WebMvcConfigurationSupport这个配置类中配置了springboot默认的各种处理器
自定义处理器
对于***自定义的参数处理器,springboot提供了一个HandlerMethodArgumentResolver接口。***
自定义返回参数处理器springboot提供了一个HandlerMethodReturnValueHandler接口。
通过实现上述两个接口,我们可以实现自己的自定义处理器。
springboot也有一个名为AbstractMessageConverterMethodProcessor的抽象类,这个抽象类实现了上述两个参数处理器接口和返回参数处理器接口,我们可以直接继承AbstractMessageConverterMethodProcessor抽象类重写相关方法同时实现参数处理器和返回值处理器。
- 需要注意的是,Spring有许多默认的参数处理器,在springboot底层调用时,所有的处理器都存储在一个list集合中,使用一个for循环进行调用,谁先被循环到符合条件就调用谁,暂未找到去除自带方法处理器的方法,最好是自己定义一个注解进行标识,从而百分百生效。
- 下面我们实现一个自定义的处理器。
自定义一个注解进行标识:
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnocation {
}
自定义一个方法处理器
@Component
public class MyProcesser extends AbstractMessageConverterMethodProcessor {protected MyProcesser(List<HttpMessageConverter<?>> converters) {super(converters);}@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(MyAnnocation.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {Bean1 bean1 = new Bean1();bean1.setName("hello world");return bean1;}//如果返回是Bean1类型就支持处理@Overridepublic boolean supportsReturnType(MethodParameter returnType) {return returnType.getMethod().getReturnType().equals(Bean1.class);}@Overridepublic void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {//这里是摘抄springboot默认的RequestResponseBodyMethodProcessor处理器直接返回json对象。mavContainer.setRequestHandled(true);ServletServerHttpRequest inputMessage = createInputMessage(webRequest);ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);System.out.println("my handleReturnValue");// Try even with null return value. ResponseBodyAdvice could get involved.writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);}
}
添加这个处理器到容器中
@Configuration
public class WebConfigure implements WebMvcConfigurer {private final MyProcesser myProcesser;public WebConfigure(MyProcesser myProcesser) {this.myProcesser = myProcesser;}@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(myProcesser);}@Overridepublic void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {handlers.add(myProcesser);}
}
测试类
//注意这里不要直接使用RestController注解,那样的话等同于在方法前加@ResponseBody,在遍历处理器时,默认处理@ResponseBody的处理
//器RequestResponseProcesser顺序可能在我们自定义的处理器之前从而导致无法调用我们自定义的处理器。
@Controller
public class TestController {@GetMapping("/test")public Bean1 test(@MyAnnocation Bean1 bean) {return bean;}
}