【拦截器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…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...