过滤器与拦截器区别、应用场景介绍

news2024/11/20 18:21:38

我们在进行 Web 应用开发时,时常需要对请求进行拦截或处理,故 Spring 为我们提供了过滤器和拦截器来应对这种情况。

那么两者之间有什么不同呢?本文将详细讲解两者的区别和对应的使用场景。

过滤器

过滤器是一种在 Java Web 应用中用于处理请求和响应的组件。它可以拦截客户端发起的请求,也可以拦截服务器返回的响应,对它们进行处理或者修改。

过滤器属于Servlet规范的一部分,过滤器是用于执行过滤任务的对象,它可以在请求到达 Servlet 之前或响应发送给客户端之前执行一些额外的逻辑。

应用场景

日志记录: 过滤器常用于记录请求和响应的日志,包括请求的路径、参数、处理时间等信息。

身份验证和授权: 过滤器可以用于实现身份验证和授权逻辑,例如检查用户是否已登录,是否具有足够的权限访问某个资源。

防御性编程: 过滤器可以用于对请求进行安全检查,防止潜在的攻击,比如阻止恶意请求、XSS(跨站脚本攻击)等。

性能监控: 过滤器可以用于收集请求的处理时间、资源使用等信息,用于性能监控和优化。

如何创建过滤器

Filter 的生命周期对应的三个关键方法:

  • init():当请求发起时,会调用 init() 方法初始化 Filter 实例,仅初始化一次。若需要设置初始化参数的时可调用该方法。

  • doFilter():拦截要执行的请求,对请求和响应进行处理。

  • destroy():请求结束时调用该方法销毁 Filter 的实例。

下面将介绍二种方法创建 Filter。

实现 Filter 接口

1. 创建 Filter 处理类,实现 Filter 接口,加上 @WebFilter 注解配置拦截 Url,但是不能指定过滤器执行顺序,也可通过 web.xml 配置。

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 用于完成 Filter 的初始化
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        System.out.println("过滤器已经拦截成功!!!");
        // 执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        // 用于 Filter 销毁前,完成某些资源的回收;
        Filter.super.destroy();
    }
}

2. 在启动类添加注解 @ServletComponentScan ,让 Spring 可以扫描到。

@SpringBootApplication
@ServletComponentScan
public class MyFilterDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyFilterDemoApplication.class, args);
    }
}

3. 创建 Controller 发起 Url 请求。

@RestController
public class MyFilterController {
    @GetMapping("/testFilter")
    public String testFilter(){
        return "Hello World";
    }
}

通过@Component

1. 创建 Filter 处理类,实现 javax.servlet.Filter 接口,加 @Component 注解。

可以使用 @Order 注解保证过滤器执行顺序,不加则按照类名排序。且过滤器不能指定拦截的url , 只能默认拦截全部

@Component
@Order(1)
public class MyComponentFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        System.out.println("我是过滤器1已经拦截成功!!!");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
@Component
@Order(2)
public class MyComponentFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 
    
        System.out.println("我是过滤器2已经拦截成功!!!");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

2. 2-3 步骤同 1.2.1,结果如下。

拦截器 

拦截器(Interceptor)是一种在应用程序处理请求和响应的过程中,插入自定义处理逻辑的组件。拦截器是一种常见的设计模式,它允许在核心处理逻辑之前或之后执行额外的操作。

一般出现在Spring MVC中,Spring MVC 中的拦截器实现原理主要基于 Spring 框架的 AOP和 HandlerInterceptor 接口。

 应用场景

敏感字检测:过滤器可以用于检测请求中的文本内容,包括表单提交、请求参数等,以查找是否包含敏感字。异常处理: 拦截器可以用于捕获和处理在请求处理过程中发生的异常。这使得开发者可以集中处理异常情况,返回合适的错误响应或记录异常信息。日志记录: 拦截器可用于记录请求和响应的日志信息,包括请求参数、响应状态码、执行时间等。国际化和本地化: 拦截器可以用于根据请求的语言或地区设置合适的国际化或本地化信息,以提供多语言支持。

如何实现

1. 创建 Interceptor 类,实现 HandlerInterceptor 接口,重写 3 个方法,加@Component注解。

@Component
public class MyHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        //请求开始时间
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        System.out.println("startTime : " +  new Date(startTime));
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        
        long startTime = (Long)request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        // 统计耗时
        long executeTime = endTime - startTime;
        System.out.println("executeTime : " + executeTime + "ms");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

2. 配置拦截器,实现 WebMvcConfigurer 接口,加@ Configuration 注解并重写 addInterceptors 方法。

@Configuration
public class MyWebConfigurer implements WebMvcConfigurer {
    @Resource
    private MyHandlerInterceptor myHandlerInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> patterns = new ArrayList<>();

        patterns.add("/test/handlerInterceptor");

