过滤器和拦截器的使用和原理

news2024/11/14 6:19:39

1. 过滤器和拦截器

过滤器(Filter)
拦截器(Interceptor)
在这里插入图片描述

1.1 区别

过滤器和拦截器触发时机不一样

  • 过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。
  • 请求结束返回也是,是在servlet处理完后,返回给前端之前

拦截器可以获取IOC容器中的各个bean,而过滤器就不行

  • 因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。
  • 过滤器是JavaEE标准只需依赖servlet api ,不需要依赖spring

过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射

Filter依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用

Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。

Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此拦截器可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。

最简单明了的区别就是:

  • 过滤器可以修改request,而拦截器不能
  • 过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
  • 拦截器可以调用IOC容器中的各种依赖,而过滤器不能
  • 过滤器只能在请求的前后使用,而拦截器可以详细到每个方法

本质区别
   从灵活性上说拦截器功能更强大些,Filter能做的事情它都能做,而且可以在请求前,请求后执行,比较灵活。
   Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验,其他的还是建议用interceptor。

1.2 执行顺序

过滤前-----拦截前-----Action处理-----拦截后-----过滤后。

【过滤器】开始执行
【拦截器】处理前
com.boot.filter.controller.HelloController
Controller:Hello World!
【拦截器】处理中
【拦截器】耗时:20ms
【拦截器】处理后
【拦截器】耗时:20ms
【过滤器】耗时:27ms
【过滤器】结束执行

过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息
拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数
切片(Aspect): 可以拿到方法的参数,但是却拿不到http请求和响应的对象
在这里插入图片描述
在这里插入图片描述

2. 过滤器

过滤器是处于客户端与服务器资源文件之间的一道过滤网

在访问资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以对响应进行过滤,拦截或修改响应

两种实现方式
1、使用spring boot提供的FilterRegistrationBean注册Filter
2、使用原生servlet注解定义Filter

两种方式的本质都是一样的,都是去FilterRegistrationBean注册自定义Filter

2.1 Filter

2.1.1 示例

2.1.1.1 自定义一个TimeFilter类
@Component
@WebFilter(urlPatterns = {
   "/*"})
public class TimeFilter implements Filter{
   
    Logger log = LoggerFactory.getLogger(Logger.class);
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
   
        log.info("【过滤器】初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
   
        log.info("【过滤器】开始执行");
        Long startTime = System.currentTimeMillis();
        filterChain.doFilter(servletRequest, servletResponse);
        log.info("【过滤器】耗时:" + (System.currentTimeMillis() - startTime)+"ms");
        log.info("【过滤器】结束执行");
    }

