概述 :
DispatcherServlet作为Spring MVC的核心控制器,初始化组件,处理客户端发送的请求,并返回 ModelAndView,进行视图渲染。主要是实现了父类 FrameworkServlet的抽象方法 doService()。
DispatcherServlet的 initStrategies方法如何被调用的
入口类:AbstractApplicationContext # refresh
├─ refresh
│├─ finishRefresh
││└─ publishEvent
│││├─ publishEvent
│││└─ multicastEvent
││││└─ invokeListener
│││││└─ doInvokeListener
││││││└─ onApplicationEvent
│││││││└─ onRefresh
││││││││└─ onRefresh
│││││││││└─ initStrategies
进入 onRefresh方法
所在类:org.springframework.web.servlet. DispatcherServlet
protected void onRefresh(ApplicationContext context) { initStrategies(context); } protected void initStrategies(ApplicationContext context) { // 初始化文件上传处理 initMultipartResolver(context); // 初始化本地化 Resolver initLocaleResolver(context); // 初始化主题 Resolver initThemeResolver(context); // 初始化 URL映射关系 initHandlerMappings(context); // 初始化Handler接口适配器 initHandlerAdapters(context); // 初始化异常处理的 handler initHandlerExceptionResolvers(context); // 初始化请求路径转换 initRequestToViewNameTranslator(context); // 初始化视图解析 initViewResolvers(context); // 初始化 flashmap管理 initFlashMapManager(context); }
::: warning 知识点 initStrategies方法中的所有初始化组件中之所以可以拿到值,主要是通过 @EnableWebMvc注解,调用到 WebMvcConfigurationSupport类中的各个 @Bean注解的方法,完成的实例化过程。:::
当父子容器都启动完成后,开始进行请求的响应处理,
进入 service方法
所在类:JAVAx.servlet.http. HttpServlet
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } // ...... 省略 }
进入 doGet方法
所在类:org.springframework.web.servlet. FrameworkServlet
@Override protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); }
进入 processRequest方法
所在类:org.springframework.web.servlet. FrameworkServlet
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; doService(request, response);}
进入 doService方法
所在类:org.springframework.web.servlet. DispatcherServlet
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { logRequest(request); 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); } } }}
请求最终进入 doDispatch方法
所在类:org.springframework.web.servlet. DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; // 异步管理 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { // 文件上传解析,如果请求类型是multipart将通过 // MultipartResolver进行文件上传解析 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // 对当前请求匹配一个合适的 handler,重要方法 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. 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; } // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { dispatchException = new NestedServletException("Handler dispatch failed", err); } 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 { // 如果是multipart的请求,清空上传的multipart资源 if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
::: warning 知识点总结, getHandler方法的主要作用体现在以下几点:
进入 getHandler方法
所在类:org.springframework.web.servlet. DispatcherServlet
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // handlerMappering 实例容器不为空 if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { // 获取 HandlerMethod 和过滤器链的包装类 HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
进入 getHandler方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 根据请求的 URL 拿到对应的 HandlerMethod 对象 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); } // 获取 HandlerMethod 和过滤器链的包装类 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } // 是否是跨域请求,就是查看 request 请求头中是否有 Origin 属性 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
进入 getHandlerInternal方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMethodMapping
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 从request对象中获取 URL,/common/query2 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); this.mappingRegistry.acquireReadLock(); try { // 根据 URL 从映射关系中找到对应的 HandlerMethod 对象 HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); // 执行beanFactory.getBean的过程,获取Controller实例 return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
::: warning 知识点
lookupHandlerMethod方法之所以可以从映射关系中拿到 HandlerMethod对象,是因为 AbstractHandlerMethodMapping类实现了 InitializingBean接口,在 afterPropertiesSet方法里建立好了映射关系。:::
进入 lookupHandlerMethod方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMethodMapping
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 匹配过程,是否符合 RequestMappingInfo 里的属性值 addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // No choice but to go through all mappings... addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); Match bestMatch = matches.get(0); if (matches.size() > 1) { if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); // 如果两个 RequestMappinginfo 什么都相同,报错 if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
::: warning 知识点
addMatchingMappings方法,主要一个匹配过程,匹配 @RequestMapping注解中的属性值是否满足
/* * consumes:指定处理请求的提交内容类型(Content-Type), * 例如application/json, text/html; * produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回; * params:指定request中必须包含某些参数值是,才让该方法处理。 * headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。 * */@RequestMapping(value = "/getUser", method = RequestMethod.GET, params = "username=jack", consumes = "application/json", produces = "application/json", headers = "Referer=http://www.xx.com/")
:::
返回 getHandler,进入 getHandlerExecutionChain方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMapping
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { // 如果没有获得则创建一个 HandlerExecutionChain HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); // 获取当前的请求地址:/user/xxx String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); // 在 HandlerExecutionChain 中添加拦截器 // 遍历 SpringMVC 容器的所有拦截器 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { // 判断拦截器类型,如果是 MappedInterceptor 类型 if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; // 则先匹配路径后再添加到执行链 if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { // 否则直接添加到执行链 chain.addInterceptor(interceptor); } } return chain; }
::: warning 知识点
getHandlerExecutionChain中的 HandlerInterceptor拦截器是 SpringMVC中的, SpringAOP中的拦截器是 MethodInterceptor。:::
拿到当前请求对应的 handler后,
返回主流程,进入 getHandlerAdapter方法
所在类:org.springframework.web.servlet. DispatcherServlet
/** * TODO : 根据 handlerMethod对象,找到合适的 HandlerAdapter对象,这里用到了策略模式 */protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { // 返回一个可以支持的HandlerAdapter 处理程序实例 return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
::: warning 知识点
HandlerAdapter 是什么HandlerAdapter是一个接口,充当自身与处理程序对象之间的桥梁,从而导致松散耦合设计。HandlerAdapter主要处理方法参数、相关注解、数据绑定、消息转换、返回值、调用视图解析器等。
RequestMappingHandlerMapping为当前的请求找到合适的处理程序方法。
RequestMappingHandlerAdapter执行这个处理程序方法,并为它提供反射调用所需要的参数。
HandlerAdapter UML 图
HandlerAdapter的4个实现类:
SimpleServletHandlerAdapter: 适配实现 Servlet 接口的 Handler, 默认调用其 service方法
SimpleControllerHandlerAdapter: 适配实现 Controller 接口的 Handler, 默认调用其 handleRequest 方法
HttpRequestHandlerAdapter: 适配实现 HttpRequestHandler 接口的 Handler, 默认调用其 handleRequest 方法
RequestMappingHandlerAdapter: 适配被 @RequestMapping注释的方式, 一般都是解析一个一个参数, 并且通过反射进行激活
HandlerAdapter 总结HandlerAdapter 是 SpringMVC中扩展机制的非常好的一个体现,,通过 HandlerAdapter这种设计模式, DispatcherServlet 就可以支持任何格式的 Handler(这里的可以支持指在不改变 DispatcherServlet 的情况下),第二是 HandlerAdapter 基于不同 Handler实现不同实现类(策略模式),最后也是最重要的就是参数的解析与返回值的解析。
:::
::: danger 为什么要用HandlerAdapter适配器模式? 首先, Controller的定义有多种 ,一种是带 @Controller注解的, 还可以写一个 servlet 当做 controller, 所以用适配器做适配,不同子类实现 HandlerAdapter接口,定义自己的业务逻辑,每个子类都是适配某一种类型的控制器,有了 HandlerAdapter,你只需要调用自己实现的 handle方法,屏蔽了不一致的细节,对用户来说直接找到对应的处理方法,无须关系哪个实现方法,否则只能在 DispatcherServlet里面通过 if、 else来处理了。:::
返回主流程,进入 applyPreHandle方法,前置过滤器
所在类:org.springframework.web.servlet. DispatcherServlet
/** * TODO :调用所有的 HandlerInterceptor 拦截器并调用其 preHandler方法 */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)) { triggerAfterCompletion(request, response, null); return false; } // 如果失败,记录最后一次拦截器的位置,倒序释放 this.interceptorIndex = i; } } return true; }
返回主流程,进入 handle方法,调用具体 Controller的方法
最终会进入 AbstractHandlerMethodAdapter的 handle方法,
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
进入 handleInternal方法,
所在类:org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter
protected 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 // 执行 HandlerMethod,返回 ModelAndView mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... // 执行 HandlerMethod,返回 ModelAndView mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
进入 invokeHandlerMethod方法,
所在类:org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // 获取数据绑定工厂 @InitBinder注解支持, WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // Model工厂,收集了@ModelAttribute注解的方法 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)); // 调用有 @ModelAttribute注解的方法。每次请求都会调用有 @ModelAttribute注解的方法 //把 @ModelAttribute注解的方法的返回值存储到 ModelAndViewContainer对象的 map中了 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); } // Controller方法调用,重点看看 invocableMethod.invokeAndHandle(webRequest, mavContainer); if (asyncManager.isConcurrentHandlingStarted()) { return null; } return getModelAndView(mavContainer, modelFactory, webRequest); } finally { webRequest.requestCompleted(); } }
::: warning 知识点
invokeHandlerMethod方法主要进行了数据和参数的绑定、创建 ModelAndViewContainer视图容器,以及相关初始化工作。:::
进入 invokeAndHandle方法
所在类:org.springframework.web.servlet.mvc.method.annotation. ServletInvocableHandlerMethod
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // 具体调用逻辑,重点看 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); setResponseStatus(webRequest); if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { // 返回值处理 this.returnValueHandlers.handleReturnValue( returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } }
进入 invokeForRequest方法
所在类:org.springframework.web.method.support. InvocableHandlerMethod
public 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方法
所在类:org.springframework.web.method.support. InvocableHandlerMethod
protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { if (ObjectUtils.isEmpty(getMethodParameters())) { return EMPTY_ARGS; } // 入参的包装类,里面包装了参数类型,参数名称,参数注解等等信息 MethodParameter[] parameters = getMethodParameters(); 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; } // 典型的策略模式,根据 parameter 能否找到对应参数的处理类,能找到就返回true 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 error = ex.getMessage(); if (error != null && !error.contains(parameter.getExecutable().toGenericString())) { logger.debug(formatArgumentError(parameter, error)); } } throw ex; } } return args; }
进入 resolveArgument方法
所在类:org.springframework.web.method.support. HandlerMethodArgumentResolverComposite
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { // 根据参数获取对应参数的解析类 HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException( "Unsupported parameter type [" + parameter.getParameterType().getName() + "]." + " supportsParameter should be called first."); } // 策略模式去调用具体参数解析类 return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }
::: warning 知识点
MethodParameter类是对参数信息的封装,其中重要的几个属性包括:
进入 getArgumentResolver方法
所在类:org.springframework.web.method.support. HandlerMethodArgumentResolverComposite
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { // 先从缓存中拿到参数处理器对象 HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter); // 如果缓存中没有 if (result == null) { // 循环容器中 HandlerMethodArgumentResolver类型的所有解析器: List<HandlerMethodArgumentResolver> for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) { // 典型的策略模式匹配,拿到当前参数对应的处理解析类 if (methodArgumentResolver.supportsParameter(parameter)) { // 赋值给 HandlerMethodArgumentResolver 对象 result = methodArgumentResolver; // 放到缓存中 this.argumentResolverCache.put(parameter, result); break; } } } return result; }
::: warning 知识点
HandlerMethodArgumentResolver参数解析器,最复杂的处理流程之一,Spring中默认有26种参数解析器,来对应完成某种参数的解析工作。添加过程是 SpringMVC启动实例化后,通过 RequestMappingHandlerAdapter类的 afterPropertiesSet方法调用 getDefaultArgumentResolvers添加到 HandlerMethodArgumentResolver解析器中的。:::
返回主流程,进入 handleInternal方法,中置过滤器
所在类:org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter
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]; // 分别调用拦截器的 postHandle方法 interceptor.postHandle(request, response, this.handler, mv); } } }
::: warning 知识点中置过滤器的调用时序,是当 ha.handle 掉完以后,也就是 Controller 里面具体方法调用完以后才轮到中置过滤器调用。可以根据 ModelAndView对象做视图修改。:::
返回主流程,进入 triggerAfterCompletion方法,后置过滤器
所在类:org.springframework.web.servlet.mvc.method.annotation. RequestMappingHandlerAdapter
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); } } } }
::: warning 知识点
applyPreHandle前置过滤器主要作用是对当前请求做一些初步的验证,内部执行顺序是正序遍历, applyPostHandle 中置过滤器和 triggerAfterCompletion后置过滤器的执行顺序是倒序遍历,倒序是因为一但前置过滤器中断(拦截器 preHndle返回 false)那么请求终止,根据中断的数组坐标 interceptorIndex,倒序释放执行已经过滤的的拦截方法。:::
到此为止,主流程结束,以上完成了Spring MVC`从请求到处理的一系列过程,包括请求方法调用
、参数解析、过滤器调用等,接下来就是处理返回值的解析工作。
::: danger 常见注解