过滤器和拦截器的 5 个区别!

76b3a963ef440ac36f45da4f309d79ae.jpeg

作者 | 磊哥

来源 | Java面试真题解析(ID:aimianshi666)

转载请联系授权(微信ID:GG_Stone)

过滤器(Filter)和拦截器(Interceptor)都是基于 AOP(Aspect Oriented Programming,面向切面编程)思想实现的,用来解决项目中某一类问题的两种“工具”,但二者有着明显的差距,接下来我们一起来看。

实现过滤器和拦截器

首先,我们先来看一下二者在 Spring Boot 项目中的具体实现,这对后续理解二者的区别有很大的帮助。

实现过滤器

过滤器可以使用 Servlet 3.0 提供的 @WebFilter 注解,配置过滤的 URL 规则,然后再实现 Filter 接口,重写接口中的 doFilter 方法,具体实现代码如下:

import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("过滤器:执行 init 方法。");}@Overridepublic void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {System.out.println("过滤器:开始执行 doFilter 方法。");// 请求放行filterChain.doFilter(servletRequest, servletResponse);System.out.println("过滤器:结束执行 doFilter 方法。");}@Overridepublic void destroy() {System.out.println("过滤器:执行 destroy 方法。");}
}

其中:

  • void init(FilterConfig filterConfig):容器启动(初始化 Filter)时会被调用,整个程序运行期只会被调用一次。用于实现 Filter 对象的初始化。

  • void doFilter(ServletRequest request, ServletResponse response,FilterChain chain):具体的过滤功能实现代码,通过此方法对请求进行过滤处理,其中 FilterChain 参数是用来调用下一个过滤器或执行下一个流程

  • void destroy():用于 Filter 销毁前完成相关资源的回收工作。

    实现拦截器

    拦截器的实现分为两步,第一步,创建一个普通的拦截器,实现 HandlerInterceptor 接口,并重写接口中的相关方法;第二步,将上一步创建的拦截器加入到 Spring Boot 的配置文件中。接下来,先创建一个普通拦截器,实现 HandlerInterceptor 接口并重写 preHandle/postHandle/afterCompletion 方法,具体实现代码如下:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TestInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("拦截器:执行 preHandle 方法。");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("拦截器:执行 postHandle 方法。");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("拦截器:执行 afterCompletion 方法。");}
}

其中:

  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle):在请求方法执行前被调用,也就是调用目标方法之前被调用。比如我们在操作数据之前先要验证用户的登录信息,就可以在此方法中实现,如果验证成功则返回 true,继续执行数据操作业务;否则就返回 false,后续操作数据的业务就不会被执行了。

  • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView):调用请求方法之后执行,但它会在 DispatcherServlet 进行渲染视图之前被执行。

  • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex):会在整个请求结束之后再执行,也就是在 DispatcherServlet 渲染了对应的视图之后再执行。

最后,我们再将上面的拦截器注入到项目配置文件中,并设置相应拦截规则,具体实现代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AppConfig implements WebMvcConfigurer {// 注入拦截器@Autowiredprivate TestInterceptor testInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(testInterceptor) // 添加拦截器.addPathPatterns("/*"); // 拦截所有地址}
}

了解了二者的使用之后,接下来我们来看二者的区别。

过滤器 VS 拦截器

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

  1. 出身不同;

  2. 触发时机不同;

  3. 实现不同;

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

  5. 使用的场景不同。

接下来,我们一一来看。

1.出身不同

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

2.触发时机不同

请求的执行顺序是:请求进入容器 > 进入过滤器 > 进入 Servlet > 进入拦截器 > 执行控制器(Controller),如下图所示:48b220ca8915b23742279e2e7b2434e4.png所以过滤器和拦截器的执行时机也是不同的,过滤器会先执行,然后才会执行拦截器,最后才会进入真正的要调用的方法

3.实现不同

