拦截器Interceptor
拦截器是SpringMVC提供的请求处理扩展点,在Handler执行前后进行拦截处理。
接口定义
Java
public interface HandlerInterceptor {
// Handler执行前
default boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
return true;
}
// Handler执行后,视图渲染前
default void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) {
}
// 视图渲染后,响应发送前
default void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler,
Exception ex) {
}
}
三个方法详解
| 方法 | 执行时机 | 返回值 | 作用 |
|---|---|---|---|
| preHandle | Handler执行前 | boolean | 认证、授权、预处理 |
| postHandle | Handler执行后 | void | 修改ModelAndView |
| afterCompletion | 视图渲染后 | void | 资源清理、异常处理 |
HandlerExecutionChain
Java
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
private int interceptorIndex = -1;
// 正序执行preHandle
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
// 返回false时触发已执行拦截器的afterCompletion
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
return true;
}
// 逆序执行postHandle
void applyPostHandle(HttpServletRequest request, HttpServletResponse response,
ModelAndView modelAndView) {
for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, modelAndView);
}
}
// 逆序执行afterCompletion(只执行preHandle成功的)
void triggerAfterCompletion(HttpServletRequest request,
HttpServletResponse response, Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
interceptor.afterCompletion(request, response, this.handler, ex);
}
}
}
执行顺序示例
Java
请求 → Interceptor1.preHandle(true)
→ Interceptor2.preHandle(true)
→ Interceptor3.preHandle(true)
→ Handler执行
→ Interceptor3.postHandle
→ Interceptor2.postHandle
→ Interceptor1.postHandle
→ 视图渲染
→ Interceptor3.afterCompletion
→ Interceptor2.afterCompletion
→ Interceptor1.afterCompletion
→ 响应
典型实现场景
认证拦截器
Java
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
String token = request.getHeader("Authorization");
if (token == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"error\":\"未授权\"}");
return false;
}
// 校验token
User user = userService.validateToken(token);
if (user == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
// 设置用户到请求上下文
request.setAttribute("currentUser", user);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
// 清理上下文
request.removeAttribute("currentUser");
}
}
日志拦截器
Java
@Component
public class LogInterceptor implements HandlerInterceptor {
private static final String START_TIME = "startTime";
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
request.setAttribute(START_TIME, System.currentTimeMillis());
log.info("请求开始: {} {} {}", request.getMethod(),
request.getRequestURI(), request.getRemoteAddr());
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) {
log.info("Handler执行完成: {}", handler);
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
long startTime = (Long) request.getAttribute(START_TIME);
long duration = System.currentTimeMillis() - startTime;
if (ex != null) {
log.error("请求异常: {} {} 耗时{}ms 异常:{}",
request.getMethod(), request.getRequestURI(),
duration, ex.getMessage());
} else {
log.info("请求完成: {} {} 耗时{}ms 状态:{}",
request.getMethod(), request.getRequestURI(),
duration, response.getStatus());
}
}
}
性能监控拦截器
Java
@Component
public class PerformanceInterceptor implements HandlerInterceptor {
private static final String PERF_KEY = "performance";
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
PerformanceStats stats = new PerformanceStats();
stats.setStartTime(System.currentTimeMillis());
stats.setStartMemory(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
request.setAttribute(PERF_KEY, stats);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
PerformanceStats stats = (PerformanceStats) request.getAttribute(PERF_KEY);
stats.setEndTime(System.currentTimeMillis());
stats.setEndMemory(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
long duration = stats.getEndTime() - stats.getStartTime();
long memoryUsed = stats.getEndMemory() - stats.getStartMemory();
// 记录性能指标
if (duration > 1000) {
log.warn("慢请求: {} {} 耗时{}ms 内存{}KB",
request.getMethod(), request.getRequestURI(),
duration, memoryUsed / 1024);
}
}
}
权限拦截器
Java
@Component
public class PermissionInterceptor implements HandlerInterceptor {
@Autowired
private PermissionService permissionService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 检查方法上的@RequirePermission注解
RequirePermission annotation = handlerMethod.getMethodAnnotation(RequirePermission.class);
if (annotation == null) {
// 检查类上的注解
annotation = handlerMethod.getBeanType().getAnnotation(RequirePermission.class);
}
if (annotation != null) {
User user = (User) request.getAttribute("currentUser");
if (user == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
return false;
}
// 检查权限
if (!permissionService.hasPermission(user, annotation.value())) {
response.setStatus(HttpStatus.FORBIDDEN.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"error\":\"无权限\"}");
return false;
}
}
}
return true;
}
}
// 权限注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
String value();
}
注册拦截器
WebMvcConfigurer方式
Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 认证拦截器
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**", "/api/auth/**")
.order(1);
// 权限拦截器
registry.addInterceptor(new PermissionInterceptor())
.addPathPatterns("/api/**")
.order(2);
// 日志拦截器
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**")
.order(3);
}
}
InterceptorRegistration详解
Java
public class InterceptorRegistration {
private HandlerInterceptor interceptor;
private List<String> includePatterns = new ArrayList<>();
private List<String> excludePatterns = new ArrayList<>();
private int order = 0;
// 添加拦截路径
public InterceptorRegistration addPathPatterns(String... patterns) {
this.includePatterns.addAll(Arrays.asList(patterns));
return this;
}
// 排除路径
public InterceptorRegistration excludePathPatterns(String... patterns) {
this.excludePatterns.addAll(Arrays.asList(patterns));
return this;
}
// 设置顺序
public InterceptorRegistration order(int order) {
this.order = order;
return this;
}
}
AsyncHandlerInterceptor
Java
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
// 异步请求开始时调用
default void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response, Object handler) {
}
}
// 异步请求拦截器实现
@Component
public class AsyncInterceptor implements AsyncHandlerInterceptor {
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response, Object handler) {
log.info("异步处理开始: {}", request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
log.info("异步处理完成: {}", request.getRequestURI());
}
}
MappedInterceptor
Java
// 带路径匹配的拦截器包装
public class MappedInterceptor implements HandlerInterceptor {
private final String[] includePatterns;
private final String[] excludePatterns;
private final HandlerInterceptor interceptor;
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
// 检查是否在包含路径中
if (matches(includePatterns, lookupPath, pathMatcher)) {
// 检查是否在排除路径中
if (!matches(excludePatterns, lookupPath, pathMatcher)) {
return true;
}
}
return false;
}
}
拦截器获取Handler信息
text
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取Controller类名
String controllerName = handlerMethod.getBeanType().getSimpleName();
// 获取方法名
String methodName = handlerMethod.getMethod().getName();
// 获取方法参数
MethodParameter[] parameters = handlerMethod.getMethodParameters();
// 获取方法注解
RequestMapping mapping = handlerMethod.getMethodAnnotation(RequestMapping.class);
log.info("处理方法: {}#{}", controllerName, methodName);
}
return true;
}
拦截器通过HandlerExecutionChain形成责任链,preHandle正序执行控制流程,postHandle和afterCompletion逆序执行。
要点总结
- HandlerInterceptor定义三个拦截点:preHandle、postHandle、afterCompletion
- preHandle返回false终止链条,触发已执行拦截器的afterCompletion
- postHandle逆序执行,可修改ModelAndView
- afterCompletion保证执行,用于资源清理
- AsyncHandlerInterceptor扩展异步请求处理
jwdev/articles/SPRINGMVC/专家/容器级WEB组件扩展/容器级WEB组件扩展/拦截器Interceptor.md
📝 发现内容有误?点击此处直接编辑