【拦截器Interceptor】springboot拦截器的使用和原理
【拦截器Interceptor】springboot拦截器的使用和原理
- 【一】拦截器简介
- (1)简介
- 【2】作用
- 【二】实现步骤
- 【1】自定义拦截器,实现拦截器接口HandlerInterceptor
- 【2】将拦截器添加到容器当中
- 【3】配置拦截器的拦截规则
- 【4】拦截器的执行顺序
- 【三】拦截器参数
- 【1】获取请求头 request.getHeader
- 【2】Object handler 是什么参数
- 【3】ModelAndView modelAndView
- 【4】Exception ex
- 【5】HttpServletRequest request
- 【6】HttpServletResponse response
- 【四】多拦截器执行顺序
- 【五】拦截器和过滤器的区别
- 【六】拦截器的实际案例
- 【1】拦截器实现权限控制
- 【2】拦截器实现日志记录
- 【3】拦截器实现接口幂等性校验
- 【七】拦截器的性能优化和常见问题
- 【1】拦截器性能优化策略
- 【2】拦截器的常见问题和解决方案
- 【八】拦截器的原理和源码分析
【一】拦截器简介
(1)简介
拦截器就是用来拦截指定的请求,在请求前、请求处理后做一些响应的业务逻辑处理,或者在请求完成之后做一些资源释放。
拦截器最常用的使用场景就是认证,在请求开始之前,对当前请求进行权限校验,如果当前请求用户具备操作当前请求的权限,就对当前请求放行,允许执行业务逻辑;否则拦截当前请求,直接返回。
拦截器的功能通过网关也都是可以实现的,但是一些单体架构还是需要使用拦截器。
【2】作用
拦截器可以用于实现以下功能:
(1)权限控制:拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。
(2)日志记录:拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。
(3)接口幂等性校验:拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。
(4)数据校验:拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。
(5)缓存处理:拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。
【二】实现步骤
【1】自定义拦截器,实现拦截器接口HandlerInterceptor
要在SpringBoot中实现拦截器,首先需要创建一个类并实现HandlerInterceptor接口。HandlerInterceptor接口包含以下三个方法:
(1)preHandle:在请求到达处理器之前执行,可以用于权限验证、数据校验等操作。如果返回true,则继续执行后续操作;如果返回false,则中断请求处理。
(2)postHandle:在处理器处理请求之后执行,可以用于日志记录、缓存处理等操作。
(3)afterCompletion:在视图渲染之后执行,可以用于资源清理等操作。
/*** 登录检查* 1.配置到拦截器要拦截哪些请求* 2.把这些配置放在容器中** 实现HandlerInterceptor接口*/
public class LoginInterceptor implements HandlerInterceptor {/*** 目标方法执行之前* 登录检查写在这里,如果没有登录,就不执行目标方法* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取进过拦截器的路径String requestURI = request.getRequestURI();// 登录检查逻辑HttpSession session = request.getSession();Object loginUser = session.getAttribute("loginUser");if(loginUser !=null){// 放行return true;}// 拦截 就是未登录,自动跳转到登录页面,然后写拦截住的逻辑return false;}/*** 目标方法执行完成以后* @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}/*** 页面渲染以后* @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}
【2】将拦截器添加到容器当中
要让拦截器生效,需要将其注册到InterceptorRegistry中。这可以通过实现WebMvcConfigurer接口并重写addInterceptors方法来实现。以下是一个简单的注册示例:
@Configuration
//定制SpringMVC的一些功能都使用WebMvcConfigurer
public class AdminWebConfig implements WebMvcConfigurer {/*** 配置拦截器* @param registry 相当于拦截器的注册中心*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {//下面这句代码相当于添加一个拦截器 添加的拦截器就是我们刚刚创建的registry.addInterceptor(new LoginInterceptor())//addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源.addPathPatterns()//excludePathPatterns()表示我们要放行哪些(表示不用经过拦截器)//excludePathPatterns("/","/login")表示放行“/”与“/login”请求//如果有静态资源的时候可以在这个地方放行.excludePathPatterns("/","/login");}
}
【3】配置拦截器的拦截规则
在注册拦截器时,可以通过addPathPatterns和excludePathPatterns方法来配置拦截器的拦截规则。addPathPatterns方法用于指定需要拦截的请求路径,excludePathPatterns方法用于指定不需要拦截的请求路径。以下是一个配置示例:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/register");}
}
在上述示例中,我们配置了拦截器拦截所有请求,但排除了登录和注册请求。
【4】拦截器的执行顺序
【三】拦截器参数
【1】获取请求头 request.getHeader
@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contenType = request.getHeader("Content-Type");System.out.println("preHandle..."+contenType);//放行return true;}
【2】Object handler 是什么参数
@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contenType = request.getHeader("Content-Type");System.out.println(handler);System.out.println("preHandle..."+contenType);
// 放行return true;}
使用PostMan发送请求后,控制台出现下面这个样子
这个参数有什么用?被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String contenType = request.getHeader("Content-Type");
// System.out.println(handler);HandlerMethod hm = (HandlerMethod)handler;
// 通过hm.getMethod()就可以拿到原始执行的对象,拿到这个对象就可以进行反射hm.getMethod();System.out.println("preHandle..."+contenType);
// 放行return true;}
【3】ModelAndView modelAndView
封装了SpringMVC进行页面跳转的相关数据,但是我们现在都是返回JSON
【4】Exception ex
通过这个ex可以拿到原始的程序执行过程中出现的异常的
假设controller层抛了异常,在这里是可以拿到异常对象的,但是我们有异常处理机制,所以这里就没有那么大的需求了
如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
【5】HttpServletRequest request
request:请求对象
【6】HttpServletResponse response
response:响应对象
【四】多拦截器执行顺序
当配置多个拦截器时,形成拦截器链
准备第二个拦截器
注册
@Configuration
//定制SpringMVC的一些功能都使用WebMvcConfigurer
public class AdminWebConfig implements WebMvcConfigurer {/*** 配置拦截器* @param registry 相当于拦截器的注册中心*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {
// 下面这句代码相当于添加一个拦截器 添加的拦截器就是我们刚刚创建的registry.addInterceptor(new LoginInterceptor())
// addPathPatterns()配置我们要拦截哪些路径 addPathPatterns("/**")表示拦截所有请求,包括我们的静态资源.addPathPatterns()
// excludePathPatterns()表示我们要放行哪些(表示不用经过拦截器)
// excludePathPatterns("/","/login")表示放行“/”与“/login”请求
// 如果有静态资源的时候可以在这个地方放行.excludePathPatterns("/","/login");// 第二个拦截器registry.addInterceptor(new LoginInterceptor2()).addPathPatterns("/books");}
}
那当我们配置了两个拦截器以后,会有一个执行顺序
拦截器链的运行顺序参照拦截器添加顺序为准,下面就是三个拦截器时的执行顺序
拦截器链的运行顺序参照拦截器添加顺序为准,下面就是三个拦截器时的执行顺序
【五】拦截器和过滤器的区别
拦截器和过滤器都可以实现对请求和响应的拦截和处理,但它们之间存在以下区别:
(1)执行顺序:过滤器在拦截器之前执行,拦截器在处理器之前执行。
(2)功能范围:过滤器可以对所有请求进行拦截,而拦截器只能对特定的请求进行拦截。
(3)生命周期:过滤器由Servlet容器管理,拦截器由Spring容器管理。
(4)使用场景:过滤器适用于对请求和响应的全局处理,拦截器适用于对特定请求的处理。
【六】拦截器的实际案例
【1】拦截器实现权限控制
拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。以下是一个简单的权限控制示例:
public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {HttpSession session = request.getSession();User user = (User) session.getAttribute("user");if (user == null) {response.sendRedirect("/login");return false;}return true;}
}
在上述示例中,我们在preHandle方法中检查用户是否已登录,如果未登录,则重定向到登录页面并中断请求处理。
【2】拦截器实现日志记录
拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。以下是一个简单的日志记录示例:
public class LogInterceptor implements HandlerInterceptor {private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {logger.info("Request URI: {}", request.getRequestURI());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {logger.info("Response status: {}", response.getStatus());}
}
在上述示例中,我们在preHandle方法中记录请求URI,在postHandle方法中记录响应状态。
【3】拦截器实现接口幂等性校验
拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。以下是一个简单的幂等性校验示例:
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方法中检查请求头中的幂等性令牌,如果令牌无效,则抛出异常并中断请求处理。
【七】拦截器的性能优化和常见问题
【1】拦截器性能优化策略
拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:
(1)减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。
(2)精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。
(3)使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。
(4)使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。
【2】拦截器的常见问题和解决方案
拦截器是一种用于处理请求和响应的中间件,它可以在请求到达目标处理器之前或响应返回客户端之前执行一些操作。然而,在实际使用过程中,我们可能会遇到一些问题,如拦截器不生效、执行顺序错误或影响性能等。接下来,我们将逐一分析这些问题的原因及解决方法。
(1)拦截器不生效:拦截器不生效的可能原因有很多,其中最常见的包括拦截器未注册到InterceptorRegistry、拦截规则配置错误等。为了解决这个问题,我们需要首先检查拦截器是否已经正确注册到InterceptorRegistry中,然后再检查拦截规则是否配置正确。如果发现问题,需要及时进行调整和修复。
(2)拦截器执行顺序错误:拦截器执行顺序错误的主要原因是拦截器的注册顺序错误。在实际应用中,拦截器的执行顺序是根据它们在InterceptorRegistry中的注册顺序来决定的。因此,为了解决这个问题,我们需要调整拦截器在InterceptorRegistry中的注册顺序,确保它们按照预期的顺序执行。
(3)拦截器影响性能:拦截器影响性能的主要原因是拦截器中的处理逻辑过于复杂或资源消耗过大。为了解决这个问题,我们需要对拦截器的处理逻辑进行优化,尽量减少不必要的计算和资源消耗。同时,我们还可以考虑使用一些性能监控工具,如JProfiler等,来对拦截器的性能进行实时监控和分析,从而找到性能瓶颈并进行优化。
【八】拦截器的原理和源码分析
相关文章:

【拦截器Interceptor】springboot拦截器的使用和原理
【拦截器Interceptor】springboot拦截器的使用和原理 【一】拦截器简介(1)简介【2】作用 【二】实现步骤【1】自定义拦截器,实现拦截器接口HandlerInterceptor【2】将拦截器添加到容器当中【3】配置拦截器的拦截规则【4】拦截器的执行顺序 【…...
Android12 user版本无法进入recovery问题
1.前言 之前Android9的时候公司自己写了一个简单的OTA在线升级,调用Recovery升级系统。后来Android12的时候想使用AB升级,发现我这套代码AB升级完成了之后,重启却无法切到B,所以造成升级一直是失败的。后来想着要不还是把AB关掉直…...
Android沙盒机制
Android沙盒机制 Android Q文件存储机制修改成了沙盒模式,应用只能访问自己沙盒下的文件和公共媒体文件 存储(也就是write)私有目录和公共媒体文件都不需要WRITE_EXTERNAL_STORAGE权限读取(也就是read)私有目录不需要…...
【C++】每日一题 290 单词规律
给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 #include <string> #include <unordered_ma…...
CSS3 animation-direction 属性
CSS3 animation-direction 属性 定义和用法 animation-direction 属性定义是否循环交替反向播放动画。 **注意:**如果动画被设置为只播放一次,该属性将不起作用。 默认值:normal继承:否可动画化:否。请参阅 可动画…...
【mysql 5.7 没有ini 文件,手动添加配置文件】
在安装目录的根目录添加my.ini配置文件: 注意注释的内容, 其中server-id 在开启日志归档的时候,一定要配置, [mysql] # 设置mysql客户端默认字符集 default-character-setutf8[mysqld] #server id 一定要设置,否则无法…...
【Python】从零开始学习Python中的随机模块:实现验证码生成功能
欢迎来CILMY23的博客 本篇主题为 从零开始学习Python中的随机模块:实现验证码生成功能 个人主页:CILMY23-CSDN博客 个人专栏系列: Python | C语言 | 数据结构与算法 | C 感谢观看,支持的可以给个一键三连,点赞关注…...
游戏动画技术:从传统到深度学习
一、传统游戏动画技术简介 3D游戏动画的骨骼动画和蒙皮技术动画交互控制:状态机、动作融合和IK基于状态机的动画控制原理和问题 二、Motion Matching技术简介 传统状态机动画的缺陷Motion Matching的原理:根据角色状态自动匹配动画Dance Card动捕流程…...

Github 2024-04-12 开源项目日报 Top10
根据Github Trendings的统计,今日(2024-04-12统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目2Cuda项目1C++项目1C项目1HTML项目1Jupyter Notebook项目1JavaScript项目1Python - 100天从新手到大师 创建周期:22…...
若依下整合多个Redis
提前总结,因此项目已多处使用Redis1 故此我创建的Redis工厂只添加了Redis2并不影响Redis1。但如若还有Redis3、4、5可按照下述方法继续往Redis工厂里添加 下述代码添加到 RedisConfig import org.springframework.beans.factory.annotation.Autowired; import org…...
SRTP + RTCP + SCTP
SRTP(Secure Real-time Transport Protocol) 主要功能:SRTP 是 RTP 的一个扩展,提供额外的安全特性,如加密、完整性校验和认证。它旨在保护实时传输的音频和视频流不被窃听或篡改。加密传输:SRTP 使用强加密…...

每日一题 — 串联所有单词的子串
30. 串联所有单词的子串 - 力扣(LeetCode) 思路:因为words里面的每一个字符串的长度都是固定的,所以可以将题转换成字符在字符串中的所有异位词 设出哈希表定义left和right进窗口维护count判断出窗口维护count 代码: …...

Android studio顶部‘app‘红叉- Moudle ‘XX.app’ dosen’t exist in project
Android studio顶部app红叉- Moudle ‘XX.app’ dosen’t exist in project 1、现象: 运行老项目或者有时候替换项目中的部分代码,明明没有错但是Android studio就编译报错了。 1.1 Android studio顶部app红叉。 1.2 点击Build没有clear菜单࿰…...

软考证书有用吗?软考证书的含金量大吗?
一、以考代评 通过考试并获得相应级别计算机专业技术资格(水平)证书的人员,表明其已具备从事相应专业岗位工作的水平和能力,用人单位可根据《工程技术人员职务试行条例》有关规定和工作需要,从获得计算机专业技术资格…...
自动化测试原理,怎么理解?【UI自动化】
首先,UI自动化是一种通过自动化工具或框架模拟用户与用户界面交互的测试技术。在软件开发过程中,这种技术对于确保用户界面的正确性和稳定性起着至关重要的作用。 具体来说,UI自动化的原理主要基于以下三个核心环节: 界面定位&am…...
typedef,#define,asserr,exit函数,free函数
一.typedef的应用 1.给已定的变量类型起个别名 加不加typedef,类型不变 (加之前是个数组,加之后是数组类型; 加之前是个函数指针,加之后是函数指针类型;) struct _person {char name[20];in…...

Linux的重要命令(二)+了解Linux目录结构
目录 一.Linux的目录结构 二.查看文件内容命令 1.cat 命令 2.more 命令 3.less 命令 4.head 命令 5.tail 命令 6.拓展 head 和 tail 的其他用法 编辑 三.统计文件内容的命令-wc 编辑 四.检索和过滤文件内容的命令-grep 编辑 编辑 五.压缩命令 gzip 和 bz…...
nmap使用
常用语句 主机发现和端口扫描 主机发现 sudo nmap -sn 192.168.80.0/24或sudo arp-scan -larp-scan是Kali Linux自带的一款ARP扫描工具。轻量级扫描工具,用来扫描局域网的主机还是挺好用的,由于扫描的少,所以扫描速度比较快,可…...

简约风好看的个人主页源码
效果图 PC端 移动端 源代码 index.html <html lang"en"><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&quo…...

1113. 红与黑--Flood Fill 算法
目录 1113. 红与黑--Flood Fill 算法---宽搜(BFS)或DFS) 输入格式 输出格式 数据范围 输入样例: 输出样例: 思路: 1.BFS 思路: 2.DFS 思路 方法一:(BFS&#x…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...