Spring拦截器(Interceptor)学习笔记
一、拦截器概述
1.1 什么是拦截器?
拦截器是Spring框架提供的一种动态拦截方法调用的机制,类似于Servlet中的过滤器(Filter)。主要特点包括:
- 动态拦截控制器方法的执行
- 在指定方法调用前后执行预设代码
- 用于处理通用性的业务逻辑(如登录校验、权限检查、日志记录等)
1.2 拦截器 vs 过滤器
特性 |
拦截器(Interceptor) |
过滤器(Filter) |
所属框架 |
Spring MVC |
Servlet规范 |
拦截范围 |
只拦截Spring环境中的资源 |
拦截所有资源 |
依赖 |
依赖Spring容器 |
不依赖任何框架 |
执行时机 |
Controller方法前后 |
Servlet处理前后 |
实现接口 |
HandlerInterceptor |
Filter |
二、拦截器快速入门
2.1 实现步骤
- 定义拦截器:实现
HandlerInterceptor
接口
- 注册配置:通过
WebMvcConfigurer
配置
2.2 代码实现
1) 自定义拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@Component
public class DemoInterceptor implements HandlerInterceptor {
// 目标方法执行前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle执行...");
return true; // true放行,false拦截
}
// 目标方法执行后调用(视图渲染前)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行...");
}
// 整个请求完成后调用(视图渲染后)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion执行...");
}
}
|
2) 注册拦截器
1
2
3
4
5
6
7
8
9
10
11
12
|
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private DemoInterceptor demoInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(demoInterceptor)
.addPathPatterns("/**"); // 拦截所有路径
}
}
|
2.3 执行顺序验证
当访问一个Controller方法时,控制台输出:
1
2
3
4
|
preHandle执行...
Controller方法执行...
postHandle执行...
afterCompletion执行...
|
注意:如果preHandle
返回false
,则后续流程都不会执行!
三、登录校验拦截器实战
3.1 令牌校验实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
@Slf4j
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 获取请求URL
String url = request.getRequestURL().toString();
// 2. 登录请求直接放行
if(url.contains("login")) {
log.info("登录请求,放行");
return true;
}
// 3. 获取token
String jwt = request.getHeader("token");
// 4. token不存在返回未登录
if(!StringUtils.hasLength(jwt)) {
log.error("令牌为空");
response.setStatus(HttpStatus.SC_UNAUTHORIZED); // 401
return false;
}
// 5. 解析token
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {
log.error("令牌解析失败");
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
return false;
}
// 6. 放行
log.info("令牌校验通过");
return true;
}
}
|
3.2 配置拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login"); // 排除登录接口
}
}
|
四、拦截器详解
4.1 拦截路径配置
1) 基本配置方法
addPathPatterns()
:添加拦截路径
excludePathPatterns()
:添加排除路径
1
2
3
|
registry.addInterceptor(interceptor)
.addPathPatterns("/**") // 拦截所有
.excludePathPatterns("/login"); // 排除登录
|
2) 常见路径模式
模式 |
说明 |
/* |
一级路径(如/user ) |
/** |
任意级路径(如/user/1 ) |
/admin/** |
拦截/admin 下的所有路径 |
/secure/*.do |
拦截/secure 下的所有.do请求 |
4.2 拦截器执行流程
完整请求生命周期
- 过滤器前置处理
- DispatcherServlet接收请求
- 拦截器preHandle
- Controller方法执行
- 拦截器postHandle
- 视图渲染
- 拦截器afterCompletion
- 过滤器后置处理
执行流程图

五、最佳实践建议
-
登录校验:推荐使用拦截器而非过滤器
- 能利用Spring的依赖注入
- 更精准控制Spring环境中的请求
-
路径配置:
1
2
3
4
|
// 推荐配置方式
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
|
-
性能优化:
- 在
preHandle
中进行轻量级检查
- 避免在拦截器中执行耗时操作
-
多拦截器顺序:
1
2
|
registry.addInterceptor(interceptor1).order(1);
registry.addInterceptor(interceptor2).order(2);
|
六、常见问题解答
Q1:拦截器和过滤器如何选择?
- 需要处理Spring相关功能(如自动注入、AOP等)→ 拦截器
- 需要处理静态资源、非Spring请求 → 过滤器
Q2:拦截器能获取Controller方法信息吗?
可以,通过handler
参数:
1
2
3
4
5
|
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
// 可以获取方法注解等信息
}
|
Q3:拦截器中如何修改响应数据?
可以在postHandle
中操作ModelAndView
:
1
2
3
4
|
@Override
public void postHandle(...) {
modelAndView.addObject("newData", "value");
}
|