        registry.addInterceptor(myHandlerInterceptor)
                .addPathPatterns(patterns) // 需要拦截的请求
                .excludePathPatterns(); // 不需要拦截的请求
    }
}

 拦截结果如下:

 Spring 项目如何实现?可通过使用mvc:interceptors标签来声明需要加入到 SpringMVC 拦截器链中的拦截器。

 过滤器 VS 拦截器区别

过滤器和拦截器的区别主要体现在以下 5 点:

  1. 出身不同;

  2. 触发时机不同;

  3. 实现不同;

  4. 支持的项目类型不同;

  5. 使用的场景不同。

接下来,我们一一来看。

出身不同

过滤器来自于 Servlet,而拦截器来自于 Spring 框架,从上面代码中我们也可以看出,过滤器在实现时导入的是 Servlet 相关的包,如下图所示:

而拦截器在实现时,导入的是 Spring 相关的包,如下图所示:

 

触发时机不同 

请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器(Controller),如下图所示:

所以过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法

实现不同

过滤器是基于方法回调实现的,我们在上面实现过滤器的时候就会发现,当我们要执行下一个过滤器或下一个流程时,需要调用 FilterChain 对象的 doFilter 方法进行回调执行,如下图所示:

由此可以看出,过滤器的实现是基于方法回调的。而拦截器是基于动态代理(底层是反射)实现的,它的实现如下图所示:

 

代理调用的效果如下图所示:

 

总结 

过滤器和拦截器都是基于 AOP 思想实现的,用来处理某个统一的功能的,但二者又有 5 点不同:出身不同、触发时机不同、实现不同、支持的项目类型不同以及使用的场景不同。过滤器通常是用来进行全局过滤的,而拦截器是用来实现某项业务拦截的。

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

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

相关文章

2024-7-9 Windows NDK,Clion,C4droid 编译环境配置(基础|使用命令编译,非AndroidStudio),小白(记录)友好型教程

2024-7-9 Windows NDK,Clion,C4droid 编译环境配置(基础|使用命令编译),小白友好型 一直想使用NDK编译出lua库,然后进行开发.结果一直不成功,问题Bug出现了一堆(主要还是自己太菜,毕竟咱是编程散修一名>_<) NDK之前一直不会配置(直接用命令配置的那种,非AndroidStudio),一…

nvm下载

nvm下载 1.下载nvm安装包2.安装nvm3.修改settings.txt4.安装成功5.继续配置 下载nvm之前,你最好将你电脑上的node卸载掉,直接在winx中卸载就行 1.下载nvm安装包 https://github.com/coreybutler/nvm-windows/releases 2.安装nvm 3.修改settings.txt root: E:\nvm\install\nv…

哦华为仓颉语言

本来我不太想说的&#xff0c;奈何有不少粉丝提问提到了这语言&#xff0c;目前的情况我不透露太多&#xff0c;看过这课程C实现一门计算机编程语言到手撸虚拟机实战的懂的自然懂。 在互联网领域几乎大部分应用软件运行在X86 LINUX上居多&#xff0c;如果你有问题可以先学习这…

红酒的秘密配方:如何调配出个性化的口感?

在红酒的世界里&#xff0c;每一滴都蕴藏着大自然的秘密和酿酒师的匠心。那些令人陶醉的口感、迷人的色泽和香气&#xff0c;都是经过精心调配和时光酝酿的结果。今天&#xff0c;就让我们一起揭开红酒调配的神秘面纱&#xff0c;探索如何调配出个性化的口感&#xff0c;感受雷…

大语言模型垂直化训练技术与应用

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已经成为推动技术进步的关键力量&#xff0c;垂直化训练技术逐渐成为研究的热点&#xff0c;它使得大模型能够更精准地服务于特定行业和应用场景。本文结合达观数据的分享&#xff0c…

C++·模板进阶

1. 非类型模板参数 之前我们写的模板参数都设定class类型的&#xff0c;这个模板参数用来给下面的代码中的某些元素定义类型&#xff0c;我们管这种模板参数叫类型形参。非类型模板参数就是用一个常量作为模板的一个参数&#xff0c;在模板中可将该参数当作常量来使用&#xff…

RT2-使用NLP的方式去训练机器人控制器

目标 研究在网络数据上训练的视觉语言模型也可以直接结合到端到端的机器人控制中&#xff0c;提升泛化性以及获得突出的语义推理&#xff1b;使得单个的端到端训练模型可以同时学习从机器人观测到动作的映射&#xff0c;这个过程可以受益于基于网络上的语言和视觉语言数据的预训…

Python函数 之 函数基础

print() 在控制台输出 input() 获取控制台输⼊的内容 type() 获取变量的数据类型 len() 获取容器的⻓度 (元素的个数) range() ⽣成⼀个序列[0, n) 以上都是我们学过的函数&#xff0c;函数可以实现⼀个特定的功能。我们将学习⾃⼰如何定义函数, 实现特定的功能。 1.函数是什么…

C++进阶:继承和多态

