在spring中,filter都默认继承OncePerRequestFilter,但为什么要这样呢? 
OncePerRequestFilter顾名思义,他能够确保在一次请求只通过一次filter,而不需要重复执行。

/**
* 过滤器基类,旨在确保每个请求调度在任何servlet容器上执行一次执行。
* 它提供了一个带有HttpServletRequest和HttpServletResponse参数的{@link #doFilterInternal}方法。
*/
public abstract class OncePerRequestFilter extends GenericFilterBean {//附加到“已过滤”请求属性的过滤器名称的后缀。public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED"; //这个doFilter实现存储“已经过滤”的请求属性,如果该属性已经存在,则不进行再次过滤。//@see #getAlreadyFilteredAttributeName@Overridepublic final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)throws ServletException, IOException {if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {throw new ServletException("OncePerRequestFilter just supports HTTP requests");}HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;if (hasAlreadyFilteredAttribute || skipDispatch(httpRequest) || shouldNotFilter(httpRequest)) {// 继续而不调用此过滤器...filterChain.doFilter(request, response);}else {// 调用这个过滤器…request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);try {doFilterInternal(httpRequest, httpResponse, filterChain);}finally {// 删除此请求的“已过滤”请求属性。request.removeAttribute(alreadyFilteredAttributeName);}}}/*** 返回表明请求已被过滤的请求属性的名称。*/protected String getAlreadyFilteredAttributeName() {// 如果没有可用的过滤器名,则为{@code null}String name = getFilterName();if (name == null) {name = getClass().getName();}return name + ALREADY_FILTERED_SUFFIX;}private boolean skipDispatch(HttpServletRequest request) {if (isAsyncDispatch(request) && shouldNotFilterAsyncDispatch()) {return true;}if (request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE) != null && shouldNotFilterErrorDispatch(){return true;}return false;}/*** 在Servlet 3.0中引入的调度器类型{@code javax.servlet.DispatcherType.ASYNC}意味着一个过滤器可以在一个请求过程中在多个线* 程中被调用。 如果过滤器当前在异步分派中执行,则此方法返回{true}。*/protected boolean isAsyncDispatch(HttpServletRequest request) {return WebAsyncUtils.getAsyncManager(request).hasConcurrentResult();}/*** 请求处理是否处于异步模式,意味着退出当前线程后不会提交响应。*/protected boolean isAsyncStarted(HttpServletRequest request) {return WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted();}/*** 可以在子类中覆盖自定义过滤控件,返回{true}以避免过滤给定的请求。 默认实现总是返回{@code false}。*/protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {return false;}protected boolean shouldNotFilterAsyncDispatch() {return true;}protected boolean shouldNotFilterErrorDispatch() {return true;}/*** 与{@code doFilter}相同的合同,但保证在单个请求线程中每个请求只调用一次。* /protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException;}
    // GenericFilterBean.class//使这个过滤器的名称对子类可用。类似于GenericServlet的{@code getServletName()}。<p>默认使用FilterConfig的过滤器名称。//如果在Spring应用程序上下文中初始化为bean,那么它将返回到bean工厂中定义的bean名称。@Nullableprotected String getFilterName() {return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName);} 

--------------------- 
作者:Pazz枫 
来源:CSDN 
原文:https://blog.csdn.net/baidu_36327010/article/details/80538491?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

OncePerRequestFilter-源码解析相关推荐

  1. spring MVC cors跨域实现源码解析

    spring MVC cors跨域实现源码解析 名词解释:跨域资源共享(Cross-Origin Resource Sharing) 简单说就是只要协议.IP.http方法任意一个不同就是跨域. sp ...

  2. Spring Session源码解析

    AbstractHttpSessionApplicationInitializer,很明显它是一个初始化的类,它是一个抽象类,可以理解为一个公用的基类,然后看一下onStartup这个方法,最主要的方 ...

  3. Spring 源码解析 -- SpringWeb过滤器Filter解析

    简介 在上几篇文章中探索了请求处理相关的代码,本篇开始探索请求处理前的一些操作代码,如Filter.本篇探索Filter初始化.请求处理等相关代码. 前言 说先简单的定义相关的测试代码: 启动类: i ...

  4. spring boot 源码解析23-actuate使用及EndPoint解析

    前言 spring boot 中有个很诱人的组件–actuator,可以对spring boot应用做监控,只需在pom文件中加入如下配置即可: <dependency><group ...

  5. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  6. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

  7. 谷歌BERT预训练源码解析(一):训练数据生成

    目录 预训练源码结构简介 输入输出 源码解析 参数 主函数 创建训练实例 下一句预测&实例生成 随机遮蔽 输出 结果一览 预训练源码结构简介 关于BERT,简单来说,它是一个基于Transfo ...

  8. Gin源码解析和例子——中间件(middleware)

    在<Gin源码解析和例子--路由>一文中,我们已经初识中间件.本文将继续探讨这个技术.(转载请指明出于breaksoftware的csdn博客) Gin的中间件,本质是一个匿名回调函数.这 ...

  9. Colly源码解析——结合例子分析底层实现

    通过<Colly源码解析--框架>分析,我们可以知道Colly执行的主要流程.本文将结合http://go-colly.org上的例子分析一些高级设置的底层实现.(转载请指明出于break ...

  10. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

最新文章

  1. 在线作图|如何绘制带分组的散点图
  2. java 反射机制_Java反射机制原理探究
  3. 操作系统CnetOS_7—systemd管理实践指南
  4. hello python jpush api_jpush python服务器端
  5. 区分JAVA中的对象和引用
  6. nodejs 快速搭建接口
  7. boost::hana::alignof_用法的测试程序
  8. SQL 进行数据的更新和插入
  9. Centos7更换阿里云yum源
  10. 虚拟机中那些可以作为root对象_java虚拟机面试题及答案整理
  11. 从科技到“科技亲”,2019 IBM 中国论坛干货分享
  12. 【强化学习】表格型求解方法总结:基于表格型方法(Tabular Methods)的规划(Planning)和学习(Learning)
  13. 零基础学python要多久-零基础学Python要多久
  14. python 随机请求头_为了爬虫换个头,我用python实现三种随机请求头方式!
  15. string 类简介和例程
  16. html5中drag//drop拖曳效果的用法
  17. python: 列表的方法
  18. C语言新思路跟未来教育哪个好,计算机等级考试用什么书好 未来教育的书怎么样?貌似网上评价很高...
  19. 基于SSM 的图书馆管理系统
  20. 对称密钥和非对称密钥有什么区别,区别在哪里

热门文章

  1. Bash : test 命令
  2. 用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现
  3. 科沃斯旺宝与阿里云联合参加通信展
  4. spice server dpkg-buildpackage 打包编译备忘
  5. 使用typedef声明新类型及函数指针
  6. ios 应用 开发流程。。。
  7. With在sql server 2005中的用法
  8. Foundation HTML5 Canvas中的2处错误
  9. 使用VS进行工作流开发系列博客1-So You Want to Develop Custom Workflows in Visual Studio... - The Blog Series...
  10. Caffe官方教程翻译(8):Brewing Logistic Regression then Going Deeper