说在前面
前期回顾
sharding-jdbc源码解析 更新完毕
spring源码解析 更新完毕
spring-mvc源码解析 更新完毕
spring-tx源码解析 更新完毕
spring-boot源码解析 更新完毕
rocketmq源码解析 更新完毕
dubbbo源码解析 更新完毕
netty源码解析 更新完毕
spring源码架构更新完毕
springmvc源码架构更新中
springboot源码架构计划中
github https://github.com/tianheframe
sharding-jdbc源码解析 更新完毕
rocketmq源码解析 更新完毕
seata 源码解析 更新完毕
dubbo 源码解析 更新完毕
netty 源码解析 更新完毕
源码解析
org.springframework.web.servlet.HandlerInterceptor 公共接口HandlerInterceptor,工作流接口,允许定制处理程序执行链。应用程序可以为特定的处理程序组注册任意数量的现有或自定义拦截器,以添加公共预处理行为,而不需要修改每个处理程序实现。在适当的HandlerAdapter触发处理程序本身的执行之前,将调用HandlerInterceptor。此机制可用于大量的预处理方面,例如用于授权检查,或用于语言环境或主题更改等公共处理程序行为。它的主要目的是允许分解出重复的处理程序代码。在异步处理场景中,当主线程退出而不呈现或调用postHandle和afterCompletion回调时,处理程序可能在单独的线程中执行。当并发处理程序执行完成时,请求被发送回去,以便继续呈现模型,并再次调用此契约的所有方法。
通常,拦截器链是为每个HandlerMapping bean定义的,共享其粒度。为了能够将某个拦截器链应用于一组处理程序,需要通过一个HandlerMapping bean映射所需的处理程序。拦截器本身在应用程序上下文中定义为bean,由映射bean定义通过其“拦截器”属性引用(在XML中:的)。HandlerInterceptor基本上类似于Servlet过滤器,但与后者相比,它只允许自定义预处理(带有禁止处理程序本身执行的选项)和自定义后处理。过滤器更强大,例如,它们允许交换传递到链中的请求和响应对象。请注意,过滤器是在web中配置的。应用程序上下文中的HandlerInterceptor。作为基本的指导原则,细粒度处理程序相关的预处理任务是HandlerInterceptor实现的候选任务,特别是分解出来的公共处理程序代码和授权检查。另一方面,筛选器非常适合于请求内容和视图内容处理,比如多部分表单和GZIP压缩。这通常显示当需要将筛选器映射到特定的内容类型(例如图像)或所有请求时。
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
拦截处理程序的执行。在HandlerMapping确定适当的处理程序对象之后调用,但在HandlerAdapter调用处理程序之前调用。DispatcherServlet在执行链中处理一个处理程序,该处理程序由任意数量的拦截器组成,处理程序本身位于执行链的末端。使用此方法,每个拦截器可以决定中止执行链,通常是发送HTTP错误或编写自定义响应。
void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
拦截处理程序的执行。在HandlerAdapter实际调用处理程序之后调用,但在DispatcherServlet呈现视图之前调用。可以通过给定的ModelAndView向视图公开其他模型对象。DispatcherServlet在执行链中处理一个处理程序,该处理程序由任意数量的拦截器组成,处理程序本身位于执行链的末端。通过这种方法,每个拦截器可以对一个执行进行后处理,以执行链的相反顺序应用。
void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
请求处理完成后的回调,即呈现视图后的回调。将在处理程序执行的任何结果上调用,从而允许适当的资源清理。注意:只有当这个拦截器的preHandle方法成功完成并返回true时才会被调用!与postHandle方法一样,该方法将在链中的每个拦截器上以相反的顺序调用,因此第一个拦截器将是最后一个被调用的拦截器。
org.springframework.web.servlet.AsyncHandlerInterceptor 使用在异步请求处理启动后调用的回调方法扩展HandlerInterceptor。当一个处理程序启动一个异步请求时,DispatcherServlet在没有调用postHandle和afterCompletion的情况下退出,就像它通常对同步请求所做的那样,因为请求处理的结果(例如ModelAndView)可能还没有准备好,并且将从另一个线程并发生成。在这样的场景中,会调用afterConcurrentHandlingStarted,从而允许实现在将线程释放到Servlet容器之前执行清理线程绑定属性等任务。当异步处理完成时,请求被分派到容器进行进一步处理。在这个阶段,DispatcherServlet调用预句柄、postHandle和afterCompletion。为了区分初始请求和异步处理完成后的后续分派,拦截器可以检查javax.servlet。DispatcherType javax.servlet。ServletRequest是“REQUEST”或“ASYNC”。注意,当异步请求超时或出现网络错误时,HandlerInterceptor实现可能需要执行工作。对于这种情况,Servlet容器不会分派,因此不会调用postHandle和afterCompletion方法。相反,拦截器可以注册以通过WebAsyncManager上的registerCallbackInterceptor和registerDeferredResultInterceptor方法跟踪异步请求。无论异步请求处理是否启动,都可以对来自preHandle的每个请求主动执行此操作。
void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
调用,而不是postHandle和afterCompletion,此时a处理程序正在并发执行。实现可以使用提供的请求和响应,但是应该避免以与处理程序的并发执行冲突的方式修改它们。这种方法的典型用法是清除线程局部变量。
org.springframework.web.servlet.handler.HandlerInterceptorAdapter AsyncHandlerInterceptor接口的抽象适配器类,用于简化仅前/仅后拦截器的实现。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; }
@Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { }
@Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
@Override public void afterConcurrentHandlingStarted( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { }
org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor 拦截器,它将配置的ConversionService放在请求范围中,以便在请求处理期间可用。请求属性名为“org.springframe .core.convert”。, ConversionService.class. getname()的值。
private final ConversionService conversionService;
conversionService
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException { request.setAttribute(ConversionService.class.getName(), this.conversionService); return true; }
org.springframework.web.servlet.resource.ResourceUrlProviderExposingInterceptor 将ResourceUrlProvider实例公开为请求属性的拦截器。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { request.setAttribute(RESOURCE_URL_PROVIDER_ATTR, this.resourceUrlProvider); return true; }
org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter 实现Servlet HandlerInterceptor接口并包装底层WebRequestInterceptor的适配器。
private final WebRequestInterceptor requestInterceptor;
requestInterceptor
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { this.requestInterceptor.preHandle(new DispatcherServletWebRequest(request, response)); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { this.requestInterceptor.postHandle(new DispatcherServletWebRequest(request, response), (modelAndView != null && !modelAndView.wasCleared() ? modelAndView.getModelMap() : null)); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { this.requestInterceptor.afterCompletion(new DispatcherServletWebRequest(request, response), ex); }
@Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) { if (this.requestInterceptor instanceof AsyncWebRequestInterceptor) { AsyncWebRequestInterceptor asyncInterceptor = (AsyncWebRequestInterceptor) this.requestInterceptor; DispatcherServletWebRequest webRequest = new DispatcherServletWebRequest(request, response); asyncInterceptor.afterConcurrentHandlingStarted(webRequest); } }
org.springframework.web.servlet.handler.MappedInterceptor 包含和委托对HandlerInterceptor的调用,以及拦截器应该应用的include(和可选排除)路径模式。还提供匹配逻辑来测试拦截器是否应用于给定的请求路径。MappedInterceptor可以直接注册到任何AbstractHandlerMethodMapping中。此外,通过AbstractHandlerMethodMapping(包括祖先ApplicationContext的)自动检测MappedInterceptor类型的bean,这实际上意味着拦截器在所有处理程序映射中都是“全局”注册的。
private final String[] includePatterns;
includePatterns
private final String[] excludePatterns;
excludePatterns
private final HandlerInterceptor interceptor;
interceptor,这里是适配器模式实现
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return this.interceptor.preHandle(request, response, handler); }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { this.interceptor.postHandle(request, response, handler, modelAndView); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { this.interceptor.afterCompletion(request, response, handler, ex); }
org.springframework.web.servlet.mvc.WebContentInterceptor 检查请求并准备响应的处理程序拦截器。检查支持的方法和所需的会话,并应用指定的CacheControl构建器。拦截器支持的所有设置也可以在AbstractController上设置。这个拦截器主要用于对HandlerMapping映射的一组控制器应用检查和准备。
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {// 校验方法是否合法 checkRequest(request); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up cache seconds for [" + lookupPath + "]"); } CacheControl cacheControl = lookupCacheControl(lookupPath); Integer cacheSeconds = lookupCacheSeconds(lookupPath); if (cacheControl != null) { if (logger.isDebugEnabled()) { logger.debug("Applying CacheControl to [" + lookupPath + "]"); } applyCacheControl(response, cacheControl); } else if (cacheSeconds != null) { if (logger.isDebugEnabled()) { logger.debug("Applying CacheControl to [" + lookupPath + "]"); } applyCacheSeconds(response, cacheSeconds); } else { if (logger.isDebugEnabled()) { logger.debug("Applying default cache seconds to [" + lookupPath + "]"); } prepareResponse(response); } return true; }
检查请求方法是否合法,进行缓存处理
@Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { }
@Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }
说在最后
本次解析仅代表个人观点,仅供参考。
扫码进入技术微信群
钉钉技术群qq技术群