拦截器和过滤器(原理区别)

目录

一、拦截器

拦截器是什么

拦截器的使用

拦截器的实现

导入依赖

实现HandlerInterceptor接口

注册拦截器

拦截器的生命周期

拦截器的执行顺序

拦截器的生命周期

多个拦截器的执行流程

拦截器的实际使用

拦截器实现日志记录

实现接口幂等性校验

拦截器的性能优化

二、过滤器

过滤器是什么

过滤器的使用

过滤器的实现

创建过滤器

开启URL过滤

过滤器的生命周期

多个Filter的执行顺序

三、过滤器和拦截器的区别

相同

底层原理

使用范围不同

触发时机不同

控制执行的顺序不同


一、拦截器

拦截器是什么

拦截器(Interceptor)是一种特殊的组件,它是基于反射进行实现。它可以在请求处理的过程中对请求和响应进行拦截和处理。拦截的是servlet 和 controller 之间的请求和响应。

拦截器的使用

  • 权限控制:拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。

  • 日志记录:拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。

  • 接口幂等性校验:拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。

  • 数据校验:拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。

  • 缓存处理:拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。

拦截器的实现

导入依赖

如果是使用的是springboot项目的话,直接导入这个依赖,spring项目需要导入 web 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

实现HandlerInterceptor接口

要在SpringBoot中实现拦截器,首先需要创建一个类并实现HandlerInterceptor接口。HandlerInterceptor接口包含以下三个方法:

preHandle:在请求到达处理器之前执行,可以用于权限验证、数据校验等操作。如果返回true,则继续执行后续操作;如果返回false,则中断请求处理。

postHandle:在处理器处理请求之后执行,可以用于日志记录、缓存处理等操作。

afterCompletion:在视图渲染之后执行,可以用于资源清理等操作。

public class MainInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("我是处理之前!");return true;   //只有返回true才会继续,否则直接结束}
​@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("我是处理之后!");}
​@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("我是完成之后!");}
}

注册拦截器

要让拦截器生效,需要将其注册到InterceptorRegistry中。这可以通过实现WebMvcConfigurer接口并重写addInterceptors方法来实现。注册成功以后,我们还可以设置拦截的规则,拦截的路径,和不拦截的路径

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate MainInterceptor customInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 添加拦截器,并设置拦截路径registry.addInterceptor(customInterceptor).addPathPatterns("/**").excludePathPatterns("/exclude/**");}
}

拦截器的生命周期

拦截器的执行顺序

当有多个拦截器时,它们的执行顺序取决于注册顺序。先注册的拦截器先执行,后注册的拦截器后执行。在请求处理过程中,拦截器的preHandle方法按注册顺序执行,而postHandle和afterCompletion方法按注册顺序的逆序执行。

拦截器的生命周期

拦截器的生命周期由Spring容器管理。当Spring容器启动时,拦截器会被实例化并初始化;当Spring容器关闭时,拦截器会被销毁。

多个拦截器的执行流程

当有多个拦截器时,它们的执行流程如下:

  1. 执行所有拦截器的preHandle方法,按注册顺序执行。如果某个拦截器的preHandle方法返回false,则中断请求处理,直接执行已执

  2. 拦截器的afterCompletion方法。

  3. 执行处理器的处理方法。

  4. 执行所有拦截器的postHandle方法,按注册顺序的逆序执行。

  5. 渲染视图。

  6. 执行所有拦截器的afterCompletion方法,按注册顺序的逆序执行。

拦截器的实际使用

拦截器实现日志记录

使用拦截器记录接口访问的记录,记录访问该接口的IP地址

@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("request.getRemoteHost() = " + request.getRemoteHost());System.out.println("request.getParameter(\"id\") = " + request.getParameter("id"));return true;   //只有返回true才会继续,否则直接结束}
​@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {request.getParameter("id");System.out.println("我是处理之后!");}
​@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("我是完成之后!");}
}
​

实现接口幂等性校验

拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。以下是一个简单的幂等性校验示例:

