快捷搜索:  汽车  科技

切面和拦截器顺序是固定的吗(拦截器Interceptor与适配器)

切面和拦截器顺序是固定的吗(拦截器Interceptor与适配器)protected void onRefresh(ApplicationContext context) { initStrategies(context); } protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(cont

前言:前一节已经介绍完springmvc的请求映射器RequestMappingHandlerMapping 已经完成根据http请求的uri及请求方式(GET POST)等特征匹配对应controller的method.这一节来介绍下请求适配器RequestMappingHandlerAdpater的获取 该对象是用于后续如何反射调用 以及开发中常见的拦截器原理.

1.概述

我们还是接着看DispatcherServlet的doDispatch方法

protected void doDispatch(HttpServletRequest request HttpServletResponse response) throws Exception { try { // 省略... try { // 省略... // 上节的HandlerExecutionChain 包含两类东西 // 1.方法控制器(HandlerMethod) // 2.拦截器 包含我们自定义的拦截器及 // RequestMappingHandlerMapping默认拦截器 // (ConversionServiceExposingInterceptor ResourceUrlProviderExposingInterceptor) mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest response); return; } // A.根据HandlerMethod获取适配器RequestMappingHandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 省略 last-modified... String method = request.getMethod(); // B.调用拦截器的前置处理 if (!mappedHandler.applyPreHandle(processedRequest response)) { return; } // 通过适配器完成controller对应method的调用(下节分享) mv = ha.handle(processedRequest response mappedHandler.getHandler()); // 省略视图解析... // C.调用拦截器的后置处理 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); } // 全局异常处理器(下下节分享) processDispatchResult(processedRequest response mappedHandler mv dispatchException); } catch (Exception ex) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler ex); } catch (Throwable err) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler new NestedServletException("Handler processing failed" err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { //异步请求才会走拦截器的该方法 这里与tomcat的处理机制有关 不做过多解读 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest response); } } // 省略... } }2.拦截器加载

为了与当前流行的web框架结合 从这节看是我们从springboot的视角来分析DispatcherServlet 与springmvc中不同之处是 springboot使用了自动装载机制。基本流程如下:

  • 在META-INF文件夹下创建spring.factories文件 并在文件中定义key value形式的键值对(类似于propreties文件)
  • 加载文件中定义Bean并注册到spring容器中
2.1.DispatcherServlet加载

首先我们先找到springboot自动配置文件

切面和拦截器顺序是固定的吗(拦截器Interceptor与适配器)(1)

springboot配置类

这里有两个我们需要关注的键值对

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration \ # 完成DispatcherServlet初始化 org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration \ # 完成自定义web行为配置初始化(自定义拦截器、自定义跨域配置)

我们先看看是如何完成DispatcherServlet初始化的

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 声明这是一个配置类 需要将该类中@Bean的方法注入到容器中 @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet"; @Configuration(proxyBeanMethods = false) // 同上 @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) protected static class DispatcherServletConfiguration { @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) { // 这里完成DispatcherServlet的初始化 DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails()); return dispatcherServlet; } } }

当请求第一次DispatcherServlet第一次请求Http请求时会初始化RequestMappingHandlerMapping与RequestMappingHandlerAdapter。

protected void onRefresh(ApplicationContext context) { initStrategies(context); } protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); } // 下面就是DispatcherServlet的初始化了 可以看前一篇的文章2.2.RequestMappingHandlerMapping加载

@Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class DispatcherServlet.class WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class TaskExecutionAutoConfiguration.class ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { // 该注解不只会将其方法中的bean注入到spring容器中 还会为当前的类创建bean并注入到spring容器中. @Configuration(proxyBeanMethods = false) public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager @Qualifier("mvcConversionService") FormattingConversionService conversionService @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { // Must be @Primary for MvcUriComponentsBuilder to work // 这里进行RequestMappingHandlerMapping加载 并注入spring容器 return super.requestMappingHandlerMapping(contentNegotiationManager conversionService resourceUrlProvider); } } }

我们先看看EnableWebMvcConfiguration类结构关系图

切面和拦截器顺序是固定的吗(拦截器Interceptor与适配器)(2)

DispatcherServlet自动装配UML

由上图可知requestMappingHandlerMapping执行的是父类WebMvcConfigurationSupport的requestMappingHandlerMapping方法 我们一起来看一下.

// WebMvcConfigurationSupport public RequestMappingHandlerMapping requestMappingHandlerMapping( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager @Qualifier("mvcConversionService") FormattingConversionService conversionService @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { // 1.new RequestMappingHandlerMapping RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping(); // 2.设置排序 当DispatcherServlet获取HandlerMapping实现类时 该对象位于第一个 // 也就是为RequestMappingHandlerMapping是DispatcherServlet默认的Mapping处理器的原因 mapping.setOrder(0); // 3.设置拦截器 mapping.setInterceptors(getInterceptors(conversionService resourceUrlProvider)); mapping.setContentNegotiationManager(contentNegotiationManager); // 4.跨域设置 mapping.setCorsConfigurations(getCorsConfigurations()); // 省略... return mapping; }2.3.EnableWebMvcConfiguration加载

当EnableWebMvcConfiguration初始化时会做两件事情:

  • 将其父类DelegatingWebMvcConfigurationWebMvcConfigurationSupport初始化。
  • 将初始化的实例(包含父类)进行依赖注入:1、带有@Autowired成员变量注入,2、带有@Autowired的方法注入变量并执行。

@Configuration(proxyBeanMethods = false) public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { public EnableWebMvcConfiguration(ResourceProperties resourceProperties ObjectProvider<WebMvcProperties> mvcPropertiesProvider ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider ListableBeanFactory beanFactory) { this.resourceProperties = resourceProperties; this.mvcProperties = mvcPropertiesProvider.getIfAvailable(); this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique(); this.beanFactory = beanFactory; } } // 父类 public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); // EnableWebMvcConfiguration依赖注入 // 这里会从容器中寻找类型为WebMvcConfigurer.class的对象 作为configurers的参数 然后执行当前方法 // 将WebMvcConfigurer存储在WebMvcConfigurerComposite中 @Autowired(required = false) public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); } } } // 引用 class WebMvcConfigurerComposite implements WebMvcConfigurer { // 自定义webmvc配置器会存放到这里 这里面也包含自定义拦截器(MyInterceptor) private final List<WebMvcConfigurer> delegates = new ArrayList<>(); public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.delegates.addAll(configurers); } } }

我们是如何自定义WebMvcConfigurer对象的呢?

@Component public class WebConfiguration implements WebMvcConfigurer { // 拦截请求 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } // 跨域支持 @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowCredentials(true).allowedHeaders("*").allowedOrigins("*") .allowedMethods("HEAD" "OPTIONS" "GET" "POST" "PUT" "PATCH" "DELETE"); } } public class MyInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request HttpServletResponse response Object handler) throws Exception { // 如果这里返回false 整个DispatcherServlet的调用就到此结束了 System.out.println("pre........"); return super.preHandle(request response handler); } @Override public void postHandle(HttpServletRequest request HttpServletResponse response Object handler ModelAndView modelAndView) throws Exception { // 只有pre返回true的时候才会走这里 pre碰到异常也不会走这里 System.out.println("post........."); super.postHandle(request response handler modelAndView); } @Override public void afterCompletion(HttpServletRequest request HttpServletResponse response Object handler Exception ex) throws Exception { // 不论pre返回true还是false 还是碰到任何异常 都会走这里 System.out.println("afterCompletion..."); super.afterCompletion(request response handler ex); } @Override public void afterConcurrentHandlingStarted(HttpServletRequest request HttpServletResponse response Object handler) throws Exception { System.out.println("afterConcurrentHandlingStarted..."); super.afterConcurrentHandlingStarted(request response handler); } }

上面完成了2个工作:

  • 完成了自定义webmvc配置器(WebConfiguration)初始化 并完成自定义拦截器MyInterceptor挂载 且将该对象注入到容器中。
  • 完成DelegatingWebMvcConfiguration依赖注入(setConfigurers) 并完成自定义webmvc配置WebConfiguration的挂载 此时自定义拦截器MyInterceptor已经挂载到DelegatingWebMvcConfiguration中。
2.4.拦截器加载

拦截器也是通过springboot自动装配类(WebMvcConfigurationSupport)加载进spring容器的

2.4.1.拦截器加载

// WebMvcConfigurationSupport public RequestMappingHandlerMapping requestMappingHandlerMapping( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager @Qualifier("mvcConversionService") FormattingConversionService conversionService @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) { // ... // 3.设置拦截器 mapping.setInterceptors(getInterceptors(conversionService resourceUrlProvider)); // ... return mapping; } // WebMvcConfigurationSupport protected final Object[] getInterceptors( FormattingConversionService mvcConversionService ResourceUrlProvider mvcResourceUrlProvider) { if (this.interceptors == null) { // 创建默认的InterceptorRegistry InterceptorRegistry registry = new InterceptorRegistry(); addInterceptors(registry); registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService)); registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider)); // 原始拦截器的包装在这里 this.interceptors = registry.getInterceptors(); } return this.interceptors.toArray(); } public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { // 2.3.EnableWebMvcConfiguration初始化时已经将自定义的WebConfiguration加载进来了 其中包含MyInterceptor private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); protected void addInterceptors(InterceptorRegistry registry) { // 这里将自定义的WebConfiguration交给了InterceptorRegistry this.configurers.addInterceptors(registry); } } class WebMvcConfigurerComposite implements WebMvcConfigurer { private final List<WebMvcConfigurer> delegates = new ArrayList<>(); public void addInterceptors(InterceptorRegistry registry) { // 遍历之前加载进来的自定义WebConfiguration for (WebMvcConfigurer delegate : this.delegates) { // 这里回调自定义的WebConfiguration的addInterceptors方法 // 看自定义addInterceptors方法逻辑 delegate.addInterceptors(registry); } } } // 自定义WebConfiguration public class WebConfiguration implements WebMvcConfigurer { // 把自定义的拦截器添加拦截器chain 并定义拦截规则 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); } } // 原始拦截器的包装 protected List<Object> getInterceptors() { return this.registrations.stream() .sorted(INTERCEPTOR_ORDER_COMPARATOR) .map(InterceptorRegistration::getInterceptor) .collect(Collectors.toList()); } // 看看InterceptorRegistration::getInterceptor方法 protected Object getInterceptor() { // 如果拦截与不拦截的正则过滤器均为空 那么这里直接返回 if (this.includePatterns.isEmpty() && this.excludePatterns.isEmpty()) { return this.interceptor; } String[] include = StringUtils.toStringArray(this.includePatterns); String[] exclude = StringUtils.toStringArray(this.excludePatterns); // 如果不为空 这里需要将我们的拦截器包装到MappedInterceptor对象中 // 我们自定义的拦截器MyInterceptor添加了匹配路径正则 所以会被包装成MappedInterceptor // 这个在我们在获取拦截的的时候会用到 MappedInterceptor mappedInterceptor = new MappedInterceptor(include exclude this.interceptor); if (this.pathMatcher != null) { mappedInterceptor.setPathMatcher(this.pathMatcher); } return mappedInterceptor; }

至此自定义拦截器被加载到RequestMappingHandlerMapping对象中.

2.4.2.拦截器包装

当我们加载到RequestMappingHandlerMapping中的拦截器有可能属于WebRequestInterceptor类型 需要将该类型的拦截器转换成HandlerInterceptor类型 所以对拦截器做了如下转换 这个转换也是在spring bean初始化的时候处理 请看下图

切面和拦截器顺序是固定的吗(拦截器Interceptor与适配器)(3)

spring初始化拦截器调用链

AbstractAutowireCapableBeanFactory是所有spring bean初始化都要走的流程 明显该动作是在RequestMappingHandlerMapping执行自定义init方法之前执行的回调 具体执行回调的后置处理器为ApplicationContextAwareProcessor.我们看代码

// ApplicationContextAwareProcessor public Object postProcessBeforeInitialization(final Object bean String beanName) throws BeansException { // ... invokeAwareInterfaces(bean); return bean; } private void invokeAwareInterfaces(Object bean) { // .... if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } // ApplicationObjectSupport public final void setApplicationContext(@Nullable ApplicationContext context) throws BeansException { if (context == null && !isContextRequired()) { // Reset internal context state. this.applicationContext = null; this.messageSourceAccessor = null; } else if (this.applicationContext == null) { // ... initApplicationContext(context); } else { // ... } } // 拦截器规范化 // AbstractHandlerMapping 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"); } this.adaptedInterceptors.add(adaptInterceptor(interceptor)); } } } // AbstractHandlerMapping // 这里将EnableWebMvcConfiguration加载的拦截器转换到了adaptedInterceptors成员变量中 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()); } }2.5.拦截器获取

接着回到DispatcherServlet的解析请求的核心方法

protected void doDispatch(HttpServletRequest request HttpServletResponse response) throws Exception { try { // 省略... try { // ... // mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest response); return; } // A.根据HandlerMethod获取适配器RequestMappingHandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // 省略 last-modified... String method = request.getMethod(); // B.调用拦截器的前置处理 if (!mappedHandler.applyPreHandle(processedRequest response)) { return; } // 通过适配器完成controller对应method的调用(下节分享) mv = ha.handle(processedRequest response mappedHandler.getHandler()); // 省略视图解析... // C.调用拦截器的后置处理 mappedHandler.applyPostHandle(processedRequest response mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // ... } // 全局异常处理器(下下节分享) processDispatchResult(processedRequest response mappedHandler mv dispatchException); } catch (Exception ex) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler ex); } catch (Throwable err) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler new NestedServletException("Handler processing failed" err)); } }2.5.1拦截器获取

// DispatcherServlet protected 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; } // AbstractHandlerMapping(RequestMappingHandlerMapping) public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 1.获取HandlerMethod 就是找到哪个Controller的Method 用于方法的反射调用.这里包含method及待调用的bean Object handler = getHandlerInternal(request); // 2.获取Handler调用链 包含了所有的拦截器 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler request); // ... return executionChain; } protected HandlerExecutionChain getHandlerExecutionChain(Object handler HttpServletRequest request) { HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); // 还记得这个对象(adaptedInterceptors)吗 这个就是2.4.2.节拦截器规范会之后的存储对象 // 其中包含我们自定义的拦截器 for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { // 还记得2.4.1.包装拦截器时 如果有设置匹配路径时会被封装成MappedInterceptor 这里就用到了 MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; // 这里是匹配http请求的url 如果能匹配上才把该过滤器添加到此次请求的拦截器中 if (mappedInterceptor.matches(lookupPath this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }2.6.拦截器执行

再来看DisptcherServlet的doDisptach方法

protected void doDispatch(HttpServletRequest request HttpServletResponse response) throws Exception { try { // 省略... try { //... // B.调用拦截器的前置处理 if (!mappedHandler.applyPreHandle(processedRequest response)) { return; } // 完成controller对应method的调用(下节分享) mv = ha.handle(processedRequest response mappedHandler.getHandler()); // C.调用拦截器的后置处理 mappedHandler.applyPostHandle(processedRequest response mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // ... } // 全局异常处理器(下下节分享) 该方法中也包含triggerAfterCompletion方法 即D.拦截器执行完毕回调 processDispatchResult(processedRequest response mappedHandler mv dispatchException); } catch (Exception ex) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler ex); } catch (Throwable err) { // D.拦截器执行完毕回调 triggerAfterCompletion(processedRequest response mappedHandler new NestedServletException("Handler processing failed" err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { // E.并发执行完成回调 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest response); } } else { // Clean up any resources used by a multipart request. // 这里是清除文件上传的内存缓存 我们一般通过multipart/form-data头处理文件上传 if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }2.6.1.前置回调

前置处理就是上面(2.6)B的位置

// HandlerExecutionChain boolean applyPreHandle(HttpServletRequest request HttpServletResponse response) throws Exception { // 获取拦截器(包含自定义的MyInterceptor) HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i ) { HandlerInterceptor interceptor = interceptors[i]; // 调用前置处理方法 这里的interceptor也有子集定义的拦截器MyInterceptor // 这里就是执行自定义拦截器的前置处理方法 // 这里的handler就是从RequestMappingHandlerMapping获取到的 // HandlerMethod(包含待调用的controller的方法及controller对象) if (!interceptor.preHandle(request response this.handler)) { triggerAfterCompletion(request response null); return false; } this.interceptorIndex = i; } } return true; }2.6.2.后置回调

后置处理就是上面(2.6)C的位置

// HandlerExecutionChain void applyPostHandle(HttpServletRequest request HttpServletResponse response @Nullable ModelAndView mv) throws Exception { // 获取拦截器(包含MyInterceptor) HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; // 执行拦截器后置操作(包含MyInterceptor) interceptor.postHandle(request response this.handler mv); } } }2.6.3.执行完成回调

后置处理就是上面(2.6)D的位置

// HandlerExecutionChain private void triggerAfterCompletion(HttpServletRequest request HttpServletResponse response @Nullable HandlerExecutionChain mappedHandler Exception ex) throws Exception { if (mappedHandler != null) { // 完成自定义回调 mappedHandler.triggerAfterCompletion(request response ex); } throw ex; } void triggerAfterCompletion(HttpServletRequest request HttpServletResponse response @Nullable Exception ex) throws Exception { // 获取拦截器(包含MyInterceptor) HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; try { // 执行拦截器controller方法执行完毕回调操作(包含MyInterceptor) interceptor.afterCompletion(request response this.handler ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception" ex2); } } } }2.6.4.并发执行已开始回调

并发执行已开始回调就是上面(2.6)E的位置

// HandlerExecutionChain void applyAfterConcurrentHandlingStarted(HttpServletRequest request HttpServletResponse response) { // 获取拦截器(包含MyInterceptor) HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; if (interceptor instanceof AsyncHandlerInterceptor) { try { AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) interceptor; // 执行并发完成回调 asyncInterceptor.afterConcurrentHandlingStarted(request response this.handler); } //... } } } }3.适配器加载(预告)

适配器的加载与路径映射器(RequestMappingHandlerMapping)的加载基本一致 也是通过EnableWebMvcConfiguration加载进来的 接着看代码吧

// EnableWebMvcConfiguration @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager @Qualifier("mvcConversionService") FormattingConversionService conversionService @Qualifier("mvcValidator") Validator validator) { RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(contentNegotiationManager conversionService validator); adapter.setIgnoreDefaultModelOnRedirect( this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); return adapter; } // WebMvcConfigurationSupport @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter( @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager @Qualifier("mvcConversionService") FormattingConversionService conversionService @Qualifier("mvcValidator") Validator validator) { // 1.这里就是new RequestMappingHandlerAdapter() RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); // 省略各种配置加载... // 下期分享方法调用时再来分详细拆解 return adapter; }

spring加载的逻辑同RequestMappingHandlerMapping一致,下期也会像RequestMappingHandlerMapping一样画一幅RequestMappingHandlerAdapter一样的加载流程图.再回到DispatcherServlet处理每次请求的主流程doService->doDispatch方法

// DisptcherServlet protected void doDispatch(HttpServletRequest request HttpServletResponse response) throws Exception { // 我们看看每次请求是如何获取HandlerAdapter的 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); } protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { // 这里的handler就是从上一步getHandler中带来的HandlerMethod if (this.handlerAdapters != null) { // 这里的handlerAdapters也是通过onRefresh方法加载到DispatcherServlet对象中 for (HandlerAdapter adapter : this.handlerAdapters) { // 这里主要看RequestMappingHandlerAdapter的supports方法 if (adapter.supports(handler)) { return adapter; } } } } // AbstractHandlerMethodAdapter(RequestMappingHandlerAdapter) @Override public final boolean supports(Object handler) { // 1.这里handler就是从上期RequestMappingHandlerMapping中获取的HandlerMethod(包含controller待执行的method) // 2.supportsInternal方法默认返回true return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } @Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }

到此我们知道返回的HandlerAdapter为RequestMappingHandlerAdapter.

4.思考
  • 拦截器一共有4种回调方式 当我们前置回调碰到异常时 后置回调执行完成回调还会正常进行吗?这种逻辑与我们定义aop切面到全部的controller上有什么区别呢?

猜您喜欢: