sunny123456

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  1796 随笔 :: 22 文章 :: 24 评论 :: 226万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

OncePerRequestFilter
顾名思义,它能够确保在一次请求中只通过一次filter,而不会重复执行
是由Spring提供的抽象类
https://www.cnblogs.com/sjxbg/p/13475387.html

摘录自:https://www.jianshu.com/p/3d9b4cfe1a62

doFilter是整个过滤器最底层的概念Filter接口中的方法
所有过滤器都要实现Filter

复制代码
复制代码
package javax.servlet;

import java.io.IOException;

public interface Filter {
void init(FilterConfig var1) throws ServletException;

</span><span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> IOException, ServletException;

</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy();

}

复制代码
复制代码

而doFilterInternal是OncePerRequestFilter 中的一个抽象方法
阅读源码可知:
OncePerRequestFilter.doFilter方法中通过request.getAttribute判断当前过滤器是否已执行
若未执行过,则调用doFilterInternal方法,交由其子类实现

OncePerRequestFilter
顾名思义,它能够确保在一次请求中只通过一次filter,而不会重复执行
是由Spring提供的抽象类

复制代码
复制代码
package org.springframework.session.web.http;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

abstract class OncePerRequestFilter implements Filter {
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
private String alreadyFilteredAttributeName = this.getClass().getName().concat(".FILTERED");

OncePerRequestFilter() {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    </span><span style="color: rgba(0, 0, 255, 1)">if</span> (request <span style="color: rgba(0, 0, 255, 1)">instanceof</span> HttpServletRequest &amp;&amp; response <span style="color: rgba(0, 0, 255, 1)">instanceof</span><span style="color: rgba(0, 0, 0, 1)"> HttpServletResponse) {
        HttpServletRequest httpRequest </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletRequest)request;
        HttpServletResponse httpResponse </span>=<span style="color: rgba(0, 0, 0, 1)"> (HttpServletResponse)response;
        </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> hasAlreadyFilteredAttribute = request.getAttribute(<span style="color: rgba(0, 0, 255, 1)">this</span>.alreadyFilteredAttributeName) != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
        </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (hasAlreadyFilteredAttribute) {
            filterChain.doFilter(request, response);
        } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
            request.setAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName, Boolean.TRUE);

            </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.doFilterInternal(httpRequest, httpResponse, filterChain);
            } </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)"> {
                request.removeAttribute(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.alreadyFilteredAttributeName);
            }
        }

    } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ServletException("OncePerRequestFilter just supports HTTP requests"<span style="color: rgba(0, 0, 0, 1)">);
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doFilterInternal(HttpServletRequest var1, HttpServletResponse var2, FilterChain var3) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> init(FilterConfig config) {
}

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> destroy() {
}

}

复制代码
复制代码
常识上都认为,一次请求本来就只filter一次,为什么还要由此特别限定呢?
往往我们的常识和实际的实现并不真的一样,经过一番资料的查阅,此方法是为了兼容不同的web container
也就是说并不是所有的container都入我们期望的只过滤一次,servlet版本不同,执行过程也不同
因此,为了兼容各种不同运行环境和版本,默认filter继承OncePerRequestFilter是一个比较稳妥的选择。
posted on   sunny123456  阅读(995)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示