文章目录 ❤️继承&#x1fa77;继承与友元&#x1f9e1;继承和静态成员&#x1f49b;菱形继承及菱形虚拟继承&#x1f49a;继承和组合 ❤️多态&#x1fa77;什么是多态&#xff1f;&#x1f9e1;多态的定义以及实现&#x1f49b;虚函数&#x1f49a;虚函数的重写&#x1f499…

如何借助社交媒体影响者的力量,让品牌影响力倍增?

一、引言&#xff1a;为何社交媒体影响者如此关键&#xff1f; 在信息爆炸的今天&#xff0c;社交媒体已成为塑造消费者行为与品牌认知的重要渠道。社交媒体影响者&#xff0c;凭借其在特定领域的专业知识、庞大的粉丝基础及高度的互动性&#xff0c;成为了品牌传播不可忽视的…

JVM原理(二四):JVM虚拟机锁优化

高效并发是从JDK 5升级到JDK 6后一项重要的改进项&#xff0c;HotSpot虛 拟机开发团队在这个版本上花费了大量的资源去实现各种锁优化技术&#xff0c;如适应性自旋( Adaptive Spinning)、锁消除( Lock Elimination)、锁膨胀(Lock Coarsening)、轻量级锁(Lightweight Locking)、…

DeepMind的JEST技术:AI训练速度提升13倍,能效增强10倍,引领绿色AI革命

谷歌旗下的人工智能研究实验室DeepMind发布了一项关于人工智能模型训练的新研究成果&#xff0c;声称其新提出的“联合示例选择”&#xff08;Joint Example Selection&#xff0c;简称JEST&#xff09;技术能够极大地提高训练速度和能源效率&#xff0c;相比其他方法&#xff…

数字信号处理教程(3)——z变换

在连续时间域中的每一种分析方法&#xff0c;在离散时间域中想必也能得到对应一种分析方法。连续傅里叶变换对应着离散傅里叶变换&#xff08;DFT&#xff09;&#xff0c;而在拉普拉斯变换则是对应着z变换。z变换能够将信号表示成离散复指数函数的线性组合。连续傅里叶变换可以…

NAT技术及其应用

网络地址转换&#xff08;NAT&#xff0c;Network Address Translation&#xff09;是一种广泛应用于现代网络中的技术&#xff0c;旨在解决IP地址短缺问题&#xff0c;同时增强网络的安全性和灵活性。本文将详细解释NAT技术的工作原理&#xff0c;并探讨其在家庭及企业网络中的…

华为HCIP Datacom H12-821 卷30

1.单选题 以下关于OSPF协议报文说法错误的是? A、OSPF报文采用UDP报文封装并且端口号是89 B、OSPF所有报文的头部格式相同 C、OSPF协议使用五种报文完成路由信息的传递 D、OSPF所有报文头部都携带了Router-ID字段 正确答案&#xff1a;A 解析&#xff1a; OSPF用IP报…

【大模型LLM面试合集】大语言模型架构_layer_normalization

2.layer_normalization 1.Normalization 1.1 Batch Norm 为什么要进行BN呢&#xff1f; 在深度神经网络训练的过程中&#xff0c;通常以输入网络的每一个mini-batch进行训练&#xff0c;这样每个batch具有不同的分布&#xff0c;使模型训练起来特别困难。Internal Covariat…

最佳 iPhone 解锁软件工具,可免费下载用于电脑操作的

业内专业人士表示&#xff0c;如果您拥有 iPhone&#xff0c;您一定知道忘记锁屏密码会多么令人沮丧。由于 Apple 的安全功能强大&#xff0c;几乎不可能在没有密码或 Apple ID 的情况下访问锁定的 iPhone。 “当我忘记密码时&#xff0c;如何在没有密码的情况下解锁iPhone&am…

来一组爱胜品1133DN PRO打印机的照片

刚拆箱的机器正面照片 打开前盖正准备要安装原装耗材 下图是原装耗材&#xff0c;硒鼓型号是DR2833、碳粉盒型号是TN2833,鼓组件打印页数12000页&#xff0c;TN2833标准容量粉盒打印页数1600页/5%覆盖率&#xff0c;TN2833H大容量粉盒打印页数3000页/5%覆盖率、TN2833L超大容量…

【LLM】三、open-webui+ollama搭建自己的聊天机器人

系列文章目录 往期文章回顾&#xff1a; 【LLM】二、python调用本地的ollama部署的大模型 【LLM】一、利用ollama本地部署大模型 目录 前言 一、open-webui是什么 二、安装 1.docker安装 2.源码安装 三、使用 四、问题汇总 总结 前言 前面的文章&#xff0c;我们已经…

Studying-代码随想录训练营day34| 62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树

第34天&#xff0c;动态规划part02&#xff0c;牢记五部曲步骤&#xff0c;编程语言&#xff1a;C 目录 62.不同路径 63.不同路径II 343.整数拆分 96.不同的二叉搜索树 总结 62.不同路径 文档讲解&#xff1a;代码随想录不同路径 视频讲解&#xff1a;手撕不同路径 题目…