public class IdempotentInterceptor implements HandlerInterceptor {
​private static final String IDEMPOTENT_TOKEN = "idempotentToken";
​@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {String token = request.getHeader(IDEMPOTENT_TOKEN);if (StringUtils.isEmpty(token)) {throw new RuntimeException("Idempotent token is missing");}if (!checkIdempotentToken(token)) {throw new RuntimeException("Duplicate request");}return true;}
​private boolean checkIdempotentToken(String token) {// Check the token in the cache or database// Return true if the token is valid, false otherwise}
}
​
//在上述示例中,我们在preHandle方法中检查请求头中的幂等性令牌,如果令牌无效,则抛出异常并中断请求处理。

拦截器的性能优化

拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:

  • 减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。

  • 精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。

  • 使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。

  • 使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。

二、过滤器

过滤器是什么

过滤器顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。过滤器的实现是通过函数回调进行实现。

函数回调:它指的是将一个函数作为参数传递给另一个函数,并在特定事件发生时被调用执行的函数。这种方式使得在异步编程中,当某个操作完成后,系统能够调用预先定义好的回调函数来处理结果,从而避免阻塞程序的执行,提高程序的效率和响应速度。

过滤器的使用

  • 如登录控制

  • 权限管理

  • 过滤敏感词汇等

过滤器的实现

过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。

创建过滤器

init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。 FilterConfig可以获取配置信息

doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

默认就会传入Request和Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。

destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次

@Component
@WebFilter("/*") // 定义的过滤规则,只过滤对应的url请求
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
​System.out.println("Filter 前置");}
​@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
​System.out.println("Filter 处理中");filterChain.doFilter(servletRequest, servletResponse);}
​@Overridepublic void destroy() {
​System.out.println("Filter 后置");}
}
开启URL过滤

开启专门的Url过滤需要在启动类添加一个注解 @ServletComponentScan

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

过滤器的生命周期

  1. 初始化阶段(Initialization): 在 Servlet 容器启动时,会实例化所有的过滤器并调用其 init 方法进行初始化。在 init 方法中,过滤器可以进行一些初始化操作,例如读取配置文件、建立数据库连接等。该方法只会在过滤器实例化时调用一次。

  2. 请求处理阶段(Request Processing): 在请求到达 Servlet 前,过滤器可以对请求进行预处理。当请求与过滤器匹配时,Servlet 容器会调用过滤器的 doFilter 方法来处理请求。在 doFilter 方法中,过滤器可以执行一些操作,例如修改请求或响应内容、记录日志、验证权限等。如果请求不符合过滤器的条件,过滤器可以选择放行请求,将请求传递给下一个过滤器或目标 Servlet。

  3. 销毁阶段(Destruction): 在 Servlet 容器关闭时,会销毁所有的过滤器并调用其 destroy 方法进行清理。在 destroy 方法中,过滤器可以进行一些清理操作,例如释放资源、关闭连接等。该方法只会在过滤器销毁时调用一次。

多个Filter的执行顺序
  • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是<filter-mapping>在web配置的顺序,配置在上面那么就会先执行。

  • 如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。

  • 如果注解和xml混用,那么在web.xml中配置的会先执行。

三、过滤器和拦截器的区别

相同

二者都是体现了AOP的思想,都可以实现诸如日志记录、登录鉴权等功能,但二者的不同点也是比较多的,接下来一一说明。

底层原理

拦截器是使用反射进行实现,过滤器是基于函数回调进行实现

使用范围不同

过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。

拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于ApplicationSwing等程序中。

触发时机不同

过滤器拦截器的触发时机也不同,我们看下边这张图

过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。

拦截器 Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。·

控制执行的顺序不同

拦截器:是先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。

为什么?

两个方法中在调用拦截器数组 HandlerInterceptor[] 时,循环的顺序竟然是相反的。导致postHandle()preHandle() 方法执行的顺序相反。

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

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

相关文章

Gitee配置SSH登录

一、背景 新入手的电脑&#xff0c;需要对Gitee上存放的项目进行更改上传&#xff0c;发现上传不了需要登录&#xff0c;便采用SSH密钥进行登录&#xff0c;防止远程管理工程中的信息泄露 二、前提 电脑已下载Git Bash工具&#xff0c;在项目下点击鼠标右键&#xff0c;进入…

