netty springmvc_springmvc源码架构解析之HandlerMapping
说在前面
前期回顾
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技术群
netty springmvc_springmvc源码架构解析之HandlerMapping相关推荐
- yolov3之pytorch源码解析_springmvc源码架构解析之view
说在前面 前期回顾 sharding-jdbc源码解析 更新完毕 spring源码解析 更新完毕 spring-mvc源码解析 更新完毕 spring-tx源码解析 更新完毕 spring-boot源 ...
- spring boot 源码_springboot源码架构解析listener
说在前面 前期回顾 sharding-jdbc源码解析 更新完毕 spring源码解析 更新完毕 spring-mvc源码解析 更新完毕 spring-tx源码解析 更新完毕 spring-boot源 ...
- OpenBLAS学习一:源码架构解析GEMM分析
1. 什么是OpenBLAS 1.1. BLAS 1.2. 功能 1.3. 使用 1.3.1. 编译 1.3.2. 调用 1.3.3. 定制化 build 2. OpenBLAS实现 2.1. TOP ...
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
原文 Go netpoll I/O 多路复用构建原生网络模型之源码深度解析 导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go ...
- dubbo源码深度解析_Spring源码深度解析:手把手教你搭建Spring开发环境
Spring环境搭建流程,如果是第一次接触spring源码的环境搭建,确实还是比较麻烦的. 作者使用的编译器为目前流行的lntelliJ IDEA,版本为2018旗舰版.Eclipse用户还需要自己揣 ...
- 车载USB DVR(行车记录仪)的源码架构浅析(基于AndroiidM)
基于AndroiidM的USB DVR的源码架构浅析,主要讲述大概流程,以便于分析问题. APP层 源码路径: AndroidM/vendor/mediatek/proprietary/package ...
- 从零手写pm-cli脚手架,统一阿里拍卖源码架构
前言 ❝ 原文地址:https://github.com/Nealyang/PersonalBlog ❞ 脚手架其实是大多数前端都不陌生的东西,基于前面写过的两篇文章: 前端源码架构在拍卖详情页上的探 ...
- 【笔记-vue】《imooc-vue.js高仿饿了么》、《imooc-vue 音乐app》、《imooc-vue.js源码全方位解析》
20170709 - 20171128:<imooc-vue.js高仿饿了么> 一.第一章 课程简介 1-1课程简介 1.需求分析-脚手架工具-数据mock-架构设计-代码编写-自测-编译 ...
- Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(三)-Controller 解析
在之前的博客中Spring源码深度解析(郝佳)-学习-源码解析-Spring MVC(一),己经对 Spring MVC 的框架做了详细的分析,但是有一个问题,发现举的例子不常用,因为我们在实际开发项 ...
最新文章
- 如何在windows xp下使用ntfs权限控制
- JSON.stringify()和JSON.parse()分别是什么
- PowerDesigner的使用二
- Command NetWork(POJ-3164)
- 阿里云服务器ECS选型
- Leetcode每日一题:38.Count and Say(外观数列)
- C# 组成结构、数据类型、运算符 以及 基本语法练习
- paip.验证码识别---使用字符集的选取
- Redis后门植入分析报告
- iOS-详解没有dSYM文件 如何解析iOS崩溃日志
- Paxos算法原理与推导
- 使用JAXB实现JAVA对象和XML字符串的互相转换
- 微信,该文件已过期或已被清理
- 影响员工满意度下降的因素
- 【学习笔记】H5性能测试
- 如何对图像进行卷积操作
- 高等数学二从零开始学习的总结笔记(持续更新)
- ublox ubx协议 c语言,Ublox-M8N GPS接收机UBX协议解析
- 谷歌语音对接-GoogleAssistant-smart-home
- Linux内核之各个SIG信号含义
热门文章
- Julia女神告诉我任何一家企业本质上都是一家软件公司
- linux上还原自主nuget包需要注意的问题
- C#使用Xamarin开发可移植移动应用进阶篇(8.打包生成安卓APK并精简大小),附源码
- asp.net core mvc实现伪静态功能
- ArcGIS,Envi软件中的卷帘工具使用及对比
- linux之systemctl设置自定义服务
- linux之vim操作快速跳到下一个空格和上一个空格命令
- linux之tmp文件夹
- Android之调用js常见错误
- 判断一个字符串是否包含另一个字符串(用java但是不能用index()这个函数)