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

这篇文章以梁山为背景的介绍SpringBoot中的拦截器,可能更通俗易懂。
希望对你会有所帮助,记得点赞和收藏。
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 收尾中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 90w+ 字,讲解图 3713+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有3200+小伙伴加入
第一把交椅: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);
returnfalse; // 关门放狗
}
returntrue;
}
}
// 衙门张贴告示
@Configuration
publicclass 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
publicclass FeignConfig {
@Bean
public FeignAuthInterceptor feignAuthInterceptor() {
returnnew 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
最后送给各位江湖儿女一句话:
拦截是门艺术,别让好刀砍了自己人!
👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
新项目:《从零手撸:仿小红书(微服务架构)》 收尾中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
专栏阅读地址:https://www.quanxiaoha.com/column
截止目前,累计输出 90w+ 字,讲解图 3713+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有3200+小伙伴加入
1. 我的私密学习小圈子,从0到1手撸企业实战项目~ 2. Spring Batch 批处理零基础速成指南,效率飙升 500%! 3. 风险管理利器:一款开源的实时风控引擎 4. 求求你们别再用 kill -9 了,这才是 Spring Boot 停机的正确方式!!!
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。 点“在看”支持小哈呀,谢谢啦