    @Override
    public void destroy() {
   
        log.info("【过滤器】销毁");
    }
}
2.1.1.2 配置方式
  • @WebFilter注解的urlPatterns属性配置了哪些请求可以进入该过滤器,/*表示所有请求
  • 除了在过滤器类上加注解外,我们也可以通过FilterRegistrationBean来注册过滤器。定义一个TimeFilterConfig类,加上@Configuration注解表明其为配置类,然后通过FilterRegistrationBean来注册过滤器。
    @Configuration
    public class TimeFilterConfig {
         
        @Bean
        public FilterRegistrationBean timeFilter() {
         
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            TimeFilter timeFilter = new TimeFilter();
            filterRegistrationBean.setFilter(timeFilter);
    
            List<String> urlList = new ArrayList<>();
            urlList.add("/*");
    
            filterRegistrationBean.setUrlPatterns(urlList);
            return filterRegistrationBean;
        }
    }
    
2.1.1.3 测试
@RestController
public class HelloController {
   
    Logger log = LoggerFactory.getLogger(Logger.class);

    @RequestMapping("hello")
    public void hello(){
   
        log.info("Controller:Hello World!");
    }
}

运行结果:

【过滤器】开始执行
ControllerHello World!
【过滤器】耗时:26ms
【过滤器】结束执行

2.2 OncePerRequestFilter

2.2.1 概念

在Spring中,Filter默认继承OncePerRequestFilter

Filter 可以在 Servlet 执行之前或之后调用。当请求被调度给一个 Servlet 时,RequestDispatcher 可能会将其转发给另一个 Servlet。另一个 Servlet 也有可能使用相同的 Filter。在这种情况下,同一个 Filter 会被调用多次。

OncePerRequestFilter是 Spring 框架中的一个抽象类,

  • 用于确保在每个请求中只执行一次过滤操作
  • 它通常用于实现一些需要在每个请求中执行一次的逻辑

    比如日志记录、身份验证等

可以继承 OncePerRequestFilter。

Spring 保证 OncePerRequestFilter 只对指定请求执行一次

2.2.1.1 一般只会请求一次,那为什么还要使用该注解

此方法是**为了兼容不同的web container**,也就是说并不是所有的container都是我们期望的只过滤一次,servlet版本不同,执行过程也不同

  • servlet2.3中Filter会经过一切请求,包括服务器内部使用的forward转发请求<%@ include file=”/login.jsp”%>的情况
  • servlet2.4中Filter默认情况下只过滤外部提交的请求forward和include这些内部转发都不会被过滤
  • 所以,若是在Spring环境下使用Filter的话,还是继承OncePerRequestFilter吧,而不是直接实现Filter接口

2.2.2 OncePerRequestFilter源码解读

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.web.filter;

import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.async.WebAsyncUtils;

public abstract class OncePerRequestFilter extends GenericFilterBean {
   
    // 常量,表示已经过滤的请求属性后缀
    public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";

    // 构造函数
    public OncePerRequestFilter() {
   
    }

    // 核心过滤方法,确保每个请求只执行一次过滤操作
    public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
   
        // 检查请求和响应是否为 HTTP 类型
        if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
   
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            // 获取已经过滤的请求属性名称
            String alreadyFilteredAttributeName = this.getAlreadyFilteredAttributeName();
            // 检查请求是否已经被过滤
            boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
            // 检查是否需要跳过过滤
            if (!this.skipDispatch(httpRequest) && !this.shouldNotFilter(httpRequest)) {
   
                if (hasAlreadyFilteredAttribute) {
   
                    // 如果是错误调度类型,执行嵌套错误调度过滤
                    if (DispatcherType.ERROR.equals(request.getDispatcherType())) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2089993.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科研项目经费管理,降本增效的不二之选

国内外主流的 10 款科研项目经费管理系统对比&#xff1a;PingCode、Worktile、Colloa科研项目管理平台、云科研管理系统、智方科研管理系统、NIH Grants、NSF – National Science Foundation、IDRC、Bill & Melinda Gates Foundation、Canadian Institutes of Health Res…

媲美Flux pro! Ideogram 发布了 2.0 图像生成模型, 照片级真实感和高质量文本渲染!

Ideogram 发布了 2.0 模型,图像生成质量大幅提高&#xff0c;产品易用性改善&#xff0c;文字生成能力也提升许多。Ideogram 2.0 在图像快速对齐、照片级真实感和文本渲染质量方面取得了显著进步。人工评估一致认为 Ideogram 2.0 比 Flux Pro 和 DALLE 3 有了显著改进。尽管我们…

人工智能的可解释性(XAI) | 使用LIME

人工智能&#xff08;AI&#xff09;的广阔领域近年来经历了巨大的增长。随着每年更新、更复杂的模型问世&#xff0c;人工智能模型已经开始以无人能预测的速度超越人类智力。但是&#xff0c;随着我们得到更准确和精确的结果&#xff0c;解释这些模型所采取的复杂数学决策背后…

[翻译+笔记] 用于视频生成的Diffusion Model

这次翻译笔记的博客是https://lilianweng.github.io/posts/2021-07-11-diffusion-models/ 在阅读这篇博客前, 推荐先对Diffusion Model进行了解. 可以看我的笔记: https://blog.csdn.net/wjpwjpwjp0831/article/details/141524088 视频相关的任务向来是比图像更有挑战性, 这是…

涉密载体管控系统DW-S402|实现载体全寿命管控

为加强涉密载体使用管控&#xff0c;按照预防为主&#xff0c;强化监督&#xff0c;在满足各级保密规定前提下&#xff0c;方便涉密载体的使用和管理&#xff0c;确保涉密载体保密安全。 现有涉密载体使用过程中&#xff0c;存在手工登记台账耗工耗时、领用情况不直观、违规带…

史上最全Android UI界面设计尺寸!点击收藏

作为一名 UI 设计师&#xff0c;在进行 Android UI 设计之前&#xff0c;首先需要明确 Android 系统与 iOS 系统之间的主要区别。Android 系统是开源的&#xff0c;而 iOS 系统则是不开源的。虽然 Android 系统的开源特性对于交互设计师是有益的&#xff0c;但它也带来了一些挑…

白立新谈命运三重奏:《黑神话:悟空》中的人生思考

文 | 头部财经首席评论员白立新 发布 | 头部财经 top168.com 导语&#xff1a;《黑神话&#xff1a;悟空》中三个悟空形象演绎命运三种属性。老者悟空象征确定性&#xff0c;历经沧桑&#xff0c;蕴含世界法则&#xff1b;玩家操作悟空代表能动性&#xff0c;承载玩家意志影响…

seaborn:一个超炫的数据可视化Python库

我是东哥&#xff0c;专注于分享Python技术的自媒体人。今天&#xff0c;我将带你深入了解一个非常有趣的Python库——Seaborn。无论你是刚入门的Python小白&#xff0c;还是希望提升数据可视化技能的技术小白&#xff0c;相信这篇文章都会对你有所帮助。 项目地址&#xff1a…

数学符号-西格玛

西格玛”是希腊字母&#xff0c;也有念作“西玛”“希玛”等各种读法&#xff0c;符号是∑,英文译音是Sigma, 表示数学中的求和号&#xff0c;是数学中常用的符号&#xff0c;主要用于求多项数的和&#xff0c;用∑表示 ∑下面的小字,如i1表示从i1开始求和 上面的小字&#xf…

【网络世界】网络层

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 网络层 &#x1f4c1; IPV4 &#x1f4c2; 什么是IP地址 &#x1f4c2; 网段划分 &#x1f4c2; 特殊IP &#x1f4c2; 内网和公网 &#x1f4c2; IPV4的危机 &#x1f4c1; IP协议格式 &#x1f4c1; 路由 &#x1f…

【工具篇】高效记忆方法之AnKi工具

&#x1f60a;你好&#xff0c;我是南极。正在变强的路上不断地努力着&#x1f4aa; &#x1f514;今天和大家分享一些记忆的方法&#xff0c;以及推荐了一款用于复习和巩固知识的软件AnKi。 对我们程序员而言&#xff0c;平常学习的东西会比较多&#xff0c;有时呢学的东西会…

气势向前,豪华向上 全新BMW X3长轴距版全球首发,更大体量、更高价值、更多驾趣

X家族的中流砥柱&#xff0c;豪华中型SAV的引领者现代极简主义&#xff0c;原石切割般的型面&#xff0c;塑造纯粹的BMW X辨识度“以驾驶员为中心”和“以简释繁”&#xff0c;打造“中国专属”的精致豪华空间创新不止&#xff0c;驾趣依旧&#xff0c;探索未知的忠实伙伴 &…

Django+Vue二手交易平台的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 需要的环境3.2 Django接口层3.3 实体类3.4 config.ini3.5 启动类3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质创作者&…

钉钉好用吗?类似钉钉的内部知识库有哪些?

在数字化转型的浪潮中&#xff0c;企业对于高效、便捷的知识管理工具需求日益增长。 在企业管理领域&#xff0c;虽然钉钉作为一款功能全面的企业级即时通讯与协作平台&#xff0c;以其强大的知识管理功能受到了广泛认可&#xff0c;但市场上仍有许多其他优秀的知识管理工具可…

《苍穹外卖》电商实战项目(java)知识点整理(P1~P65)【上】

史上最完整的《苍穹外卖》项目实操笔记&#xff0c;跟视频的每一P对应&#xff0c;全系列10万字&#xff0c;涵盖详细步骤与问题的解决方案。如果你操作到某一步卡壳&#xff0c;参考这篇&#xff0c;相信会带给你极大启发。 《苍穹外卖》项目实操笔记【中】&#xff1a;P66~P…

phpstorm远程连接阿里云项目

1.安全组 打开端口3306&#xff0c;22 一、.远程连接mysql 1.1新建一个远程连接的用户&#xff08;root用户默认不能远程&#xff0c;不用修改&#xff09; -- 登录到MySQL mysql -u root -p -- 授权远程用户 GRANT ALL PRIVILEGES ON *.* TO 远程用户名% IDENTIFIED BY 远…

ffmpeg视频转切片m3u8并加密videojs播放hls.js播放dplayer播放(弹幕效果)

文章目录 学习链接步骤安装openssl生成一个enc.key文件生成加密串创建enc.keyinfo文件视频切分m3u8文件 web前端查看m3u8视频后台返回enc.key的接口videojs播放m3u8视频 其它videojs切换播放视频hls.js切换播放视频dplayer切换播放视频(弹幕) 学习链接 Java实现视频加密及播放…

redis主从同步

redis 相比于memcached可以永久缓存。 首先停掉mysql源码安装redis 1. 安装redis cd /root/redis-6.2.4 make # 直接make&#xff0c;里面已经配置过了 make install# 安装 cd utils/ ./install_server.sh需要在文件里面注释掉&#xff0c;systemd判断语句 vim install_s…

【GPT】Coze使用开放平台接口-【2】创建工作流-语音伪造检测工作流

在Coze使用开放平台接口-【1】创建插件&#xff0c;我们已经成功创建了开放平台的插件&#xff0c;也创建了对应的工具。本文档就根据创建好的插件&#xff0c;来创建对应的工作流&#xff0c;来让接口能够用起来。 下面直接用现成的插件快商通AI开放平台&#xff0c;来创建语音…

202408830使用python3给BGR3的裸图加上BMP图的文件头

202408830使用python3给BGR3的裸图加上文件头 2024/8/30 20:20 缘起&#xff0c;获取SONY索尼的8530的机芯的4K的BGR3的裸图。可以使用7-yuv打开了。 如果直接可以给这张YUV图加上BMP格式的文件头&#xff0c;就可以直接使用标准的图像处理软件/ACDSee5.0打开了&#xff01; 这…