SpringMVC之请求处理流程
SpringMVC之请求处理流程
我们知道DispatcherServlet就是一个HttpServlet,而HttpServlet的请求就从doGet/doPost开始
DispatcherServlet本身没有实现doGet/doPost,而由他的父类FrameworkServlet实现,源码如下
FrameworkServlet.doGet/doPost
@Overrideprotected final void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Delegate POST requests to {@link #processRequest}.* @see #doService*/@Overrideprotected final void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}
processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; //previousLocaleContext获取和当前线程相关的LocaleContext,根据已有请求构造一个新的和当前线程相关的LocaleContext LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = buildLocaleContext(request); //previousAttributes获取和当前线程绑定的RequestAttributes RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); //为已有请求构造新的ServletRequestAttributes,加入预绑定属性 ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);//异步请求处理 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor()); //initContextHolders让新构造的RequestAttributes和ServletRequestAttributes和当前线程绑定,加入到ThreadLocal,完成绑定 initContextHolders(request, localeContext, requestAttributes); try { //抽象方法doService由FrameworkServlet子类DispatcherServlet重写 doService(request, response); }catch (ServletException | IOException ex) { failureCause = ex; throw ex; }catch (Throwable ex) { failureCause = ex; throw new NestedServletException("Request processing failed", ex); }finally { //解除RequestAttributes,ServletRequestAttributes和当前线程的绑定 resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } logResult(request, response, failureCause, asyncManager); //注册监听事件ServletRequestHandledEvent,在调用上下文的时候产生Event publishRequestHandledEvent(request, response, startTime, failureCause); }}
doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); // Keep a snapshot of the request attributes in case of an include, // to be able to restore the original attributes after the include. Map attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap();//保存request域中的数据,存一份快照 Enumeration attrNames = request.getAttributeNames(); while (attrNames.hasMoreElements()) { String attrName = (String) attrNames.nextElement(); if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) { attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } } //设置web应用上下文 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext()); //国际化本地 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); //样式 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); //设置样式资源 request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource()); //请求刷新时保存属性 if (this.flashMapManager != null) { FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } //Flash attributes 在对请求的重定向生效之前被临时存储(通常是在session)中,并且在重定向之后被立即移除 request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); //FlashMap 被用来管理 flash attributes 而 FlashMapManager 则被用来存储,获取和管理 FlashMap 实体 request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); } try { //核心方法 doDispatch(request, response); }finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot);//将快照覆盖回去 } } }}
DispatcherServlet.doDispatch
这个方法就是处理请求的核心方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false;//异步处理,webflux相关 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { //将request转换成multipartRequest,并检查是否解析成功(判断是否有文件上传) processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); //根据请求信息获取handler(包含了拦截器),组成HandlerExecutionChain mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } //根据handler获取adapter---命名为ha HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } }//执行拦截器逻辑 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //执行业务处理,返回视图模型 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; }//给视图模型设置viewName applyDefaultViewName(processedRequest, mv); //拦截器逻辑 mappedHandler.applyPostHandle(processedRequest, response, mv); }catch (Exception ex) { dispatchException = ex; }catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } //处理请求结果,使用了组件LocaleResolver, ViewResolver和ThemeResolver(view#render) processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); }catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); }finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } }else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } }}
DispatcherServlet.getHandler
@Nullableprotected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null;}
这里的this.handlerMappings就是9大组件之一,在web容器启动时方法中初始化.
过滤器和拦截器
- 过滤器拦截DispatcherServlet,属于web服务器层面
- 拦截器可以拦截到具体方法,属于springmvc框架
HandlerExecutionChain对象包含处理器+拦截器链
public class HandlerExecutionChain { private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);//真正的处理器 private final Object handler;//配置在springmvc配置文件的拦截器 @Nullable private HandlerInterceptor[] interceptors;//所有拦截器 @Nullable private List interceptorList;}
AbstractHandlerMapping.getHandler
/** * 返回请求处理的HandlerExecutionChain,从AbstractHandlerMapping中的adaptedInterceptors和mappedInterceptors属性中获取 */@Override@Nullablepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // getHandlerInternal()为抽象方法,具体需子类实现 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // 将请求处理器封装为HandlerExectionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 对跨域的处理 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain;}
AbstractHandlerMapping.getHandlerExecutionChain
/** * 构建handler处理器的HandlerExecutionChain,包括拦截器 */protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {//将handler处理成HandlerExecutionChain HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); // 迭代添加拦截器,private final List adaptedInterceptors = new ArrayList(); for (HandlerInterceptor interceptor : this.adaptedInterceptors) { // 如果拦截器是MappedInterceptor,判断是否对该handler进行拦截,是的情况下添加 if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { // HandlerInterceptor直接添加,即通过HandingMapping属性配置的拦截器 chain.addInterceptor(interceptor); } } return chain;}// new HandlerExecutionChain(handler),将handler变成HandlerExecutionChainpublic HandlerExecutionChain(Object handler, @Nullable HandlerInterceptor... interceptors) {if (handler instanceof HandlerExecutionChain) {HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;this.handler = originalChain.getHandler();//new一个interceptorListthis.interceptorList = new ArrayList();//将HandlerInterceptor合并到interceptorListCollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);}else {this.handler = handler;this.interceptors = interceptors;}}
总结一下
就是把处理器+拦截器链组合成 HandlerExecutionChain 对象,看一下最普通的返回值
DispatcherServlet.getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { //判断adapter是否适配handler,适配的话就返回,一般情况下handler是HandlerMethod类型 if (adapter.supports(handler)) { //这里一般返回RequestMappingHandlerAdapter return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }//this.handlerAdaptersprivate List handlerAdapters;//RequestMappingHandlerAdapter的父类AbstractHandlerMethodAdapter的代码实现@Overridepublic final boolean supports(Object handler) {return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));}
HandlerAdapter就是适配器对象
RequestMappingHandlerAdapter
RequestMappingHandlerAdapter就是处理@RequestMapping注解的适配器
/** * Extension of {@link AbstractHandlerMethodAdapter} that supports * {@link RequestMapping @RequestMapping} annotated {@link HandlerMethod HandlerMethods}. * *Support for custom argument and return value types can be added via * {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}, * or alternatively, to re-configure all argument and return value types, * use {@link #setArgumentResolvers} and {@link #setReturnValueHandlers}. * * @author Rossen Stoyanchev * @author Juergen Hoeller * @since 3.1 * @see HandlerMethodArgumentResolver * @see HandlerMethodReturnValueHandler */public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { ... }
HandlerExecutionChain.applyPreHandle
执行拦截器逻辑
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; //执行拦截器preHandle方法 if (!interceptor.preHandle(request, response, this.handler)) { //拦截后的方法afterCompletion triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true;}
HandlerAdapter.handle
使用适配器执行业务处理,返回视图模型
@Override@Nullablepublic final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler);}
RequestMappingHandlerAdapter.handleInternal
@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 necessary mav = 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;}
RequestMappingHandlerAdapter.invokeHandlerMethod
@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(); }}
invocableMethod.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()) { 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; }}
invokeForRequest();
这个方法就是在处理@RequestMapper注解的方法,并通过反射得到返回值
@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);}
doInvoke(Object... args)
@Nullableprotected Object doInvoke(Object... args) throws Exception { ReflectionUtils.makeAccessible(getBridgedMethod()); try { //这里getBridgedMethod()就是Method,得到Method然后反射执行方法,得到返回值 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); } }}
这里得到返回值后,springmvc会进行一系列处理,最后用IO write出去
HandlerExecutionChain.applyPostHandle
执行拦截器中postHandle方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } }}
processDispatchResult
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false;//异常处理 if (exception != null) { //ModelAndViewDefiningException类型,会携带对应的ModelAndView if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { //由对应的处理器handler进行异常处理,返回ModelAndView。其中使用了HandlerExceptionResolver。 Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response); if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isTraceEnabled()) { logger.trace("No view rendering, null ModelAndView returned."); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { //这里执行拦截器的afterCompletion方法 // Exception (if any) is already handled.. mappedHandler.triggerAfterCompletion(request, response, null); }}
mappedHandler.triggerAfterCompletion
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } }}
HandlerMapping
public interface HandlerMapping { // 返回请求的一个处理程序handler和拦截器interceptors @Nullable HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;}
HandlerMapping作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。这是官方文档上一段描述,该接口只有一个方法getHandler(request),返回一个HandlerExecutionChain对象
如果配置了这个标签,Spring MVC会默认添加RequestMappingHandlerMapping和RequestMappingHandlerAdapter
Spring MVC会加载在当前系统中所有实现了HandlerMapping接口的bean,再进行按优先级排序。
-
SimpleUrlHandlerMapping 支持映射bean实例和映射bean名称,需要手工维护urlmap,通过key指定访问路径,
-
BeanNameUrlHandlerMapping 支持映射bean的name属性值,扫描以”/“开头的beanname,通过id指定访问路径
-
RequestMappingHandlerMapping 支持@Controller和@RequestMapping注解,通过注解定义访问路径
AbstractHandlerMapping
模板类
protected void initApplicationContext() throws BeansException { // 提供给子类去重写的,不过Spring并未去实现,提供扩展 extendInterceptors(this.interceptors); // 加载拦截器 detectMappedInterceptors(this.adaptedInterceptors); // 归并拦截器 initInterceptors();}/** * 空实现 */protected void extendInterceptors(List interceptors) {}/** * 从上下文中加载MappedInterceptor类型的拦截器,比如我们在配置文件中使用 * * 标签配置的拦截器 */protected void detectMappedInterceptors(List mappedInterceptors) { mappedInterceptors.addAll( BeanFactoryUtils.beansOfTypeIncludingAncestors( obtainApplicationContext(), MappedInterceptor.class, true, false).values());}/** * 合并拦截器,即将中的拦截器与HandlerMapping中通过属性interceptors设置的拦截器进行合并 */protected void initInterceptors() { if (!this.interceptors.isEmpty()) { for (int i = 0; i < this.interceptors.size(); i++) { Object interceptor = this.interceptors.get(i); if (interceptor == null) { throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null"); } // 适配后加入adaptedInterceptors this.adaptedInterceptors.add(adaptInterceptor(interceptor)); } }}/** * 适配HandlerInterceptor和WebRequestInterceptor */protected HandlerInterceptor adaptInterceptor(Object interceptor) { if (interceptor instanceof HandlerInterceptor) { return (HandlerInterceptor) interceptor; } else if (interceptor instanceof WebRequestInterceptor) { return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor); } else { throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName()); }}/** * 返回请求处理的HandlerExecutionChain,从AbstractHandlerMapping中的adaptedInterceptors和mappedInterceptors属性中获取 */@Override@Nullablepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // getHandlerInternal()为抽象方法,具体需子类实现 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // 将请求处理器封装为HandlerExectionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 对跨域的处理 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain;}/** * 钩子函数,需子类实现 */@Nullableprotected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;/** * 构建handler处理器的HandlerExecutionChain,包括拦截器 */protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); // 迭代添加拦截器 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { // 如果拦截器是MappedInterceptor,判断是否对该handler进行拦截,是的情况下添加 if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { // HandlerInterceptor直接添加,即通过HandingMapping属性配置的拦截器 chain.addInterceptor(interceptor); } } return chain;}
RequestMappingHandlerMapping
处理注解@RequestMapping及@Controller
- 实现InitializingBean接口,增加了bean初始化的能力,也就是说在bean初始化时可以做一些控制
- 实现EmbeddedValueResolverAware接口,即增加了读取属性文件的能力
继承自AbstractHandlerMethodMapping
//RequestMappingHandlerMapping@Overridepublic void afterPropertiesSet() { this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setUrlPathHelper(getUrlPathHelper()); this.config.setPathMatcher(getPathMatcher()); this.config.setSuffixPatternMatch(this.useSuffixPatternMatch); this.config.setTrailingSlashMatch(this.useTrailingSlashMatch); this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch); this.config.setContentNegotiationManager(getContentNegotiationManager()); super.afterPropertiesSet();}//AbstractHandlerMethodMapping@Overridepublic void afterPropertiesSet() { initHandlerMethods();}protected void initHandlerMethods() { //获取上下文中所有bean的name,不包含父容器 for (String beanName : getCandidateBeanNames()) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { processCandidateBean(beanName); } } //日志记录HandlerMethods的总数量 handlerMethodsInitialized(getHandlerMethods());}protected void processCandidateBean(String beanName) { Class beanType = null; try { //根据name找出bean的类型 beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'", ex); } } //处理Controller和RequestMapping if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); }}//RequestMappingHandlerMapping@Overrideprotected boolean isHandler(Class beanType) { //获取@Controller和@RequestMapping return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));}//整个controller类的解析过程 protected void detectHandlerMethods(Object handler) { //根据name找出bean的类型Class handlerType = (handler instanceof String ?obtainApplicationContext().getType((String) handler) : handler.getClass());if (handlerType != null) { //获取真实的controller,如果是代理类获取父类Class userType = ClassUtils.getUserClass(handlerType); //对真实的controller所有的方法进行解析和处理 key为方法对象,T为注解封装后的对象RequestMappingInfoMap methods = MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup) method -> {try { // 调用子类RequestMappingHandlerMapping的getMappingForMethod方法进行处理,即根据RequestMapping注解信息创建匹配条件RequestMappingInfo对象return getMappingForMethod(method, userType);}catch (Throwable ex) {throw new IllegalStateException("Invalid mapping on handler class [" +userType.getName() + "]: " + method, ex);}});if (logger.isTraceEnabled()) {logger.trace(formatMappings(userType, methods));}methods.forEach((method, mapping) -> { //找出controller中可外部调用的方法Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); //注册处理方法registerHandlerMethod(handler, invocableMethod, mapping);});}}//requestMapping封装成RequestMappingInfo对象protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { RequestMappingInfo info = createRequestMappingInfo(method);//解析方法上的requestMapping if (info != null) { //解析方法所在类上的requestMapping RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null) { info = typeInfo.combine(info);//合并类和方法上的路径,比如Controller类上有@RequestMapping("/demo"),方法的@RequestMapping("/demo1"),结果为"/demo/demo1" } String prefix = getPathPrefix(handlerType);//合并前缀 if (prefix != null) { info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info); } } return info;}private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { //找到方法上的RequestMapping注解 RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); //获取自定义的类型条件(自定义的RequestMapping注解) RequestCondition condition = (element instanceof Class ? getCustomTypeCondition((Class) element) : getCustomMethodCondition((Method) element)); return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);}protected RequestMappingInfo createRequestMappingInfo( RequestMapping requestMapping, @Nullable RequestCondition customCondition) { //获取RequestMapping注解的属性,封装成RequestMappingInfo对象 RequestMappingInfo.Builder builder = RequestMappingInfo .paths(resolveEmbeddedValuesInPatterns(requestMapping.path())) .methods(requestMapping.method()) .params(requestMapping.params()) .headers(requestMapping.headers()) .consumes(requestMapping.consumes()) .produces(requestMapping.produces()) .mappingName(requestMapping.name()); if (customCondition != null) { builder.customCondition(customCondition); } return builder.options(this.config).build();}//再次封装成对应的对象 面向对象编程 每一个属性都存在多个值得情况需要排重封装@Overridepublic RequestMappingInfo build() { ContentNegotiationManager manager = this.options.getContentNegotiationManager(); PatternsRequestCondition patternsCondition = new PatternsRequestCondition( this.paths, this.options.getUrlPathHelper(), this.options.getPathMatcher(), this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(), this.options.getFileExtensions()); return new RequestMappingInfo(this.mappingName, patternsCondition, new RequestMethodsRequestCondition(this.methods), new ParamsRequestCondition(this.params), new HeadersRequestCondition(this.headers), new ConsumesRequestCondition(this.consumes, this.headers), new ProducesRequestCondition(this.produces, this.headers, manager), this.customCondition);}
registerHandlerMethod
protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method);}//mapping是RequestMappingInfo对象 handler是controller类的beanName method为接口方法public void register(T mapping, Object handler, Method method) { ... this.readWriteLock.writeLock().lock(); try { //beanName和method封装成HandlerMethod对象 HandlerMethod handlerMethod = createHandlerMethod(handler, method); //验证RequestMappingInfo是否有对应不同的method,有则抛出异常 validateMethodMapping(handlerMethod, mapping); //RequestMappingInfo和handlerMethod绑定 this.mappingLookup.put(mapping, handlerMethod); List directUrls = getDirectUrls(mapping);//可以配置多个url for (String url : directUrls) { //url和RequestMappingInfo绑定 可以根据url找到RequestMappingInfo,再找到handlerMethod this.urlLookup.add(url, mapping); } String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod);//方法名和Method绑定 } CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { this.corsLookup.put(handlerMethod, corsConfig); }//将RequestMappingInfo url handlerMethod绑定到MappingRegistration对象 放入map this.registry.put(mapping, new MappingRegistration(mapping, handlerMethod, directUrls, name)); } finally { this.readWriteLock.writeLock().unlock(); }}
HandlerAdapters
Spring MVC为我们提供了多种处理用户的处理器(Handler),Spring实现的处理器类型有Servlet、Controller、HttpRequestHandler以及注解类型的处理器,即我们可以通过实现这些接口或者注解我们的类来使用这些处理器,那么针对不同类型的处理器,如何将用户请求转发到相应类型的处理器方法中的呢,这就需求Spring MVC的处理器适配器来完成适配操作,这就是处理器适配器要完成的工作。
-
SimpleServletHandlerAdapter 适配Servlet处理器
-
HttpRerquestHandlerAdapter 适配HttpRequestHandler处理器
-
RequestMappingHandlerAdapter 适配注解处理器
-
SimpleControllerHandlerAdapter 适配Controller处理器
Spring MVC默认使用的处理器适配器为:HttpRequestHandlerAdapter、SimpleServletHandlerAdapter、RequestMappingHandlerAdapter三种。
RequestMappingHandlerAdapter
通过继承抽象类AbstractHandlerMethodAdapter实现了HandlerAdapter接口
请求适配给 @RequestMapping
类型的Handler处理。
采用反射机制调用url请求对应的Controller中的方法(这其中还包括参数处理),返回执行结果值,完成HandlerAdapter的使命
getLastModified直接返回-1
@Overrideprotected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) { return -1;}//通过父类调用@Overrideprotected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // 判断当前是否需要支持在同一个session中只能线性地处理请求 if (this.synchronizeOnSession) { // 获取当前请求的session对象 HttpSession session = request.getSession(false); if (session != null) { // 为当前session生成一个唯一的可以用于锁定的key Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { // 对HandlerMethod进行参数等的适配处理,并调用目标handler mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // 如果当前不存在session,则直接对HandlerMethod进行适配 mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // 如果当前不需要对session进行同步处理,则直接对HandlerMethod进行适配 mav = invokeHandlerMethod(request, response, handlerMethod); } // 判断当前请求头中是否包含Cache-Control请求头,如果不包含,则对当前response进行处理,为其设置过期时间 if (!response.containsHeader(HEADER_CACHE_CONTROL)) { // 如果当前SessionAttribute中存在配置的attributes,则为其设置过期时间。 // 这里SessionAttribute主要是通过@SessionAttribute注解生成的 if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { // 如果当前不存在SessionAttributes,则判断当前是否存在Cache-Control设置, // 如果存在,则按照该设置进行response处理,如果不存在,则设置response中的 // Cache的过期时间为-1,即立即失效 prepareResponse(response); } } return mav;}//核心处理流程@Nullableprotected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // 获取容器中全局配置的InitBinder和当前HandlerMethod所对应的Controller中配置的InitBinder,用于进行参数的绑定 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // 获取容器中全局配置的ModelAttribute和当前HandlerMethod所对应的Controller // 中配置的ModelAttribute,这些配置的方法将会在目标方法调用之前进行调用 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // 将handlerMethod封装为一个ServletInvocableHandlerMethod对象,该对象用于对当前request的整体调用流程进行了封装 ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); if (this.argumentResolvers != null) { // 设置当前容器中配置的所有ArgumentResolver invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); } if (this.returnValueHandlers != null) { // 设置当前容器中配置的所有ReturnValueHandler invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); } // 将前面创建的WebDataBinderFactory设置到ServletInvocableHandlerMethod中 invocableMethod.setDataBinderFactory(binderFactory); // 设置ParameterNameDiscoverer,该对象将按照一定的规则获取当前参数的名称 invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer); ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); // 这里initModel()方法主要作用是调用前面获取到的@ModelAttribute标注的方法, // 从而达到@ModelAttribute标注的方法能够在目标Handler调用之前调用的目的 modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); // 获取当前的AsyncWebRequest,这里AsyncWebRequest的主要作用是用于判断目标 // handler的返回值是否为WebAsyncTask或DefferredResult,如果是这两种中的一种, // 则说明当前请求的处理应该是异步的。所谓的异步,指的是当前请求会将Controller中 // 封装的业务逻辑放到一个线程池中进行调用,待该调用有返回结果之后再返回到response中。 // 这种处理的优点在于用于请求分发的线程能够解放出来,从而处理更多的请求,只有待目标任务 // 完成之后才会回来将该异步任务的结果返回。 AsyncWebRequest asyncWebRequest = WebAsyncUtils .createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); // 封装异步任务的线程池,request和interceptors到WebAsyncManager中 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(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]"); } // 封装异步任务的处理结果,虽然封装的是一个HandlerMethod,但只是Spring简单的封装 // 的一个Callable对象,该对象中直接将调用结果返回了。这样封装的目的在于能够统一的 // 进行右面的ServletInvocableHandlerMethod.invokeAndHandle()方法的调用 invocableMethod = invocableMethod.wrapConcurrentResult(result); } // 对请求参数进行处理,调用目标HandlerMethod,并且将返回值封装为一个ModelAndView对象 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } // 对封装的ModelAndView进行处理,主要是判断当前请求是否进行了重定向,如果进行了重定向, // 还会判断是否需要将FlashAttributes封装到新的请求中 return getModelAndView(mavContainer, modelFactory, webRequest); } finally { // 调用request destruction callbacks和对SessionAttributes进行处理 webRequest.requestCompleted(); }}
- 获取当前容器中使用
@InitBinder
注解注册的属性转换器; - 获取当前容器中使用
@ModelAttribute
标注但没有使用@RequestMapping
标注的方法,并且在调用目标方法之前调用这些方法; - 判断目标handler返回值是否使用了WebAsyncTask或DefferredResult封装,如果封装了,则按照异步任务的方式进行执行;
- 处理请求参数,调用目标方法和处理返回值。
总结一下
- 所有请求都会经过DispatcherServlet.doDispatch处理
- 将请求的内容和拦截器链处理成HandlerExecutionChain,一般情况下handler是HandlerMethod类型的,
- 寻找处理器对应的合适的适配器,一般情况下就是RequestMappingHandlerAdapter,用于处理@RequestMapping注解的适配器
- 执行拦截器链的preHandle方法
- 使用找到的适配器利用反射去执行方法,获取返回值,并响应
- 执行拦截器链的postHandle方法
- 执行拦截器链的afterCompletion方法
执行结果如下
/testJson----------------------preHandletestJson/testJson----------------------postHandle/testJson----------------------afterCompletion