SpringBoot拦截器(Interceptor)深度解析与实践指南
springboot-guide SpringBoot2.0+从入门到实战! 项目地址: https://gitcode.com/gh_mirrors/sp/springboot-guide
一、拦截器基础概念
拦截器(Interceptor)是Spring框架中一个非常重要的组件,它基于AOP(面向切面编程)思想实现,主要用于在请求处理的不同阶段进行拦截和处理。与Servlet过滤器(Filter)类似,但拦截器提供了更精细的控制粒度。
拦截器与过滤器的本质区别
-
作用层面不同:
- 过滤器工作在Servlet层面,属于JavaEE标准
- 拦截器工作在Spring MVC层面,属于Spring框架特性
-
功能侧重点不同:
- 过滤器更关注请求的"过滤"(如字符编码设置、安全过滤等)
- 拦截器更关注请求处理流程的"干预"(如权限验证、日志记录等)
-
执行时机不同:
- 过滤器在Servlet容器接收到请求后立即执行
- 拦截器在DispatcherServlet处理请求的过程中执行
二、拦截器核心方法详解
Spring拦截器主要通过实现HandlerInterceptor
接口或继承HandlerInterceptorAdapter
类来实现,需要重写三个核心方法:
1. preHandle方法
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler)
执行时机:在Controller方法执行之前调用
返回值意义:
- 返回true:继续执行后续拦截器和Controller方法
- 返回false:中断执行流程,不会继续执行后续拦截器和Controller
典型应用场景:
- 权限校验
- 登录检查
- 请求参数预处理
2. postHandle方法
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
执行时机:在Controller方法执行之后,视图渲染之前调用
注意事项:
- 只有preHandle返回true时才会执行
- 可以对ModelAndView进行修改
典型应用场景:
- 向视图添加公共模型数据
- 统一处理返回结果
3. afterCompletion方法
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex)
执行时机:在整个请求完成之后调用(视图渲染完成后)
注意事项:
- 无论preHandle返回true还是false都会执行
- 适合进行资源清理工作
典型应用场景:
- 记录请求完成日志
- 资源释放
- 性能监控
三、实战:自定义拦截器开发
1. 日志记录拦截器实现
public class LogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
log.info("请求开始: URL={}, 时间={}",
request.getRequestURL(), startTime);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
long startTime = (Long)request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
log.info("请求完成: URL={}, 耗时={}ms",
request.getRequestURL(), (endTime - startTime));
}
}
2. 旧URL重定向拦截器实现
public class OldUrlRedirectInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 获取请求路径
String requestURI = request.getRequestURI();
// 如果是旧URL则重定向
if("/admin/oldLogin".equals(requestURI)) {
String contextPath = request.getContextPath();
response.sendRedirect(contextPath + "/admin/login");
return false; // 中断后续处理
}
return true;
}
}
3. 管理员权限校验拦截器实现
public class AdminAuthInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
HttpSession session = request.getSession();
Object adminUser = session.getAttribute("adminUser");
if(adminUser == null) {
// 未登录,跳转到登录页
response.sendRedirect(request.getContextPath() + "/admin/login");
return false;
}
return true;
}
}
四、拦截器配置详解
在Spring Boot中配置拦截器需要实现WebMvcConfigurer
接口:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 1. 添加日志拦截器,拦截所有请求
registry.addInterceptor(new LogInterceptor());
// 2. 添加旧URL重定向拦截器,只拦截特定路径
registry.addInterceptor(new OldUrlRedirectInterceptor())
.addPathPatterns("/admin/oldLogin");
// 3. 添加管理员权限拦截器,拦截/admin下所有请求
// 但排除登录相关请求
registry.addInterceptor(new AdminAuthInterceptor())
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/login", "/admin/doLogin");
}
}
配置方法说明:
addInterceptor()
:注册拦截器实例addPathPatterns()
:指定拦截路径(支持Ant风格)excludePathPatterns()
:指定排除路径
五、拦截器执行流程深度解析
1. 单个拦截器执行流程
preHandle → Controller → postHandle → 视图渲染 → afterCompletion
2. 多个拦截器执行流程
假设有Interceptor1和Interceptor2两个拦截器,执行顺序为:
Interceptor1.preHandle →
Interceptor2.preHandle →
Controller →
Interceptor2.postHandle →
Interceptor1.postHandle →
视图渲染 →
Interceptor2.afterCompletion →
Interceptor1.afterCompletion
关键点:
- preHandle按配置顺序执行
- postHandle按配置逆序执行
- afterCompletion按配置逆序执行
六、最佳实践与常见问题
1. 性能优化建议
- 在preHandle中进行轻量级检查
- 避免在拦截器中执行耗时操作
- 合理设计拦截路径,避免不必要的拦截
2. 常见问题解决方案
问题1:拦截器不生效
排查步骤:
- 检查是否添加了@Configuration注解
- 确认拦截路径是否正确
- 查看是否有其他配置覆盖了拦截器配置
问题2:静态资源被拦截
解决方案:
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static/**", "/resources/**");
七、高级应用场景
1. 接口限流拦截器
public class RateLimitInterceptor extends HandlerInterceptorAdapter {
private RateLimiter rateLimiter = RateLimiter.create(100); // 每秒100个请求
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
if(!rateLimiter.tryAcquire()) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
return false;
}
return true;
}
}
2. 多租户数据隔离拦截器
public class TenantInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String tenantId = request.getHeader("X-Tenant-ID");
if(StringUtils.isNotBlank(tenantId)) {
TenantContext.setCurrentTenant(tenantId);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
TenantContext.clear();
}
}
八、总结与扩展思考
Spring Boot拦截器是处理横切关注点的强大工具,合理使用可以:
- 实现统一的权限控制
- 进行请求日志记录
- 处理全局异常
- 实现接口限流
- 完成多租户隔离等复杂场景
扩展思考方向:
- 如何结合注解实现更灵活的拦截控制?
- 拦截器与Spring AOP如何配合使用?
- 在微服务架构中,拦截器与网关过滤器如何分工协作?
通过本文的详细讲解和实战示例,相信你已经掌握了Spring Boot拦截器的核心原理和实际应用方法。在实际项目中,可以根据业务需求灵活组合各种拦截器,构建强大的请求处理管道。
springboot-guide SpringBoot2.0+从入门到实战! 项目地址: https://gitcode.com/gh_mirrors/sp/springboot-guide
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考