SpringBoot中的拦截器江湖
前言
很多小伙伴在工作中遇到拦截需求就无脑写HandlerInterceptor,结果被复杂场景搞得鼻青脸肿。
作为一名有多年开发经验的程序员,今天领大家到SpringBoot的山头认认6把交椅:

这篇文章以梁山为背景的介绍SpringBoot中的拦截器,可能更通俗易懂。
希望对你会有所帮助,记得点赞和收藏。
第一把交椅:Filter
Filter是梁山中的总寨主。
典型战斗场面:全局鉴权/接口耗时统计
@WebFilter("/*")
public class CostFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
long start = System.currentTimeMillis();
chain.doFilter(req, res); // 放行江湖令箭
System.out.println("接口耗时:"+(System.currentTimeMillis()-start)+"ms");
}
}
起义缘由:必须是最高寨主,因为他在Servlet容器滚刀肉层面出手。想当年有个兄弟在Filter里调用Spring Bean,结果NPE错杀千人(要用WebApplicationContextUtils拿Bean才是正解)
第二把交椅:HandlerInterceptor
HandlerInterceptor是梁山中的二当家。
必杀场景:接口权限验证/请求参数自动装填
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("X-Token");
if(!"vip666".equals(token)){
response.setStatus(403);
return false; // 关门放狗
}
return true;
}
}
// 衙门张贴告示
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
}
二当家的雷区:
- postHandle里修改了Response但内容已提交(注意response.isCommitted()判断)
- 拦截资源请求要配置静态路径排出(例如/exclude/**)
- 多拦截器顺序要调准确(Order值越小越早执行)
第三把交椅:AOP拦截器
AOP是梁山中的军师智多星。
运筹帷幄场景:服务层方法缓存/事务管理
@Aspect
@Component
public class CacheAspect {
@Around("@annotation(com.example.anno.Cacheable)")
public Object aroundCache(ProceedingJoinPoint jp) {
String cacheKey = buildKey(jp);
Object cacheVal = redisTemplate.opsForValue().get(cacheKey);
if(cacheVal != null) return cacheVal;
Object result = jp.proceed();
redisTemplate.opsForValue().set(cacheKey, result, 5, TimeUnit.MINUTES);
return result;
}
}
军师锦囊:
- 只可拦截Spring管理的Bean(new的对象拦截不了)
- 与Transactional注解的顺序要注意(建议AOP切面Order大于事务切面)
- 自定义注解要写在接口方法上才生效(要是实现类方法需要用@within)
第四把交椅:RestTemplate拦截器
RestTemplate是梁山中的水军头领。
远程战事:统一添加请求头/加密请求参数
public class TraceInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
request.getHeaders().add("X-TraceId", UUID.randomUUID().toString());
return execution.execute(request, body);
}
}
// 注册水军
@Bean
public RestTemplate restTemplate() {
RestTemplate rt = new RestTemplate();
rt.getInterceptors().add(new TraceInterceptor());
return rt;
}
总督黑历史:
- 编码问题:body若是字符串需要自行转字节数组(避免乱码)
- 多次拦截:拦截器按添加顺序执行(第一个最后执行)
- 访问HTTPS需要额外配置SSL(记得补上SSLContext)
第五把交椅:Feign拦截器
Feign拦截器是梁山中的外交使节。
出使外国:统一签名计算/Header透传
public class FeignAuthInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
template.header("Authorization", "Bearer " + SecurityContext.getToken());
}
}
// 缔结合约
@Configuration
public class FeignConfig {
@Bean
public FeignAuthInterceptor feignAuthInterceptor() {
return new FeignAuthInterceptor();
}
}
使节烫手山芋:
- GET请求Body丢失问题(要自己特殊处理)
- Form表单参数要手动编码(使用feign-form扩展)
- Path参数需要Expression表达式解析(动态值要用@Param注明)
第六把交椅:WebFilter
WebFilter是梁山中的特种兵。
闪电战场景:响应式编程统一编码/跨域处理
@Component
public class CorsWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add("Access-Control-Allow-Origin", "*");
return chain.filter(exchange);
}
}
作战条件:
- 必须在WebFlux环境下(传统MVC无效)
- 响应式编程模式(函数式声明)
- 非阻塞管道(异步要配合Mono/Flux)
各派武功排行榜
| 门派 | 攻击范围 | 招式复杂度 | 内力消耗 | 首选战场 |
|---|---|---|---|---|
| Filter | 全局最外层 | ★★☆☆☆ | 低 | 安全校验/日志记录 |
| Handler | MVC控制器层 | ★★★☆☆ | 中 | 权限控制 |
| AOP | 业务方法级 | ★★★★☆ | 高 | 缓存/事务 |
| RestTemplate | HTTP客户端 | ★★★☆☆ | 中 | 服务间调用 |
| Feign | 声明式客户端 | ★★★★☆ | 高 | 微服务通信 |
| WebFilter | 响应式全链路 | ★★★★★ | 极高 | WebFlux应用 |
武林秘笈
1. 顺序就是力量
Filter -> Interceptor -> AOP ,越早拦截越省力(但别在Filter里做业务)
2. 量力而行选兵器
- 简单鉴权用HandlerInterceptor
- 方法级管控上AOP
- 微服务用FeignInterceptor
3. 性能损耗要监控
用Arthas监控拦截链路耗时,避免拦截器连环夺命call
# 查看HandlerInterceptor耗时
trace *.preHandle '#cost>10'
# 诊断AOP切面
watch com.example.aop.*Aspect * '{params,returnObj}' -x 3
最后送给各位江湖儿女一句话:拦截是门艺术,别让好刀砍了自己人!
最后说一句(求关注,别白嫖我)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的50万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
SpringBoot中的拦截器江湖的更多相关文章
- 在springboot中使用拦截器
在springMVC中可以实现拦截器,是通过实现HandlerInterceptor接口,然后在springmvc-web.xml中配置就可以使用拦截器了.在springboot中拦截器也是一样的思想 ...
- springmvc以及springboot中的拦截器配置
拦截器两种实现 如果不同的controller中都需要拦截器,不能使用相同的拦截器,因为拦截器不能跨controller,这个时候只能为不同的controller配置不同的拦截器,每一个拦截器只能 ...
- springboot中使用拦截器、监听器、过滤器
拦截器.过滤器.监听器在web项目中很常见,这里对springboot中怎么去使用做一个总结. 1. 拦截器(Interceptor) 我们需要对一个类实现HandlerInterceptor接 ...
- Springboot中SpringMvc拦截器配置与应用(实战)
一.什么是拦截器,及其作用 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对 ...
- 解决 Springboot中Interceptor拦截器中依赖注入失败
问题: 在Springboot拦截器Interceptor中使用@Resource依赖注入时,发现运行的时候被注解的对象居然是null,没被注入进去 原配置为: @Configurationpubli ...
- springboot中使用拦截器
5.1 回顾SpringMVC使用拦截器步骤 自定义拦截器类,实现HandlerInterceptor接口 注册拦截器类 5.2 Spring Boot使用拦截器步骤 5.2.1 按照S ...
- springboot(五).如何在springboot项目中使用拦截器
在每个项目中,拦截器都是我们经常会去使用的东西,基本上任一一个项目都缺不了拦截器的使用. 如日志记录.登录验证,session验证等,都需要拦截器来拦截URL请求,那springboot中的拦截器是如 ...
- springboot的interceptor(拦截器)的应用
一.SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.在web开发中,拦截器是经常用到的功能.它可以帮我们验证是否登陆.预先 ...
- SpringBoot如何添加拦截器
在web开发的过程中,为了实现登录权限验证,我们往往需要添加一个拦截器在用户的的请求到达controller层的时候实现登录验证,那么SpringBoot如何添加拦截器呢? 步骤如下: 1.继承Web ...
- 分享知识-快乐自己:SpringBoot结合使用拦截器(判断是否用户是否已登陆)
所有的开发之中拦截器一定是一个必须要使用的功能,利用拦截器可以更加有效的实现数据的验证处理,而且最为幸运的是在SpringBoot之中所使用的拦截器与Spring中的拦截器完全一样. 基础拦截器操作: ...
随机推荐
- 删除binlog日志
手动删除 在备库检查正在使用的binlog SHOW REPLICA STATUS 在主库获取binlog列表 SHOW BINARY LOGS 删除备库使用前或主库正在写入前的binlog 不要将正 ...
- 【译】HTTP 文件更新了请求变量
许多用户都要求在 Visual Studio 的 HTTP 文件中添加对请求变量的支持.使用请求变量,您可以发送 HTTP 请求,然后在从 HTTP 文件发送的任何后续请求中使用响应或请求中的数据.我 ...
- 技术前瞻: ECMAScript 2025 已定稿特性解析:让 JavaScript 更优雅
作为全球应用最广泛的编程语言之一,JavaScript 每年都在通过 ECMAScript 标准持续进化.2025 年,ECMAScript 再次带来多项重磅更新,本文将带你深入解读已正式定稿的核心特 ...
- Docker - 部署IT运维管理平台CAT
原文链接:https://mp.weixin.qq.com/s/Ld9OLnmHP1IAc0Ofo-RzeQ 一.CAT介绍(略) 二.环境规划(略) 三.检查环境(略) 四.部署cat镜像 1.下载 ...
- 题解:SP6517 JOCHEF - Farmer Sepp
怎么题解全是 dp?可以用笛卡尔树啊! 题目传送门. 笛卡尔树的介绍 笛卡尔树,是一种二叉搜索树,它满足如下条件: 每个节点的编号满足二叉搜索树的性质. 每个节点的权值满足小根堆或大根堆的性质. 大概 ...
- Ubuntu20.04 安装 .NET Core SDK
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-micr ...
- FastAPI 请求体参数与 Pydantic 模型完全指南:从基础到嵌套模型实战 🚀
title: FastAPI 请求体参数与 Pydantic 模型完全指南:从基础到嵌套模型实战 date: 2025/3/7 updated: 2025/3/7 author: cmdragon e ...
- CTF常见密码汇总
栅栏密码 fg2ivyo}l{2s3_o@aw__rcl@-->flag{w22_is_v3ry_cool} https://tool.bugku.com/jiemi/ 所谓栅栏密码,就是把要加 ...
- Mermaid Live Editor 如何调整方向
在 Mermaid Live Editor 中,默认情况下,流程图和序列图等都是按照从左到右的方向来布局的.但是,如果你想要创建一个从上到下(纵向)布局的图形,你可以使用 TD(Top-Down,即从 ...
- docker pause 命令使用
暂停正在运行的镜像容器 用途是在启动的容器的过程又的容器启动快了 有的还没有就绪 调试过程使用 a3: 正在运行的镜像容器简称 暂停: docker pause a3 解除暂停: docker unp ...