Spring 源码学习(十三)—— RequestMappingHandlerAdapter
0. 概览
RequestMappingHandlerAdapter 类为 HandlerMethod 处理方法的适配器,用于对 HandlerMethod 处理请求的适配;
(1) 初始化流程
(2) 请求处理流程
1. HandlerAdapter 接口
HandlerAdapter 接口向外提供了三个方法,分别为是否支持指定处理器的 supports 方法,实际处理请求的 handle 方法以及获取上次修改时间的 getLastModified 方法。
public interface HandlerAdapter {boolean supports(Object handler);@NullableModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;long getLastModified(HttpServletRequest request, Object handler);}
2. WebContentGenerator 抽象类
WebContentGenerator 抽象类是 Spring MVC 中一个基础支持类,主要功能是为各种 Web 内容生成器(如控制器、拦截器)提供了一系列与 HTTP 响应和请求控制相关的通用功能,可以通过他管理缓存策略、控制会话行为以及校验请求方法。
2.1 变量
2.1.1 常量
WebContentGenerator 抽象类拥有 6 个常量,分别是三个用于请求方法控制的 METHOD_GET、METHOD_HEAD 及 METHOD_POST 与三个用于缓存控制的 HEADER_PRAGMA(http 1.0 版本用于告知缓存行为的请求头名称)、HEADER_EXPIRES(http 1.0 版本用于标识实际缓存过期时间的请求头名称) 及 HEADER_CACHE_CONTROL(服务端告知客户端缓存行为请求头名称);
public abstract class WebContentGenerator extends WebApplicationObjectSupport {public static final String METHOD_GET = "GET";public static final String METHOD_HEAD = "HEAD";public static final String METHOD_POST = "POST";private static final String HEADER_PRAGMA = "Pragma";private static final String HEADER_EXPIRES = "Expires";protected static final String HEADER_CACHE_CONTROL = "Cache-Control";
}
2.1.2 类变量
WebContentGenerator 抽象类虽拥有 10 个变量,但已有 4 个变量已弃用;
-
在用变量
WebContentGenerator 抽象类中拥有三个请求控制属性,supportedMethods 属性保存的是当前所支持的方法集合,而 allowHeader 属性则是基于 supportedMethods 属性生成的 allowHeader 响应头值(多个方法名称使用 ,号进行分隔),requireSession 属性则是控制请求是否必须与会话绑定;
public abstract class WebContentGenerator extends WebApplicationObjectSupport {@Nullableprivate Set<String> supportedMethods;@Nullableprivate String allowHeader;private boolean requireSession = false;@Nullableprotected String getAllowHeader() {return this.allowHeader;}public final void setRequireSession(boolean requireSession) {this.requireSession = requireSession;}public final boolean isRequireSession() {return this.requireSession;}
}
setSupportedMethods 方法在使用 methods 入参更新了 supportedMethods 属性之后通过 initAllowHeader 方法为 allowHeader 属性赋值,在 supportedMethods 属性为空时,直接将 allowHeader 属性更新为除 trace 之外的所有方法名拼接字符串,在 supportedMethods 属性中拥有 OPTIONS 方法名时,直接将 allowHeader 属性更新为 supportedMethods 属性中的所有方法名拼接字符串,否则会在 supportedMethods 属性中的所有方法名拼接字符串之后增加 OPTIONS 方法名。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {public final void setSupportedMethods(@Nullable String... methods) {if (!ObjectUtils.isEmpty(methods)) {this.supportedMethods = new LinkedHashSet<>(Arrays.asList(methods));}else {this.supportedMethods = null;}initAllowHeader();}private void initAllowHeader() {Collection<String> allowedMethods;if (this.supportedMethods == null) {allowedMethods = new ArrayList<>(HttpMethod.values().length - 1);for (HttpMethod method : HttpMethod.values()) {if (method != HttpMethod.TRACE) {allowedMethods.add(method.name());}}}else if (this.supportedMethods.contains(HttpMethod.OPTIONS.name())) {allowedMethods = this.supportedMethods;}else {allowedMethods = new ArrayList<>(this.supportedMethods);allowedMethods.add(HttpMethod.OPTIONS.name());}this.allowHeader = StringUtils.collectionToCommaDelimitedString(allowedMethods);}
}
WebContentGenerator 抽象类还有 3 个还在使用的缓存控制属性,其中 cacheControl 属性提供更精细的缓存控制,cacheSeconds 属性则是旧式用于设置缓存时间(-1: 不设置缓存头(默认);0: 禁止缓存 (Cache-Control: no-cache);>0: 缓存指定秒数 (Cache-Control: max-age=xxx))及标识缓存是否变化的请求头名称数组的 varyByRequestHeaders 属性。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {@Nullableprivate CacheControl cacheControl;private int cacheSeconds = -1;@Nullableprivate String[] varyByRequestHeaders;public final void setCacheControl(@Nullable CacheControl cacheControl) {this.cacheControl = cacheControl;}@Nullablepublic final CacheControl getCacheControl() {return this.cacheControl;}public final void setCacheSeconds(int seconds) {this.cacheSeconds = seconds;}public final int getCacheSeconds() {return this.cacheSeconds;}public final void setVaryByRequestHeaders(@Nullable String... varyByRequestHeaders) {this.varyByRequestHeaders = varyByRequestHeaders;}@Nullablepublic final String[] getVaryByRequestHeaders() {return this.varyByRequestHeaders;}
}
-
弃用变量
useExpiresHeader
表示是否生成 HTTP 1.0 的 Expires 过期时间
头部(Spring 4.2+ 默认false,不再自动生成Expires头),useCacheControlHeader
是否生成HTTP 1.1的 Cache-Control 响应
头,useCacheControlNoStore 表示是否在Cache-Control
中包含no-store
指令来禁止存储,alwaysMustRevalidate
表示是否在 Cache-Control
中包含 must-revalidate
指令来重新验证。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {private boolean useExpiresHeader = false;private boolean useCacheControlHeader = true;private boolean useCacheControlNoStore = true;private boolean alwaysMustRevalidate = false;@Deprecatedpublic final void setUseExpiresHeader(boolean useExpiresHeader) {this.useExpiresHeader = useExpiresHeader;}@Deprecatedpublic final boolean isUseExpiresHeader() {return this.useExpiresHeader;}@Deprecatedpublic final void setUseCacheControlHeader(boolean useCacheControlHeader) {this.useCacheControlHeader = useCacheControlHeader;}@Deprecatedpublic final boolean isUseCacheControlHeader() {return this.useCacheControlHeader;}@Deprecatedpublic final void setUseCacheControlNoStore(boolean useCacheControlNoStore) {this.useCacheControlNoStore = useCacheControlNoStore;}@Deprecatedpublic final boolean isUseCacheControlNoStore() {return this.useCacheControlNoStore;}@Deprecatedpublic final void setAlwaysMustRevalidate(boolean mustRevalidate) {this.alwaysMustRevalidate = mustRevalidate;}@Deprecatedpublic final boolean isAlwaysMustRevalidate() {return this.alwaysMustRevalidate;}
}
2.2 方法
2.2.1 构造方法
WebContentGenerator 拥有三个构造方法,其只做了两件事,第一个是为 supportedMethods 属性赋值,第二则是使用调用 initAllowHeader 方法使用使用 supportedMethods 属性值初始化 allowHeader 属性。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {public WebContentGenerator() {this(true);}public WebContentGenerator(boolean restrictDefaultSupportedMethods) {if (restrictDefaultSupportedMethods) {this.supportedMethods = new LinkedHashSet<>(4);this.supportedMethods.add(METHOD_GET);this.supportedMethods.add(METHOD_HEAD);this.supportedMethods.add(METHOD_POST);}initAllowHeader();}public WebContentGenerator(String... supportedMethods) {setSupportedMethods(supportedMethods);}
}
2.2.2 checkRequest 方法
checkRequest 方法用于请求合法性验证,其第一步验证了是否为支持的方法,主要是通过 supportedMethods 是否为空且不为空时是否保存请求方法进行判断,第二步进行的是会话验证,在 requireSession 为 true 时验证请求是否拥有会话;
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void checkRequest(HttpServletRequest request) throws ServletException {// Check whether we should support the request method.String method = request.getMethod();if (this.supportedMethods != null && !this.supportedMethods.contains(method)) {throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods);}// Check whether a session is required.if (this.requireSession && request.getSession(false) == null) {throw new HttpSessionRequiredException("Pre-existing session required but none found");}}
}
2.2.3 prepareResponse 方法
prepareResponse 方法响应缓存控制的设置,cacheControl 属性拥有最高的缓存控制优先级,即该属性不为空时直接利用该属性执行 applyCacheControl 方法设置缓存控制响应头,否则调用 applyCacheSeconds 方法设置;最后利用 varyByRequestHeaders 属性对 Vary 响应头进行扩展。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void prepareResponse(HttpServletResponse response) {if (this.cacheControl != null) {applyCacheControl(response, this.cacheControl);}else {applyCacheSeconds(response, this.cacheSeconds);}if (this.varyByRequestHeaders != null) {for (String value : getVaryRequestHeadersToAdd(response, this.varyByRequestHeaders)) {response.addHeader("Vary", value);}}}
}
applyCacheControl 方法首先调用 cacheControl 参数的 getHeaderValue 方法获取 Cache-Control 响应头值,在其不为空时,将 response 响应的 Cache-Control 响应头值设置为该值并将 HEADER_PRAGMA 与 HEADER_EXPIRES 响应头值重置为空。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void applyCacheControl(HttpServletResponse response, CacheControl cacheControl) {String ccValue = cacheControl.getHeaderValue();if (ccValue != null) {// Set computed HTTP 1.1 Cache-Control headerresponse.setHeader(HEADER_CACHE_CONTROL, ccValue);if (response.containsHeader(HEADER_PRAGMA)) {// Reset HTTP 1.0 Pragma header if presentresponse.setHeader(HEADER_PRAGMA, "");}if (response.containsHeader(HEADER_EXPIRES)) {// Reset HTTP 1.0 Expires header if presentresponse.setHeader(HEADER_EXPIRES, "");}}}
}
applyCacheSeconds 方法在 useExpiresHeader 属性为 true 或 useCacheControlHeader 属性为 false 即当前使用的是 http 1.0 时,根据 cacheSeconds 参数值设置缓存配置;在其大于 0 时,调用 cacheForSeconds 进行设置,在其为 0 时调用 preventCaching 方法进行设置。在使用 http 1.1 时,根据 cacheSeconds 参数创建不同的 CacheControl 对象,然后调用 applyCacheControl 方法设置缓存控制器;在 cacheSeconds 大于 0 时,首先设置 CacheControl 对象的 maxAge,在 alwaysMustRevalidate 为 true 时,更新 CacheControl 的 mustRevalidate 属性值为 true,在其等于 0 时,根据 useCacheControlNoStore 值设置 noStore 还是 noCache,小于 0 则使用空缓存控制器。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void applyCacheSeconds(HttpServletResponse response, int cacheSeconds) {if (this.useExpiresHeader || !this.useCacheControlHeader) {// Deprecated HTTP 1.0 cache behavior, as in previous Spring versionsif (cacheSeconds > 0) {cacheForSeconds(response, cacheSeconds);}else if (cacheSeconds == 0) {preventCaching(response);}}else {CacheControl cControl;if (cacheSeconds > 0) {cControl = CacheControl.maxAge(cacheSeconds, TimeUnit.SECONDS);if (this.alwaysMustRevalidate) {cControl = cControl.mustRevalidate();}}else if (cacheSeconds == 0) {cControl = (this.useCacheControlNoStore ? CacheControl.noStore() : CacheControl.noCache());}else {cControl = CacheControl.empty();}applyCacheControl(response, cControl);}}
}
cacheForSeconds 方法在 useExpiresHeader 属性为 true 时,设置 HEADER_EXPIRES 过期时间响应头值,否则重置 response 的 HEADER_EXPIRES 响应头值;在 useCacheControlHeader 属性为 true 时,则会设置 HEADER_CACHE_CONTROL 响应头值;最后将 response 的 HEADER_PRAGMA 响应头重置为空。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void cacheForSeconds(HttpServletResponse response, int seconds) {cacheForSeconds(response, seconds, false);}protected final void cacheForSeconds(HttpServletResponse response, int seconds, boolean mustRevalidate) {if (this.useExpiresHeader) {// HTTP 1.0 headerresponse.setDateHeader(HEADER_EXPIRES, System.currentTimeMillis() + seconds * 1000L);}else if (response.containsHeader(HEADER_EXPIRES)) {// Reset HTTP 1.0 Expires header if presentresponse.setHeader(HEADER_EXPIRES, "");}if (this.useCacheControlHeader) {// HTTP 1.1 headerString headerValue = "max-age=" + seconds;if (mustRevalidate || this.alwaysMustRevalidate) {headerValue += ", must-revalidate";}response.setHeader(HEADER_CACHE_CONTROL, headerValue);}if (response.containsHeader(HEADER_PRAGMA)) {// Reset HTTP 1.0 Pragma header if presentresponse.setHeader(HEADER_PRAGMA, "");}}
}
preventCaching 方法首先设置 HEADER_PRAGMA 响应头值为 no-cache;在 useExpiresHeader 为 true 时,将 HEADER_EXPIRES 响应头设置为 1;useCacheControlHeader 为 true 时,将 HEADER_CACHE_CONTROL 响应头设置为 no-cache 值,在 useCacheControlNoStore 为 true 时向 HEADER_CACHE_CONTROL 响应头中追加 no-store 值。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {protected final void preventCaching(HttpServletResponse response) {response.setHeader(HEADER_PRAGMA, "no-cache");if (this.useExpiresHeader) {// HTTP 1.0 Expires headerresponse.setDateHeader(HEADER_EXPIRES, 1L);}if (this.useCacheControlHeader) {// HTTP 1.1 Cache-Control header: "no-cache" is the standard value,// "no-store" is necessary to prevent caching on Firefox.response.setHeader(HEADER_CACHE_CONTROL, "no-cache");if (this.useCacheControlNoStore) {response.addHeader(HEADER_CACHE_CONTROL, "no-store");}}}
}
getVaryRequestHeadersToAdd 方法用于获取需要扩展的 vary 响应头值。在 response 中没有 VARY 头时直接返回 varyByRequestHeaders 参数值,否则返回 varyByRequestHeaders 参数与 VARY 头的相斥部分。
public abstract class WebContentGenerator extends WebApplicationObjectSupport {private Collection<String> getVaryRequestHeadersToAdd(HttpServletResponse response, String[] varyByRequestHeaders) {if (!response.containsHeader(HttpHeaders.VARY)) {return Arrays.asList(varyByRequestHeaders);}Collection<String> result = new ArrayList<>(varyByRequestHeaders.length);Collections.addAll(result, varyByRequestHeaders);for (String header : response.getHeaders(HttpHeaders.VARY)) {for (String existing : StringUtils.tokenizeToStringArray(header, ",")) {if ("*".equals(existing)) {return Collections.emptyList();}for (String value : varyByRequestHeaders) {if (value.equalsIgnoreCase(existing)) {result.remove(value);}}}}return result;}
}
3. AbstractHandlerMethodAdapter 抽象类
3.1 变量
3.1.1 类变量
AbstractHandlerMethodAdapter 抽象类只有一个用于标识当前顺序的 order 变量,其默认值为 Ordered.LOWEST_PRECEDENCE 表明默认情况下该适配器在最后执行;
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {private int order = Ordered.LOWEST_PRECEDENCE;public void setOrder(int order) {this.order = order;}@Overridepublic int getOrder() {return this.order;}
}
3.2 方法
3.2.1 构造方法
AbstractHandlerMethodAdapter 抽象类只有一个无参构造方法,其直接使用 false 调用 WebContentGenerator 的单参数构造方法创建 AbstractHandlerMethodAdapter 对象。
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {public AbstractHandlerMethodAdapter() {// no restriction of HTTP methods by defaultsuper(false);}
}
3.2.2 supports 方法
supports 方法返回 handler 参数是否为 HandlerMethod 对象且 supportsInternal 执行结果是否为真。
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {@Overridepublic final boolean supports(Object handler) {return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));}protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
}
3.2.3 handle 方法
handle 方法直接将 handler 参数转换为 HandlerMethod 对象后执行 handleInternal 方法并返回。
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {@Override@Nullablepublic final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return handleInternal(request, response, (HandlerMethod) handler);}@Nullableprotected abstract ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
}
3.2.4 getLastModified 方法
getLastModified 方法直接将 handler 参数转换为 HandlerMethod 对象后执行 getLastModifiedInternal 方法并返回。
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {@Overridepublic final long getLastModified(HttpServletRequest request, Object handler) {return getLastModifiedInternal(request, (HandlerMethod) handler);}protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
}
4. RequestMappingHandlerAdapter 抽象类
4.1 变量
4.1.1 常量
RequestMappingHandlerAdapter 类只有两个常量,分别为 INIT_BINDER_METHODS InitBinder 方法过滤器与 MODEL_ATTRIBUTE_METHODS ModelAttribute 方法过滤器。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {public static final MethodFilter INIT_BINDER_METHODS = method ->AnnotatedElementUtils.hasAnnotation(method, InitBinder.class);public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method ->(!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) &&AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class));
}
4.1.2 类变量
-
参数解析器
RequestMappingHandlerAdapter 类拥有 3 个参数解析器,分别为通用方法参数解析器列表 customArgumentResolvers,方法参数解析器 argumentResolvers 及 initBinder 方法参数解析器 initBinderArgumentResolvers;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Nullableprivate List<HandlerMethodArgumentResolver> customArgumentResolvers;@Nullableprivate HandlerMethodArgumentResolverComposite argumentResolvers;@Nullableprivate HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;public void setCustomArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {this.customArgumentResolvers = argumentResolvers;}@Nullablepublic List<HandlerMethodArgumentResolver> getCustomArgumentResolvers() {return this.customArgumentResolvers;}public void setArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {if (argumentResolvers == null) {this.argumentResolvers = null;}else {this.argumentResolvers = new HandlerMethodArgumentResolverComposite();this.argumentResolvers.addResolvers(argumentResolvers);}}@Nullablepublic List<HandlerMethodArgumentResolver> getArgumentResolvers() {return (this.argumentResolvers != null ? this.argumentResolvers.getResolvers() : null);}public void setInitBinderArgumentResolvers(@Nullable List<HandlerMethodArgumentResolver> argumentResolvers) {if (argumentResolvers == null) {this.initBinderArgumentResolvers = null;}else {this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite();this.initBinderArgumentResolvers.addResolvers(argumentResolvers);}}@Nullablepublic List<HandlerMethodArgumentResolver> getInitBinderArgumentResolvers() {return (this.initBinderArgumentResolvers != null ? this.initBinderArgumentResolvers.getResolvers() : null);}
}
-
返参处理器
RequestMappingHandlerAdapter 类拥有通用返参处理器器列表 customReturnValueHandlers 与返参处理器 returnValueHandlers;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Nullableprivate List<HandlerMethodReturnValueHandler> customReturnValueHandlers;@Nullableprivate HandlerMethodReturnValueHandlerComposite returnValueHandlers;public void setCustomReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) {this.customReturnValueHandlers = returnValueHandlers;}@Nullablepublic List<HandlerMethodReturnValueHandler> getCustomReturnValueHandlers() {return this.customReturnValueHandlers;}public void setReturnValueHandlers(@Nullable List<HandlerMethodReturnValueHandler> returnValueHandlers) {if (returnValueHandlers == null) {this.returnValueHandlers = null;}else {this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();this.returnValueHandlers.addHandlers(returnValueHandlers);}}@Nullablepublic List<HandlerMethodReturnValueHandler> getReturnValueHandlers() {return (this.returnValueHandlers != null ? this.returnValueHandlers.getHandlers() : null);}
}
- 请求响应处理
RequestMappingHandlerAdapter 类的 modelAndViewResolvers 用于模型视图解析,contentNegotiationManager 属性为内容协商器,messageConverters 属性为使用的消息转换器列表及 requestResponseBodyAdvice 属性则是当前所使用的请求响应体处理切面对象列表。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Nullableprivate List<ModelAndViewResolver> modelAndViewResolvers;private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager();private List<HttpMessageConverter<?>> messageConverters;private final List<Object> requestResponseBodyAdvice = new ArrayList<>();@Nullableprivate WebBindingInitializer webBindingInitializer;
}
-
异步请求处理
RequestMappingHandlerAdapter 类中与请求异步处理相关的属性有 4 个,分别为异步请求处理器 taskExecutor、异步执行超时时间 asyncRequestTimeout、异步处理回调拦截器数组 callableInterceptors 及 DeferredResult 结果处理拦截器数组 deferredResultInterceptors;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync");@Nullableprivate Long asyncRequestTimeout;private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0];private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0];public void setTaskExecutor(AsyncTaskExecutor taskExecutor) {this.taskExecutor = taskExecutor;}public void setAsyncRequestTimeout(long timeout) {this.asyncRequestTimeout = timeout;}public void setCallableInterceptors(List<CallableProcessingInterceptor> interceptors) {this.callableInterceptors = interceptors.toArray(new CallableProcessingInterceptor[0]);}public void setDeferredResultInterceptors(List<DeferredResultProcessingInterceptor> interceptors) {this.deferredResultInterceptors = interceptors.toArray(new DeferredResultProcessingInterceptor[0]);}
}
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();private boolean ignoreDefaultModelOnRedirect = false;
}
-
会话管理
RequestMappingHandlerAdapter 类拥有三个会话控制相关属性,分别为 SessionAttribute 存在时,客户端缓存失效时间 cacheSecondsForSessionAttributeHandlers、是否同步处理同一会话请求的 synchronizeOnSession 标识及 SessionAttribute 会话参数存储器对象 sessionAttributeStore;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private int cacheSecondsForSessionAttributeHandlers = 0;private boolean synchronizeOnSession = false;private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {this.sessionAttributeStore = sessionAttributeStore;}public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) {this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers;}public void setSynchronizeOnSession(boolean synchronizeOnSession) {this.synchronizeOnSession = synchronizeOnSession;}
}
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();@Nullableprivate ConfigurableBeanFactory beanFactory;
}
-
缓存
RequestMappingHandlerAdapter 类拥有五个本地缓存 Map,分别为处理器类型与 SessionAttributesHandler 处理器映射缓存 sessionAttributesHandlerCache、处理器类型与处理器 initBinder 方法集合映射缓存 initBinderCache、ControllerAdvice 对象与 initBinder 方法集合映射缓存 initBinderAdviceCache、处理器类型与处理器 ModelAttribute 方法集合映射缓存 modelAttributeCache、ControllerAdvice 对象与 ModelAttribute 方法集合映射缓存 modelAttributeAdviceCache;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64);private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64);private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>();private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64);private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>();
}
4.2 方法
4.2.1 构造方法
RequestMappingHandlerAdapter 类只有一个无参构造方法,其只做了一件事情,向 messageConverters 属性中添加 ByteArrayHttpMessageConverter、StringHttpMessageConverter、SourceHttpMessageConverter 及 AllEncompassingFormHttpMessageConverter 四个默认消息转换器。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {public RequestMappingHandlerAdapter() {this.messageConverters = new ArrayList<>(4);this.messageConverters.add(new ByteArrayHttpMessageConverter());this.messageConverters.add(new StringHttpMessageConverter());try {this.messageConverters.add(new SourceHttpMessageConverter<>());}catch (Error err) {// Ignore when no TransformerFactory implementation is available}this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());}
}
4.2.2 afterPropertiesSet 方法
afterPropertiesSet 方法用于 RequestMappingHandlerAdapter 对象参数设置完的初始化;其首先调用 initControllerAdviceCache 方法初始化 ControllerAdvice 修饰的对象缓存;在 argumentResolvers 参数为空时,将
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Overridepublic void afterPropertiesSet() {// Do this first, it may add ResponseBody advice beansinitControllerAdviceCache();if (this.argumentResolvers == null) {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) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}}
}
initControllerAdviceCache 方法首先调用 ControllerAdviceBean 类的 findAnnotatedBeans 方法获取上下文中使用 ControllerAdvice 注解修饰的所有对象,并将对象与其中使用 InitBinder 修饰的方法集合映射保存到 initBinderAdviceCache 属性,对象与使用 ModelAttribute 且未使用 RequestMapping 修饰的方法集合映射保存到 modelAttributeAdviceCache 属性,将其中所有的 RequestBodyAdvice 或 ResponseBodyAdvice 的子类对象集合保存到 requestResponseBodyAdvice 属性之中。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private void initControllerAdviceCache() {if (getApplicationContext() == null) {return;}List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());List<Object> requestResponseBodyAdviceBeans = new ArrayList<>();for (ControllerAdviceBean adviceBean : adviceBeans) {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()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}if (logger.isDebugEnabled()) {int modelSize = this.modelAttributeAdviceCache.size();int binderSize = this.initBinderAdviceCache.size();int reqCount = getBodyAdviceCount(RequestBodyAdvice.class);int resCount = getBodyAdviceCount(ResponseBodyAdvice.class);if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) {logger.debug("ControllerAdvice beans: none");}else {logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize +" @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice");}}}
}
getDefaultArgumentResolvers 方法用于获取默认参数解析器;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);// Annotation-based argument resolutionresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));resolvers.add(new RequestParamMapMethodArgumentResolver());resolvers.add(new PathVariableMethodArgumentResolver());resolvers.add(new PathVariableMapMethodArgumentResolver());resolvers.add(new MatrixVariableMethodArgumentResolver());resolvers.add(new MatrixVariableMapMethodArgumentResolver());resolvers.add(new ServletModelAttributeMethodProcessor(false));resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));resolvers.add(new RequestHeaderMapMethodArgumentResolver());resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new SessionAttributeMethodArgumentResolver());resolvers.add(new RequestAttributeMethodArgumentResolver());// Type-based argument resolutionresolvers.add(new ServletRequestMethodArgumentResolver());resolvers.add(new ServletResponseMethodArgumentResolver());resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RedirectAttributesMethodArgumentResolver());resolvers.add(new ModelMethodProcessor());resolvers.add(new MapMethodProcessor());resolvers.add(new ErrorsMethodArgumentResolver());resolvers.add(new SessionStatusMethodArgumentResolver());resolvers.add(new UriComponentsBuilderMethodArgumentResolver());// Custom argumentsif (getCustomArgumentResolvers() != null) {resolvers.addAll(getCustomArgumentResolvers());}// Catch-allresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));resolvers.add(new ServletModelAttributeMethodProcessor(true));return resolvers;}
}
getDefaultInitBinderArgumentResolvers 方法用于获取默认 InitBinder 方法参数解析器;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() {List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(20);// Annotation-based argument resolutionresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));resolvers.add(new RequestParamMapMethodArgumentResolver());resolvers.add(new PathVariableMethodArgumentResolver());resolvers.add(new PathVariableMapMethodArgumentResolver());resolvers.add(new MatrixVariableMethodArgumentResolver());resolvers.add(new MatrixVariableMapMethodArgumentResolver());resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new SessionAttributeMethodArgumentResolver());resolvers.add(new RequestAttributeMethodArgumentResolver());// Type-based argument resolutionresolvers.add(new ServletRequestMethodArgumentResolver());resolvers.add(new ServletResponseMethodArgumentResolver());// Custom argumentsif (getCustomArgumentResolvers() != null) {resolvers.addAll(getCustomArgumentResolvers());}// Catch-allresolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));return resolvers;}
}
getDefaultReturnValueHandlers 方法则是用于获取默认方法返回参数处理器;
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);// Single-purpose return value typeshandlers.add(new ModelAndViewMethodReturnValueHandler());handlers.add(new ModelMethodProcessor());handlers.add(new ViewMethodReturnValueHandler());handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager));handlers.add(new StreamingResponseBodyReturnValueHandler());handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));handlers.add(new HttpHeadersReturnValueHandler());handlers.add(new CallableMethodReturnValueHandler());handlers.add(new DeferredResultMethodReturnValueHandler());handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));// Annotation-based return value typeshandlers.add(new ModelAttributeMethodProcessor(false));handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),this.contentNegotiationManager, this.requestResponseBodyAdvice));// Multi-purpose return value typeshandlers.add(new ViewNameMethodReturnValueHandler());handlers.add(new MapMethodProcessor());// Custom return value typesif (getCustomReturnValueHandlers() != null) {handlers.addAll(getCustomReturnValueHandlers());}// Catch-allif (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));}else {handlers.add(new ModelAttributeMethodProcessor(true));}return handlers;}
}
4.2.3 supportsInternal 方法
supportsInternal 方法直接返回 true。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Overrideprotected boolean supportsInternal(HandlerMethod handlerMethod) {return true;}
}
4.2.4 getLastModifiedInternal 方法
getLastModifiedInternal 方法直接返回 -1,表示从不使用缓存。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Overrideprotected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) {return -1;}
}
4.2.5 handleInternal 方法
handleInternal 方法首先调用 checkRequest 方法对请求方法与 session 会话进行验证;在 synchronizeOnSession 属性为 true 且能够获取到当前请求会话时,针对会话加锁然后执行 invokeHandlerMethod 方法,否则直接执行 invokeHandlerMethod 方法;之后在响应中不包含 HEADER_CACHE_CONTROL 头时,判断 handlerMethod 方法对象是否存在对应的 SessionAttributes 会话属性值,存在则会调用 applyCacheSeconds 将 response 响应的缓存控制参数设置为 cacheSecondsForSessionAttributeHandlers 属性值,不存在则直接调用 prepareResponse 方法处理响应的缓存控制相关头。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Overrideprotected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ModelAndView mav;checkRequest(request);// Execute invokeHandlerMethod in synchronized block if required.if (this.synchronizeOnSession) {HttpSession session = request.getSession(false);if (session != null) {Object mutex = WebUtils.getSessionMutex(session);synchronized (mutex) {mav = invokeHandlerMethod(request, response, handlerMethod);}}else {// No HttpSession available -> no mutex necessarymav = invokeHandlerMethod(request, response, handlerMethod);}}else {// No synchronization on session demanded at all...mav = invokeHandlerMethod(request, response, handlerMethod);}if (!response.containsHeader(HEADER_CACHE_CONTROL)) {if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);}else {prepareResponse(response);}}return mav;}private SessionAttributesHandler getSessionAttributesHandler(HandlerMethod handlerMethod) {return this.sessionAttributesHandlerCache.computeIfAbsent(handlerMethod.getBeanType(),type -> new SessionAttributesHandler(type, this.sessionAttributeStore));}
}
invokeHandlerMethod 方法首先创建 ServletWebRequest、WebDataBinderFactory、ModelFactory 及 ServletInvocableHandlerMethod 对象;之后依次为 ServletInvocableHandlerMethod 对象设置 argumentResolvers 参数解析器集合、returnValueHandlers 返回值处理器集合、binderFactory 数据绑定工厂及 parameterNameDiscoverer 参数名查询器;随后创建 ModelAndViewContainer 对象并向模型中添加请求的 INPUT_FLASH_MAP_ATTRIBUTE 属性,随后调用 modelFactory 的 initModel 方法对 mav 中的模型进行初始化,最后设置 ignoreDefaultModelOnRedirect 重定向忽略默认模型属性;随后获取并配置 WebAsyncManager 异步执行管理器,若异步任务已执行完成,通过 asyncManager 的 getConcurrentResult 方法获取异步执行结果并调用 getConcurrentResultContext 方法更新 mavContainer 模型视图对象与 clearConcurrentResult 方法清理异步执行结果,最后调用 invocableMethod 的 wrapConcurrentResult 方法封装异步执行结果来使不直接执行方法而是直接返回异步执行结果;之后调用 invocableMethod 的 invokeAndHandle 方法执行方法并处理返回结果;最后若异步任务已开始执行直接返回 null,否则调用 getModelAndView 方法获取执行结果模型与视图并返回。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Nullableprotected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest = new ServletWebRequest(request, response);try {WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) {invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers != null) {invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}invocableMethod.setDataBinderFactory(binderFactory);invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);ModelAndViewContainer mavContainer = new ModelAndViewContainer();mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));modelFactory.initModel(webRequest, mavContainer, invocableMethod);mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);asyncWebRequest.setTimeout(this.asyncRequestTimeout);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.setTaskExecutor(this.taskExecutor);asyncManager.setAsyncWebRequest(asyncWebRequest);asyncManager.registerCallableInterceptors(this.callableInterceptors);asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);if (asyncManager.hasConcurrentResult()) {Object result = asyncManager.getConcurrentResult();mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];asyncManager.clearConcurrentResult();LogFormatUtils.traceDebug(logger, traceOn -> {String formatted = LogFormatUtils.formatValue(result, !traceOn);return "Resume with async result [" + formatted + "]";});invocableMethod = invocableMethod.wrapConcurrentResult(result);}invocableMethod.invokeAndHandle(webRequest, mavContainer);if (asyncManager.isConcurrentHandlingStarted()) {return null;}return getModelAndView(mavContainer, modelFactory, webRequest);}finally {webRequest.requestCompleted();}}
}
getDataBinderFactory 方法首先获取 handlerMethod 所属对象的 initBinder 方法集合;随后调用 createInitBinderMethod 方法依次将 initBinderAdviceCache 缓存与当前类中的 initBinder 方法封装成 InvocableHandlerMethod 对象并保存至 initBinderMethods 集合之中,最后调用 createDataBinderFactory 方法创建 ServletRequestDataBinderFactory 对象并返回。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {Class<?> handlerType = handlerMethod.getBeanType();Set<Method> methods = this.initBinderCache.get(handlerType);if (methods == null) {methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);this.initBinderCache.put(handlerType, methods);}List<InvocableHandlerMethod> initBinderMethods = new ArrayList<>();// Global methods firstthis.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {Object bean = controllerAdviceBean.resolveBean();for (Method method : methodSet) {initBinderMethods.add(createInitBinderMethod(bean, method));}}});for (Method method : methods) {Object bean = handlerMethod.getBean();initBinderMethods.add(createInitBinderMethod(bean, method));}return createDataBinderFactory(initBinderMethods);}private InvocableHandlerMethod createInitBinderMethod(Object bean, Method method) {InvocableHandlerMethod binderMethod = new InvocableHandlerMethod(bean, method);if (this.initBinderArgumentResolvers != null) {binderMethod.setHandlerMethodArgumentResolvers(this.initBinderArgumentResolvers);}binderMethod.setDataBinderFactory(new DefaultDataBinderFactory(this.webBindingInitializer));binderMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);return binderMethod;}protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> binderMethods)throws Exception {return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());}protected ServletInvocableHandlerMethod createInvocableHandlerMethod(HandlerMethod handlerMethod) {return new ServletInvocableHandlerMethod(handlerMethod);}
}
getModelFactory 方法首先获取 handlerMethod 所属对象的 ModelAttribute 方法集合;随后调用 createModelAttributeMethod 方法依次将 modelAttributeAdviceCache 缓存与当前类中的 ModelAttribute 方法封装成 InvocableHandlerMethod 对象并保存至 attrMethods 集合之中,最后创建 ModelFactory 对象并返回。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);Class<?> handlerType = handlerMethod.getBeanType();Set<Method> methods = this.modelAttributeCache.get(handlerType);if (methods == null) {methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);this.modelAttributeCache.put(handlerType, methods);}List<InvocableHandlerMethod> attrMethods = new ArrayList<>();// Global methods firstthis.modelAttributeAdviceCache.forEach((controllerAdviceBean, methodSet) -> {if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {Object bean = controllerAdviceBean.resolveBean();for (Method method : methodSet) {attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));}}});for (Method method : methods) {Object bean = handlerMethod.getBean();attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));}return new ModelFactory(attrMethods, binderFactory, sessionAttrHandler);}private InvocableHandlerMethod createModelAttributeMethod(WebDataBinderFactory factory, Object bean, Method method) {InvocableHandlerMethod attrMethod = new InvocableHandlerMethod(bean, method);if (this.argumentResolvers != null) {attrMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}attrMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);attrMethod.setDataBinderFactory(factory);return attrMethod;}
}
getModelAndView 方法首先调用 modelFactory 更新 mavContainer 模型,随后通过 mavContainer 的 isRequestHandled 方法判断请求已被处理,已处理时直接返回 null;随后使用 mavContainer 的视图名称、模型对象及状态创建 ModelAndView 对象,在使用的不是模型引用时还需要设置模型对象,最后在模型为 RedirectAttributes 重定向参数时,将其绑定到请求的 OUTPUT_FLASH_MAP_ATTRIBUTE 参数中去;最后返回创建的 ModelAndView 对象。
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Nullableprivate ModelAndView getModelAndView(ModelAndViewContainer mavContainer,ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {modelFactory.updateModel(webRequest, mavContainer);if (mavContainer.isRequestHandled()) {return null;}ModelMap model = mavContainer.getModel();ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus());if (!mavContainer.isViewReference()) {mav.setView((View) mavContainer.getView());}if (model instanceof RedirectAttributes) {Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);if (request != null) {RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);}}return mav;}
}
5. ServletInvocableHandlerMethod 类
5.1 InvocableHandlerMethod 类
5.1.1 变量
InvocableHandlerMethod 类拥有 1 个常量与 3 个类变量,分别为空方法参数数组 EMPTY_ARGS、复合方法参数解析器 resolvers、方法参数名查询器 parameterNameDiscoverer 与参数绑定工厂 dataBinderFactory。
public class InvocableHandlerMethod extends HandlerMethod {private static final Object[] EMPTY_ARGS = new Object[0];private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();@Nullableprivate WebDataBinderFactory dataBinderFactory;public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {this.resolvers = argumentResolvers;}public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {this.parameterNameDiscoverer = parameterNameDiscoverer;}public void setDataBinderFactory(WebDataBinderFactory dataBinderFactory) {this.dataBinderFactory = dataBinderFactory;}
}
5.1.2 构造方法
InvocableHandlerMethod 拥有三个构造方法,都是直接调用 HandlerMethod 父类的对应构造方法,在 Spring 源码学习(十二)—— RequestMappingHandlerMapping 中已介绍过 HandlerMethod,这里就不重新介绍了。
public class InvocableHandlerMethod extends HandlerMethod {public InvocableHandlerMethod(HandlerMethod handlerMethod) {super(handlerMethod);}public InvocableHandlerMethod(Object bean, Method method) {super(bean, method);}public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)throws NoSuchMethodException {super(bean, methodName, parameterTypes);}
}
5.1.3 invokeForRequest 方法
invokeForRequest 方法第一步通过 getMethodArgumentValues 方法获取方法的实参数组,随后使用获取到的实参调用 doInvoke 方法实际执行方法并返回。
public class InvocableHandlerMethod extends HandlerMethod {@Nullablepublic Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);if (logger.isTraceEnabled()) {logger.trace("Arguments: " + Arrays.toString(args));}return doInvoke(args);}
}
getMethodArgumentValues 方法用于获取方法参数值,其首先通过 getMethodParameters 方法获取方法行参数组,在其为空时直接返回 EMPTY_ARGS 常量值;否则对行参列表进行遍历,首先尝试通过 findProvidedArgument 方法从 providedArgs 参数中获取参数值;未获取到才会通过 resolvers 解析器去解析获取参数值。
public class InvocableHandlerMethod extends HandlerMethod {@Nullableprotected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {MethodParameter[] parameters = getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;}Object[] args = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {MethodParameter parameter = parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] != null) {continue;}if (!this.resolvers.supportsParameter(parameter)) {throw new IllegalStateException(formatArgumentError(parameter, "No suitable resolver"));}try {args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);}catch (Exception ex) {// Leave stack trace for later, exception may actually be resolved and handled...if (logger.isDebugEnabled()) {String exMsg = ex.getMessage();if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {logger.debug(formatArgumentError(parameter, exMsg));}}throw ex;}}return args;}
}
doInvoke 方法直接调用 ReflectionUtils 的 makeAccessible 方法将当前桥接方法置为可访问,然后使用当前对象与传入参数执行桥接方法并返回。
public class InvocableHandlerMethod extends HandlerMethod {@Nullableprotected Object doInvoke(Object... args) throws Exception {ReflectionUtils.makeAccessible(getBridgedMethod());try {return getBridgedMethod().invoke(getBean(), args);}catch (IllegalArgumentException ex) {assertTargetBean(getBridgedMethod(), getBean(), args);String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");throw new IllegalStateException(formatInvokeError(text, args), ex);}catch (InvocationTargetException ex) {// Unwrap for HandlerExceptionResolvers ...Throwable targetException = ex.getTargetException();if (targetException instanceof RuntimeException) {throw (RuntimeException) targetException;}else if (targetException instanceof Error) {throw (Error) targetException;}else if (targetException instanceof Exception) {throw (Exception) targetException;}else {throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);}}}
}
5.2 变量
ServletInvocableHandlerMethod 类只有一个常量与一个变量,分别为保存 Callable 类的 call 方法的 CALLABLE_METHOD 常量与 HandlerMethodReturnValueHandlerComposite 复合返回值处理器 returnValueHandlers 属性。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private static final Method CALLABLE_METHOD = ClassUtils.getMethod(Callable.class, "call");@Nullableprivate HandlerMethodReturnValueHandlerComposite returnValueHandlers;public void setHandlerMethodReturnValueHandlers(HandlerMethodReturnValueHandlerComposite returnValueHandlers) {this.returnValueHandlers = returnValueHandlers;}
}
5.3 方法
5.3.1 构造方法
ServletInvocableHandlerMethod 类只有两个构造方法,也是直接调用父类的构造方法,因此也不做过多介绍。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {public ServletInvocableHandlerMethod(Object handler, Method method) {super(handler, method);}public ServletInvocableHandlerMethod(HandlerMethod handlerMethod) {super(handlerMethod);}
}
5.3.2 invokeAndHandle 方法
invokeAndHandle 方法首先调用 invokeForRequest 方法执行实际处理方法并将返回值保存到 returnValue 变量之中;随后调用 setResponseStatus 方法为 webRequest 设置响应状态;随后判断是否没有返回值,若没有返回值但请求未修改、responseStatus 不为空或已被处理则会调用 mavContainer 标识为已处理并返回,存在返回值但错误原因不为空时也会直接调用 mavContainer 标识为已处理并返回;在其他情况下会将 mavContainer 标记为未处理,并调用 returnValueHandlers 返回值处理器的 handleReturnValue 方法对返回结果进行处理并返回。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {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()) {disableContentCachingIfNecessary(webRequest);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;}}private boolean isRequestNotModified(ServletWebRequest webRequest) {return webRequest.isNotModified();}private void disableContentCachingIfNecessary(ServletWebRequest webRequest) {if (isRequestNotModified(webRequest)) {HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);Assert.notNull(response, "Expected HttpServletResponse");if (StringUtils.hasText(response.getHeader(HttpHeaders.ETAG))) {HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);Assert.notNull(request, "Expected HttpServletRequest");}}}
}
setResponseStatus 方法首先调用 getResponseStatus 方法获取当前方法的 HttpStatus 状态值,在其为空时直接返回;随后为响应设置状态值与错误原因(设置了错误原因会导致请求提前返回),最后将响应状态绑定到请求的 RESPONSE_STATUS_ATTRIBUTE 属性上。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private void setResponseStatus(ServletWebRequest webRequest) throws IOException {HttpStatus status = getResponseStatus();if (status == null) {return;}HttpServletResponse response = webRequest.getResponse();if (response != null) {String reason = getResponseStatusReason();if (StringUtils.hasText(reason)) {response.sendError(status.value(), reason);}else {response.setStatus(status.value());}}// To be picked up by RedirectViewwebRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, status);}
}
5.3.3 wrapConcurrentResult 方法
wrapConcurrentResult 方法用于封装异步请求结果;其使用 ConcurrentResultHandlerMethod 内部类对 result 返参进行封装。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {ServletInvocableHandlerMethod wrapConcurrentResult(Object result) {return new ConcurrentResultHandlerMethod(result, new ConcurrentResultMethodParameter(result));}
}
5.4 内部类
5.4.1 ConcurrentResultHandlerMethod 内部类
- 扩展参数
ConcurrentResultHandlerMethod 类只扩展了一个用于保存返参类型的 returnType 参数。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {private final MethodParameter returnType;@Overridepublic MethodParameter getReturnValueType(@Nullable Object returnValue) {return this.returnType;}}
}
-
构造方法
ConcurrentResultHandlerMethod 内部类继承自 ServletInvocableHandlerMethod 类,其构造方法直接使用实现了直接返回 result 对象的 Callable 对象作为 handler 处理器与 CALLABLE_METHOD 常量值执行父类对应构造方法;随后依次设置返参处理器与返参类型。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {public ConcurrentResultHandlerMethod(final Object result, ConcurrentResultMethodParameter returnType) {super((Callable<Object>) () -> {if (result instanceof Exception) {throw (Exception) result;}else if (result instanceof Throwable) {throw new NestedServletException("Async processing failed", (Throwable) result);}return result;}, CALLABLE_METHOD);if (ServletInvocableHandlerMethod.this.returnValueHandlers != null) {setHandlerMethodReturnValueHandlers(ServletInvocableHandlerMethod.this.returnValueHandlers);}this.returnType = returnType;}}
}
- 其余方法
ConcurrentResultHandlerMethod 类实现了三个方法,getBeanType、getMethodAnnotation 及 hasMethodAnnotation;都是直接调用 ServletInvocableHandlerMethod 类的对应方法用于直接获取实际方法所属类与指定注解,而不是 CALLABLE_METHOD 常量的相关值。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {@Overridepublic Class<?> getBeanType() {return ServletInvocableHandlerMethod.this.getBeanType();}@Overridepublic <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {return ServletInvocableHandlerMethod.this.getMethodAnnotation(annotationType);}@Overridepublic <A extends Annotation> boolean hasMethodAnnotation(Class<A> annotationType) {return ServletInvocableHandlerMethod.this.hasMethodAnnotation(annotationType);}}
}
5.4.2 ConcurrentResultMethodParameter 内部类
ConcurrentResultMethodParameter 类继承自 HandlerMethodParameter 对象,用于封装返回方法返回参数。
- 扩展参数
ConcurrentResultMethodParameter 类扩展了一个用于保存返参值的 returnValue 参数及一个用于保存返参解析类型的 returnType 属性。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {private final MethodParameter returnType;@Overridepublic MethodParameter getReturnValueType(@Nullable Object returnValue) {return this.returnType;}}
}
- 构造方法
ConcurrentResultMethodParameter 类拥有两个构造方法,第一个用于封装指定返回参数,第二个则用于返回参数复制。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {public ConcurrentResultMethodParameter(Object returnValue) {super(-1);this.returnValue = returnValue;this.returnType = (returnValue instanceof ReactiveTypeHandler.CollectedValuesList ?((ReactiveTypeHandler.CollectedValuesList) returnValue).getReturnType() :ResolvableType.forType(super.getGenericParameterType()).getGeneric());}public ConcurrentResultMethodParameter(ConcurrentResultMethodParameter original) {super(original);this.returnValue = original.returnValue;this.returnType = original.returnType;}@Overridepublic ConcurrentResultMethodParameter clone() {return new ConcurrentResultMethodParameter(this);}}
}
- 其余方法
getParameterType 方法在 returnValue 参数不为空时直接返回其类型,在 returnType 不等于 ResolvableType.NONE 时直接返回 returnType,最后才会调用父类的 getParameterType 方法尝试获取参数类型并返回。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {@Overridepublic Class<?> getParameterType() {if (this.returnValue != null) {return this.returnValue.getClass();}if (!ResolvableType.NONE.equals(this.returnType)) {return this.returnType.toClass();}return super.getParameterType();}}
}
getGenericParameterType 方法直接调用 returnType 对象的 getType 方法并返回。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {@Overridepublic Type getGenericParameterType() {return this.returnType.getType();}}
}
hasMethodAnnotation 方法用于判断是否拥有指定注解,其首先是调用超类的 hasMethodAnnotation 方法,在其为 true 直接返回;否则为了支持响应式返回值(方法不需要使用 ResponseBody 对象进行修饰),其增加了在 annotationType 参数为 ResponseBody 类对象时,增加了判断返回值是否为 ReactiveTypeHandler.CollectedValuesList ,即响应式返回值,如 Flux<?> 、ResponseEntity<Flux<?>> 等。
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {private class ConcurrentResultHandlerMethod extends ServletInvocableHandlerMethod {@Overridepublic <T extends Annotation> boolean hasMethodAnnotation(Class<T> annotationType) {// Ensure @ResponseBody-style handling for values collected from a reactive type// even if actual return type is ResponseEntity<Flux<T>>return (super.hasMethodAnnotation(annotationType) ||(annotationType == ResponseBody.class &&this.returnValue instanceof ReactiveTypeHandler.CollectedValuesList));} }
}