案例分析篇15:软件开发方法考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

Hadoop大数据应用:Linux 部署 HDFS 分布式集群

目录 一、实验 1.环境 2.Linux 部署 HDFS 分布式集群 3.Linux 使用 HDFS 文件系统 二、问题 1.ssh-copy-id 报错 2. 如何禁用ssh key 检测 3.HDFS有哪些配置文件 4.hadoop查看版本报错 5.启动集群报错 6.hadoop 的启动和停止命令 7.上传文件报错 8.HDFS 使用命令 一…

基于java+springboot+vue实现的旅游管理系统(文末源码+Lw+ppt)23-402

摘 要 甘肃旅游管理系统采用B/S架构&#xff0c;数据库是MySQL。网站的搭建与开发采用了先进的java进行编写&#xff0c;使用了SpringBoot框架。该系统从两个对象&#xff1a;由管理员和用户来对系统进行设计构建。主要功能包括&#xff1a;个人信息修改&#xff0c;对用户、…

微信小程序+java如何实现图片白色背景改透明

目录 1. 如何实现&#xff1f; 1.1 java端代码&#xff1a; 1.2 微信小程序端 1.2.1 前置要求 1.2.2 文件选择 1.2.3 文件上传 1.2.4 数据双向绑定 先看效果【 扫码可体验具体功能 】&#xff1a; 原图&#xff1a; 处理后&#xff1a; 1. 如何实现&#xff1f; 1.1…

Leetcode 3.14

Leetcode hot100 二叉树1.二叉树的层序遍历2.验证二叉搜索树3.二叉树的右视图 二叉树 1.二叉树的层序遍历 二叉树的层序遍历 二叉树的层序遍历可以用先进先出的队列来实现。 将每一层的所有node都添加到队列中&#xff0c;记录下当前队列的长度&#xff0c;即该层的元素数量&…

扫雷小游戏制作教程:用HTML5和JavaScript打造经典游戏

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

【Stable Diffusion】入门-03:图生图基本步骤+参数解读

目录 1 图生图原理2 基本步骤2.1 导入图片2.2 书写提示词2.3 参数调整 3 随机种子的含义4 拓展应用 1 图生图原理 当提示词不足以表达你的想法&#xff0c;或者你希望以一个更为简单清晰的方式传递一些要求的时候&#xff0c;可以给AI输入一张图片&#xff0c;此时图片和文字是…

Linux 部署 Samba 服务

一、Ubuntu 部署 Samba 1、安装 Samba # 更新本地软件包列表 sudo apt update# 安装Samba sudo apt install samba# 查看版本 smbd --version2、创建共享文件夹&#xff0c;并配置 Samba 创建需要共享的文件夹&#xff0c;并赋予权限&#xff1a; sudo mkdir /home/test sud…

2.4G合封芯片 XL2407P,收发一体

XL2407P芯片是工作在2.400~2.483GHz世界通用 ISM 频段&#xff0c;集成微控制器的的 2.4G合封芯片。该芯片集成射频收发机、频率收生器、晶体振荡器、调制解调器等功能模块&#xff0c;可以大大减少外围元件数量&#xff0c;节省空间&#xff0c;降低系统复杂度。XL2407P合封的…

图片压缩神器源码系统:无损画质 带完整的代码安装包以及搭建教程

在数字化时代&#xff0c;图片已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;随着图片数量的增加和质量的提升&#xff0c;存储空间的问题也日益凸显。如何在保证图片质量的前提下&#xff0c;有效减少图片的大小&#xff0c;成为了一个亟待解决的问题。罗峰…

如何布局马斯克推特上喊的meme币赛道

2024年的牛市正如火如荼的开展&#xff0c;截止当下&#xff0c;比特币已经站上了7.3万美元&#xff0c;远超2021年高点的6.9万美元&#xff0c;比特币的未来是一片大海。 除了比特币的一枝独秀之外&#xff0c;meme板块可以说是市场资金最青睐的。尤其是马斯克在X分享PEPE相关…