请求方法参数的处理HandlerMethodArgumentResolver和响应返回值的处理HandlerMethodReturnValueHandler


SpringMVC处理请求大致是这样的:
首先被DispatcherServlet截获,DispatcherServlet通过handlerMapping获得HandlerExecutionChain,然后获得HandlerAdapter。
HandlerAdapter在内部对于每个请求,都会实例化一个ServletInvocableHandlerMethod进行处理,ServletInvocableHandlerMethod在进行处理的时候,会分两部分别对请求跟响应进行处理。
之后HandlerAdapter得到ModelAndView,然后做相应的处理。

ServletInvocableHandlerMethod#invokeAndHandle对请求以及响应的处理。

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object… providedArgs_) _throws Exception {

//具体处理请求逻辑Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);

if (returnValue == null) {
__ _if
(_
isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
__
mavContainer.setRequestHandled(_true)_;
return;
}
}
_else if
(_
StringUtils.hasText(getResponseStatusReason())) {
__
mavContainer.setRequestHandled(_true)_;
return;
}

mavContainer.setRequestHandled(_false)_;
Assert.state_(_this.returnValueHandlers != null, “No return value handlers”);
try {
__
//返回值处理逻辑
this.returnValueHandlers.handleReturnValue(
__
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
__ _catch
(_
Exception ex) {
__ _if
(_logger
.isTraceEnabled()) {
_
_logger
.trace(formatErrorForReturnValue(returnValue), ex);
}
_
_throw
ex;
}
__}


处理请求的时候,会根据ServletInvocableHandlerMethod的属性argumentResolvers(这个属性是它的父类InvocableHandlerMethod中定义的)进行处理,其中argumentResolvers属性是一个HandlerMethodArgumentResolverComposite类(这里使用了组合模式的一种变形),这个类是实现了HandlerMethodArgumentResolver接口的类,里面有各种实现了HandlerMethodArgumentResolver的List集合。

处理响应的时候,会根据ServletInvocableHandlerMethod的属性returnValueHandlers(自身属性)进行处理,returnValueHandlers属性是一个HandlerMethodReturnValueHandlerComposite类(这里使用了组合模式的一种变形),这个类是实现了HandlerMethodReturnValueHandler接口的类,里面有各种实现了HandlerMethodReturnValueHandler的List集合。

被加入到Spring容器的时机


RequestMappingHandlerAdapter的argumentResolvers和returnValueHandlers这两个属性是在 RequestMappingHandlerAdapter#afterPropertiesSet进行实例化的时候被Spring容器注入的。

@Override
public void afterPropertiesSet() {
__
// Do this first, it may add ResponseBody advice beans
//支持@ControllerAdvice注解
initControllerAdviceCache();

if _(_this.argumentResolvers == null) {
__
//初始化ArgumentResolvers
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
__ _if
(_this
.initBinderArgumentResolvers == null) {
__
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
__ _if
(_this
.returnValueHandlers == null) {
__
//初始化ReturnValueHandlers
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
__}


RequestMappingHandlerAdapter#getDefaultArgumentResolvers对ArgumentResolvers进行初始化

RequestMappingHandlerAdapter#getDefaultReturnValueHandlers对ReturnValueHandlers进行初始化

参数解析实现类


1. RequestParamMethodArgumentResolver

支持带有@RequestParam注解的参数或带有MultipartFile类型的参数

2. RequestParamMapMethodArgumentResolver

支持带有@RequestParam注解的参数 && @RequestParam注解的属性value存在 && 参数类型是实现Map接口的属性

3. PathVariableMethodArgumentResolver

支持带有@PathVariable注解的参数 且如果参数实现了Map接口,@PathVariable注解需带有value属性

4. MatrixVariableMethodArgumentResolver

支持带有@MatrixVariable注解的参数 且如果参数实现了Map接口,@MatrixVariable注解需带有value属性

5. RequestResponseBodyMethodProcessor

本文已分析过

6. ServletRequestMethodArgumentResolver

参数类型是实现或继承或是WebRequest、ServletRequest、MultipartRequest、HttpSession、Principal、Locale、TimeZone、InputStream、Reader、HttpMethod这些类。

(这就是为何我们在Controller中的方法里添加一个HttpServletRequest参数,Spring会为我们自动获得HttpServletRequest对象的原因)

7. ServletResponseMethodArgumentResolver

参数类型是实现或继承或是ServletResponse、OutputStream、Writer这些类

8. RedirectAttributesMethodArgumentResolver

参数是实现了RedirectAttributes接口的类

9. HttpEntityMethodProcessor

参数类型是HttpEntity

返回值解析实现类

  1. ModelAndViewMethodReturnValueHandler

    返回值类型是ModelAndView或其子类

    2. ModelMethodProcessor

    返回值类型是Model或其子类

    3. ViewMethodReturnValueHandler

    返回值类型是View或其子类

    4. HttpHeadersReturnValueHandler

    返回值类型是HttpHeaders或其子类

    5. ModelAttributeMethodProcessor

    返回值有@ModelAttribute注解

    6. ViewNameMethodReturnValueHandler

    返回值是void或String

    @RequestBody解析


    @ResponseBody注解的话最终返回值会被RequestResponseBodyMethodProcessor这个HandlerMethodReturnValueHandler实现类处理.RequestResponseBodyMethodProcessor这个类其实同时实现了HandlerMethodReturnValueHandler和HandlerMethodArgumentResolver这两个接口。