龙空技术网

拦截器(Interceptor)与适配器(HandlerAdapter)

上进的小镇青年 894

前言:

今天大家对“拦截请求工具”大体比较讲究,大家都想要知道一些“拦截请求工具”的相关知识。那么小编同时在网摘上搜集了一些关于“拦截请求工具””的相关文章,希望小伙伴们能喜欢,大家快快来学习一下吧!

前言:前一节已经介绍完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自动配置文件

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类结构关系图

DispatcherServlet自动装配UML

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

// WebMvcConfigurationSupportpublic 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对象的呢?

@Componentpublic 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.拦截器加载

// WebMvcConfigurationSupportpublic RequestMappingHandlerMapping requestMappingHandlerMapping(    @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,    @Qualifier("mvcConversionService") FormattingConversionService conversionService,    @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {	// ...    // 3.设置拦截器    mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));	// ...    return mapping;}// WebMvcConfigurationSupportprotected 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);        }    }}// 自定义WebConfigurationpublic 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初始化的时候处理,请看下图

spring初始化拦截器调用链

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

// ApplicationContextAwareProcessorpublic 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);    }}// ApplicationObjectSupportpublic 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 {        // ...    }}// 拦截器规范化// AbstractHandlerMappingprotected 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拦截器获取
// DispatcherServletprotected 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的位置

// 	HandlerExecutionChainboolean 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的位置

// 	HandlerExecutionChainvoid 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的位置

// 	HandlerExecutionChainprivate 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的位置

// 	HandlerExecutionChainvoid 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@Overridepublic 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@Beanpublic 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方法

// DisptcherServletprotected 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)@Overridepublic final boolean supports(Object handler) {    // 1.这里handler就是从上期RequestMappingHandlerMapping中获取的HandlerMethod(包含controller待执行的method)    // 2.supportsInternal方法默认返回true    return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));}@Overrideprotected boolean supportsInternal(HandlerMethod handlerMethod) {    return true;}

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

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

标签: #拦截请求工具