过滤器是基于方法回调实现的,我们在上面实现过滤器的时候就会发现,当我们要执行下一个过滤器或下一个流程时,需要调用 FilterChain 对象的 doFilter 方法进行回调执行,如下图所示:e7d818732fa8305304dfe978d08f9fa0.png由此可以看出,过滤器的实现是基于方法回调的。而拦截器是基于动态代理(底层是反射)实现的,它的实现如下图所示:10c2c3f8783e898c073ca9361e05437a.png代理调用的效果如下图所示:e149b0e865030d5067dcdb314aad19ab.png

4.支持的项目类型不同

过滤器是 Servlet 规范中定义的,所以过滤器要依赖 Servlet 容器,它只能用在 Web 项目中;而拦截器是 Spring 中的一个组件,因此拦截器既可以用在 Web 项目中,同时还可以用在 Application 或 Swing 程序中

5.使用的场景不同

因为拦截器更接近业务系统,所以拦截器主要用来实现项目中的业务判断的,比如:登录判断、权限判断、日志记录等业务。而过滤器通常是用来实现通用功能过滤的,比如:敏感词过滤、字符集编码设置、响应数据压缩等功能。

本文项目源码下载

https://gitee.com/mydb/springboot-examples/tree/master/spring-boot-filter

总结

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

参考 & 鸣谢

  • blog.csdn.net/wo541075754/article/details/111661213

  • zhuanlan.zhihu.com/p/340397290

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java面试真题解析

面试合集:https://gitee.com/mydb/interview

6e1539a24d3553442398cabbf9b96e6a.gif

往期推荐

b9d9789584a49f666b77b02715a51da8.jpeg

面试突击89:事务隔离级别和传播机制有什么区别?


33120efbf063fd2f1f9b1c97053e4f62.jpeg

面试突击88:加入事务和嵌套事务有什么区别?


a54c1618cce0e8122ff7615af851a95b.jpeg

面试突击87:说一下 Spring 事务传播机制?

a9219c944791f219b5c81a926f0fd53c.gif

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

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

相关文章

面试突击第一季完结:共 91 篇!

感谢各位读者的支持与阅读,面试突击系列第一季到这里就要和大家说再见了。希望所写内容对大家有帮助,也祝你们找到满意的工作。青山不改,细水长流,我们下一季再见!91:MD5 加密安全吗?90&#xf…

SpringBoot官方热部署和远程调试神器

平时使用SpringBoot开发应用时,修改代码后需要重新启动才能生效。如果你的应用足够大的话,启动可能需要好几分钟。有没有什么办法可以加速启动过程,让我们开发应用代码更高效呢?今天给大家推荐一款SpringBoot官方的热部署工具spri…

MySQL 优化:Explain 执行计划详解

昨天中午在食堂,和部门的技术大牛们坐在一桌吃饭,作为一个卑微技术渣仔默默的吃着饭,听大佬们高谈阔论,研究各种高端技术,我TM也想说话可实在插不上嘴。聊着聊着突然说到他上午面试了一个工作6年的程序员,表…

顶级 Javaer 常用的 14 个类库

作者:小姐姐味道昨天下载下来Java16尝尝鲜。一看,好家伙,足足有176MB大。即使把jmc和jvisualvm给搞了出去,依然还是这么大,真的是让人震惊不已。但即使JDK足够庞大,它的功能也已经不够用了。我们需要借助于…

势头迅猛的儿童手表:恐陷下一个文曲星之地?

历史的节奏,就是不断重复此前发生过的事。虽然表现形态不一,但蕴藏的规律、趋势总是有着惊人的相似。在科技行业,同样如此——iPhone开启的智能手机时代走过的大兴—→平稳→下降态势,与PC的历程几乎是一样的。而在国内&#xff0…

scala 类中的对象是类_Scala中的类和对象

scala 类中的对象是类Scala中的课程 (Classes in Scala) A class is a blueprint for objects. It contains the definition of all the members of the class. There are two types of members of the class in Scala, 类是对象的蓝图。 它包含该类的所有成员的定义。 Scala中…

