拦截器概述
在 Spring 框架中,拦截器(Interceptor)是一种强大的机制,它允许开发者在请求处理的不同阶段插入自定义逻辑。WebApplicationContext 作为 Spring Web 应用的上下文容器,为拦截器的配置和管理提供了基础支持。
拦截器主要作用于以下场景:
权限验证
日志记录
性能监控
事务管理
通用行为注入等
拦截器与 WebApplicationContext 的关系
WebApplicationContext 是 Spring Web 应用的 IoC 容器扩展,它继承自 ApplicationContext,并添加了 Web 应用特有的功能。拦截器通过 WebApplicationContext 进行注册和管理,成为请求处理管道的一部分。
public interface WebApplicationContext extends ApplicationContext { String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; ServletContext getServletContext();}
复制代码
拦截器类型
HandlerInterceptor
最常用的拦截器接口,定义了三个关键方法:
public interface HandlerInterceptor { default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }}
复制代码
AsyncHandlerInterceptor
HandlerInterceptor 的扩展,增加了异步处理的支持。
WebRequestInterceptor
与 HandlerInterceptor 类似,但提供了更通用的 WebRequest 抽象,不依赖于 Servlet API。
拦截器配置
XML 配置方式
Java 配置方式
@Configuration@EnableWebMvcpublic class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoggingInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/static/**"); registry.addInterceptor(new AuthInterceptor()) .addPathPatterns("/admin/**"); }}
复制代码
注解方式
@Componentpublic class MyInterceptor implements HandlerInterceptor { // 实现方法}
@Configurationpublic class InterceptorConfig { @Autowired private MyInterceptor myInterceptor; @Bean public WebMvcConfigurer adapter() { return new WebMvcConfigurer() { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor); } }; }}
复制代码
拦截器执行流程
拦截器在 DispatcherServlet 的处理流程中扮演重要角色:
返回 true 继续执行
返回 false 中断请求处理
可修改 ModelAndView
适合资源清理
高级拦截器特性
拦截器顺序控制
可以通过 order 属性控制多个拦截器的执行顺序:
registry.addInterceptor(new InterceptorA()).order(1);registry.addInterceptor(new InterceptorB()).order(2);
复制代码
路径匹配模式
支持 Ant 风格的路径模式:
? 匹配一个字符
匹配零个或多个字符
** 匹配零个或多个目录
异步请求处理
对于异步请求,afterConcurrentHandlingStarted 方法会被调用而不是 postHandle 和 afterCompletion。
拦截器与过滤器的区别
实际应用示例
日志拦截器
public class LoggingInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); logger.info("Request URL: {} : Start Time={}", 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(); logger.info("Request URL: {} : End Time={} : Time Taken={}ms", request.getRequestURL(), endTime, (endTime - startTime)); }}
复制代码
认证拦截器
public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); if (session.getAttribute("user") == null) { response.sendRedirect("/login"); return false; } return true; }}
复制代码
DEMO 实测效果
被拦截
未被拦截
评论