2022年终总结:不再用“拼命”来应对极度的不安全感

作者 | 磊哥来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)人生匆匆三十四余载,今天又到了辞旧迎新和 2022 年说再(也不)见的时刻了,所以…

Java 最常见的 200+ 面试题:面试必备

这份面试清单是从我 2015 年做了 TeamLeader 之后开始收集的,一方面是给公司招聘用,另一方面是想用它来挖掘在 Java 技术栈中,还有那些知识点是我不知道的,我想找到这些技术盲点,然后修复它,以此来提高自己…

vim中的jk为什么是上下_JK轮胎的完整形式是什么?

vim中的jk为什么是上下JK轮胎:Juggilal Kamlapat Ji轮胎 (JK Tyres: Juggilal Kamlapat Ji Tyres) JK Tyre and Industries is an abbreviation of Juggilal Kamlapat Ji Tyres & Industries Ltd. It is an Automobile Tyre, Tubes and Flaps manufacturing com…

【C语言】第二章 类型、运算符和表达式

为什么80%的码农都做不了架构师?>>> 变量和常量是程序处理的两种基本数据对象。 声明语句说明变量的名字及类型,也可以指定变量的初值。 运算符指定要进行的操作。 表达式则把变量与常量组合起来生成新的值。 对象的类型决定该对象可取值的集…

转: 加快Android编译速度

转: http://timeszoro.xyz/2015/11/25/%E5%8A%A0%E5%BF%ABandroid%E7%BC%96%E8%AF%91%E9%80%9F%E5%BA%A6/ 加快Android编译速度 发表于 2015-11-25 | 对于Android开发者而言,随着工程不断的壮大,Android项目的编译时间也逐渐变长&#xff…

ipv6寻址_什么是IPV4寻址?

ipv6寻址IPV4寻址简介 (Introduction to IPV4 Addressing ) Internet protocol version 4 in any network, is a standard protocol for assigning a logical address (IP address) to hosts. You are currently using the same protocol. This protocol is capable of providi…

最长递增子序列 子串_最长递增子序列

最长递增子序列 子串Description: 描述: This is one of the most popular dynamic programming problems often used as building block to solve other problems. 这是最流行的动态编程问题之一,通常用作解决其他问题的基础。 Problem statement: 问…

WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

原文:WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本…

bba70_BBA的完整形式是什么?

bba70BBA:工商管理学士 (BBA: Bachelor of Business Administration) BBA is an abbreviation of Bachelor of Business Administration also spelled as B.B.A. In the field of Business Administration, it is an undergraduate degree program. This is a degre…

Qt和纹理

2019独角兽企业重金招聘Python工程师标准>>> test 转载于:https://my.oschina.net/assange/blog/537631

计算机图形学图形旋转_计算机图形学翻译

计算机图形学图形旋转计算机图形学| 翻译 (Computer Graphics | Translations) Transformation techniques mean to modify the current shape or object in a particular manner. Changing of an object after creation, in terms of position or even size is known as trans…

AP 1532E register   Cisco 2504 AP注册WLC

客户的环境是:WLC是 2504 的AP的型号是 1532E的首先要是版本匹配,那么我们就要查一个兼容性列表,请看附件同时,我们要把WLC的版本升级到AIR-CT2500-K9-8-1-111-0.aes 这个版本;同时由于瘦AP 1532E的版本是 Cisco IOS S…

C#中IDisposable 回收非托管资源

C#中IDisposable 更多2014/9/7 来源:C#学习浏览量:4185学习标签: IDisposable本文导读:C#中IDisposable接口的主要用途是释放非托管资源。当不再使用托管对象时,垃圾回收器会自动释放分配给该对象的内存。但无法预测进…

css导航栏_使用CSS的导航栏

css导航栏CSS | 导航栏 (CSS | Navigation Bar) Developing websites is great but developing a user-friendly website is even greater. So how does one design a user-friendly website? What tools to use? Well, there are many tools to mention which are quite hel…