一文带你读懂Java拦截器(Interceptor)
本文全面介绍Java拦截器(Interceptor),主要内容包括:1.拦截器简介,对比拦截器、过滤器和AOP的区别;2.源码分析,详细解析HandlerInterceptor接口、HandlerInterceptorAdapter抽象类等核心组件;3.拦截器执行流程,通过时序图和源码展示处理过程。拦截器作为Spring框架的重要组件,可用于权限验证、日志记录等场景,具有前置处理、后置处理和异常处
·
Java拦截器(Interceptor)看这篇文章就够了
目录
1. 拦截器简介
1.1 什么是拦截器
拦截器(Interceptor)是Spring框架中用于在请求处理前后进行拦截处理的组件,它可以在方法执行前、执行后、抛出异常时进行干预。
1.2 核心特性
- 前置处理: 在目标方法执行前进行拦截
- 后置处理: 在目标方法执行后进行拦截
- 异常处理: 在目标方法抛出异常时进行拦截
- 链式调用: 支持多个拦截器按顺序执行
1.3 拦截器 vs 过滤器 vs AOP
特性 | 拦截器(Interceptor) | 过滤器(Filter) | AOP |
---|---|---|---|
作用范围 | Spring MVC请求 | 所有Web请求 | 方法级别 |
执行时机 | Controller方法前后 | Servlet前后 | 方法执行前后 |
依赖框架 | Spring MVC | Servlet容器 | Spring AOP |
性能开销 | 较低 | 最低 | 较高 |
使用场景 | 权限验证、日志记录 | 编码转换、跨域处理 | 事务管理、日志 |
2. 源码分析
2.1 核心接口和类
2.1.1 HandlerInterceptor接口
public interface HandlerInterceptor {
// 前置处理,返回true继续执行,返回false中断执行
default boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
return true;
}
// 后置处理,在视图渲染前执行
default void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
// 完成处理,在视图渲染后执行
default void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable Exception ex) throws Exception {
}
}
2.1.2 HandlerInterceptorAdapter抽象类
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
// 提供默认实现,子类只需重写需要的方法
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
}
}
2.1.3 AsyncHandlerInterceptor接口
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
// 异步请求开始后执行
default void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
}
}
2.2 拦截器执行流程
2.2.1 执行时序图
2.2.2 HandlerExecutionChain源码分析
public class HandlerExecutionChain {
private final Object handler;
private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
private int interceptorIndex = -1;
// 前置处理
boolean applyPreHandle(HttpServletRequest request,
HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
// 后置处理
void applyPostHandle(HttpServletRequest request,
HttpServletResponse response,
ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = interceptors.length - 1; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
interceptor.postHandle(request, response, this.handler, mv);
}
}
}
// 完成处理
void triggerAfterCompletion(HttpServletRequest request,
HttpServletResponse response,
Exception ex) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = this.interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
}
2.3 拦截器注册机制
2.3.1 WebMvcConfigurer配置
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**") // 拦截路径
.excludePathPatterns("/static/**", "/public/**"); // 排除路径
// 添加权限拦截器
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/admin/**", "/user/**")
.excludePathPatterns("/login", "/register");
}
}
2.3.2 拦截器注册源码
public class InterceptorRegistry {
private final List<InterceptorRegistration> registrations = new ArrayList<>();
public InterceptorRegistration addInterceptor(HandlerInterceptor interceptor) {
InterceptorRegistration registration = new InterceptorRegistration(interceptor);
this.registrations.add(registration);
return registration;
}
protected List<Object> getInterceptors() {
List<Object> interceptors = new ArrayList<>();
for (InterceptorRegistration registration : this.registrations) {
interceptors.add(registration.getInterceptor());
}
return interceptors;
}
}
3. 设计模式分析
3.1 责任链模式(Chain of Responsibility)
3.1.1 模式结构
3.1.2 实现原理
- HandlerExecutionChain: 责任链的维护者
- HandlerInterceptor: 责任链中的处理节点
- 顺序执行: 前置处理按正序,后置处理按倒序
3.2 模板方法模式(Template Method)
3.2.1 模式结构
public abstract class AbstractInterceptor implements HandlerInterceptor {
// 模板方法
public final boolean handle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 1. 前置处理
if (!preHandle(request, response, handler)) {
return false;
}
try {
// 2. 执行目标方法
Object result = executeHandler(request, response, handler);
// 3. 后置处理
postHandle(request, response, handler, result);
return true;
} catch (Exception e) {
// 4. 异常处理
handleException(request, response, handler, e);
return false;
} finally {
// 5. 完成处理
afterCompletion(request, response, handler, null);
}
}
// 抽象方法,子类必须实现
protected abstract Object executeHandler(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception;
// 钩子方法,子类可选择重写
protected void handleException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception e) {
// 默认异常处理逻辑
}
}
3.3 策略模式(Strategy)
3.3.1 模式结构
public interface InterceptorStrategy {
boolean shouldIntercept(HttpServletRequest request, Object handler);
void doIntercept(HttpServletRequest request, HttpServletResponse response);
}
public class PathBasedStrategy implements InterceptorStrategy {
private final String pathPattern;
@Override
public boolean shouldIntercept(HttpServletRequest request, Object handler) {
String requestPath = request.getRequestURI();
return PathMatcher.match(pathPattern, requestPath);
}
@Override
public void doIntercept(HttpServletRequest request, HttpServletResponse response) {
// 路径匹配的拦截逻辑
}
}
public class MethodBasedStrategy implements InterceptorStrategy {
private final String methodName;
@Override
public boolean shouldIntercept(HttpServletRequest request, Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
return methodName.equals(handlerMethod.getMethod().getName());
}
return false;
}
@Override
public void doIntercept(HttpServletRequest request, HttpServletResponse response) {
// 方法匹配的拦截逻辑
}
}
3.4 装饰器模式(Decorator)
3.4.1 模式结构
public class InterceptorDecorator implements HandlerInterceptor {
private final HandlerInterceptor interceptor;
private final List<InterceptorEnhancer> enhancers;
public InterceptorDecorator(HandlerInterceptor interceptor,
List<InterceptorEnhancer> enhancers) {
this.interceptor = interceptor;
this.enhancers = enhancers;
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 前置增强
for (InterceptorEnhancer enhancer : enhancers) {
enhancer.beforePreHandle(request, response, handler);
}
boolean result = interceptor.preHandle(request, response, handler);
// 后置增强
for (InterceptorEnhancer enhancer : enhancers) {
enhancer.afterPreHandle(request, response, handler, result);
}
return result;
}
}
public interface InterceptorEnhancer {
void beforePreHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler);
void afterPreHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
boolean result);
}
4. 项目应用场景
4.1 权限验证拦截器
4.1.1 实现代码
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Autowired
private PermissionService permissionService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 1. 获取请求路径
String requestURI = request.getRequestURI();
// 2. 检查是否需要权限验证
if (isPublicPath(requestURI)) {
return true;
}
// 3. 获取用户信息
String token = getTokenFromRequest(request);
if (StringUtils.isEmpty(token)) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().write("未提供认证令牌");
return false;
}
// 4. 验证用户权限
User user = userService.getUserByToken(token);
if (user == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().write("用户认证失败");
return false;
}
// 5. 检查访问权限
if (!permissionService.hasPermission(user, requestURI)) {
response.setStatus(HttpStatus.FORBIDDEN.value());
response.getWriter().write("权限不足");
return false;
}
// 6. 将用户信息存入请求属性
request.setAttribute("currentUser", user);
return true;
}
private boolean isPublicPath(String path) {
List<String> publicPaths = Arrays.asList("/login", "/register", "/public/**");
return publicPaths.stream().anyMatch(path::matches);
}
private String getTokenFromRequest(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (StringUtils.isNotEmpty(token) && token.startsWith("Bearer ")) {
return token.substring(7);
}
return request.getParameter("token");
}
}
4.1.2 配置注册
@Configuration
public class SecurityConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**", "/api/auth/**");
}
}
4.2 日志记录拦截器
4.2.1 实现代码
@Component
public class LogInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
private final ThreadLocal<String> requestId = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 1. 生成请求ID
String reqId = UUID.randomUUID().toString();
requestId.set(reqId);
// 2. 记录开始时间
startTime.set(System.currentTimeMillis());
// 3. 记录请求信息
logger.info("请求开始 - ID: {}, URI: {}, Method: {}, IP: {}, User-Agent: {}",
reqId, request.getRequestURI(), request.getMethod(),
getClientIP(request), request.getHeader("User-Agent"));
// 4. 将请求ID添加到响应头
response.setHeader("X-Request-ID", reqId);
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
String reqId = requestId.get();
logger.info("请求处理完成 - ID: {}, Status: {}",
reqId, response.getStatus());
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
String reqId = requestId.get();
Long start = startTime.get();
long duration = System.currentTimeMillis() - start;
// 记录请求完成信息
if (ex != null) {
logger.error("请求异常 - ID: {}, Duration: {}ms, Exception: {}",
reqId, duration, ex.getMessage(), ex);
} else {
logger.info("请求完成 - ID: {}, Duration: {}ms", reqId, duration);
}
// 清理ThreadLocal
requestId.remove();
startTime.remove();
}
private String getClientIP(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotEmpty(xForwardedFor)) {
return xForwardedFor.split(",")[0].trim();
}
String xRealIP = request.getHeader("X-Real-IP");
if (StringUtils.isNotEmpty(xRealIP)) {
return xRealIP;
}
return request.getRemoteAddr();
}
}
4.3 性能监控拦截器
4.3.1 实现代码
@Component
public class PerformanceInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(PerformanceInterceptor.class);
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
private final ThreadLocal<String> methodName = new ThreadLocal<>();
// 性能阈值配置
@Value("${interceptor.performance.warn-threshold:1000}")
private long warnThreshold;
@Value("${interceptor.performance.error-threshold:5000}")
private long errorThreshold;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
startTime.set(System.currentTimeMillis());
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
String className = handlerMethod.getBeanType().getSimpleName();
String methodNameStr = handlerMethod.getMethod().getName();
methodName.set(className + "." + methodNameStr);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
Long start = startTime.get();
if (start != null) {
long duration = System.currentTimeMillis() - start;
String method = methodName.get();
// 性能监控和告警
if (duration > errorThreshold) {
logger.error("性能告警 - 方法: {}, 耗时: {}ms (超过错误阈值: {}ms)",
method, duration, errorThreshold);
// 发送告警通知
sendPerformanceAlert(method, duration, "ERROR");
} else if (duration > warnThreshold) {
logger.warn("性能警告 - 方法: {}, 耗时: {}ms (超过警告阈值: {}ms)",
method, duration, warnThreshold);
// 发送警告通知
sendPerformanceAlert(method, duration, "WARN");
} else {
logger.debug("性能正常 - 方法: {}, 耗时: {}ms", method, duration);
}
// 记录性能指标
recordPerformanceMetrics(method, duration);
}
// 清理ThreadLocal
startTime.remove();
methodName.remove();
}
private void sendPerformanceAlert(String method, long duration, String level) {
// 实现告警逻辑,如发送邮件、短信、钉钉等
PerformanceAlert alert = PerformanceAlert.builder()
.method(method)
.duration(duration)
.level(level)
.timestamp(LocalDateTime.now())
.build();
// 异步发送告警
CompletableFuture.runAsync(() -> {
alertService.sendAlert(alert);
});
}
private void recordPerformanceMetrics(String method, long duration) {
// 记录性能指标到监控系统
PerformanceMetrics metrics = PerformanceMetrics.builder()
.method(method)
.duration(duration)
.timestamp(System.currentTimeMillis())
.build();
metricsService.record(metrics);
}
}
4.4 跨域处理拦截器
4.4.1 实现代码
@Component
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 设置CORS响应头
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers",
"Content-Type, Authorization, X-Requested-With");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
// 处理预检请求
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpStatus.OK.value());
return false; // 不继续执行后续拦截器和处理器
}
return true;
}
}
4.5 限流拦截器
4.5.1 实现代码
@Component
public class RateLimitInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, String> redisTemplate;
// 限流配置
@Value("${interceptor.ratelimit.default-limit:100}")
private int defaultLimit;
@Value("${interceptor.ratelimit.default-window:60}")
private int defaultWindow;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String clientIP = getClientIP(request);
String requestURI = request.getRequestURI();
String key = "rate_limit:" + clientIP + ":" + requestURI;
// 获取当前时间窗口的请求次数
String currentCount = redisTemplate.opsForValue().get(key);
int count = currentCount == null ? 0 : Integer.parseInt(currentCount);
if (count >= defaultLimit) {
// 超过限流阈值
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":429,\"message\":\"请求过于频繁,请稍后再试\"}");
return false;
}
// 增加请求计数
if (count == 0) {
redisTemplate.opsForValue().set(key, "1", defaultWindow, TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().increment(key);
}
// 添加限流信息到响应头
response.setHeader("X-RateLimit-Limit", String.valueOf(defaultLimit));
response.setHeader("X-RateLimit-Remaining", String.valueOf(defaultLimit - count - 1));
response.setHeader("X-RateLimit-Reset",
String.valueOf(System.currentTimeMillis() / 1000 + defaultWindow));
return true;
}
private String getClientIP(HttpServletRequest request) {
String xForwardedFor = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotEmpty(xForwardedFor)) {
return xForwardedFor.split(",")[0].trim();
}
return request.getRemoteAddr();
}
}
5. 面试高频点
5.1 基础概念类
5.1.1 拦截器与过滤器的区别
答案要点:
- 作用范围: 拦截器只拦截Spring MVC请求,过滤器拦截所有Web请求
- 执行时机: 拦截器在Controller方法前后执行,过滤器在Servlet前后执行
- 依赖框架: 拦截器依赖Spring MVC,过滤器依赖Servlet容器
- 性能开销: 拦截器开销较低,过滤器开销最低
- 使用场景: 拦截器适合业务逻辑处理,过滤器适合通用处理
扩展问题:
- 拦截器能拦截静态资源吗?
- 过滤器能获取Spring容器中的Bean吗?
5.1.2 拦截器的执行顺序
答案要点:
- 前置处理: 按拦截器注册顺序执行preHandle()
- 目标方法: 执行Controller方法
- 后置处理: 按拦截器注册倒序执行postHandle()
- 完成处理: 按拦截器注册倒序执行afterCompletion()
代码示例:
// 注册顺序: A -> B -> C
// 执行顺序:
// preHandle: A -> B -> C
// postHandle: C -> B -> A
// afterCompletion: C -> B -> A
5.2 源码实现类
5.2.1 HandlerExecutionChain如何管理拦截器
答案要点:
- 拦截器存储: 使用List
<HandlerInterceptor>
存储所有拦截器 - 执行索引: 使用interceptorIndex记录当前执行到的拦截器位置
- 前置处理: 正序遍历执行preHandle(),任一返回false则中断
- 后置处理: 倒序遍历执行postHandle()
- 完成处理: 从interceptorIndex倒序遍历执行afterCompletion()
源码关键点:
// 前置处理
for (int i = 0; i < interceptors.length; i++) {
if (!interceptor.preHandle(request, response, this.handler)) {
return false; // 中断执行
}
this.interceptorIndex = i; // 记录位置
}
// 后置处理
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptor.postHandle(request, response, this.handler, mv);
}
// 完成处理
for (int i = this.interceptorIndex; i >= 0; i--) {
interceptor.afterCompletion(request, response, this.handler, ex);
}
5.2.2 拦截器注册机制
答案要点:
- 配置类实现: 实现WebMvcConfigurer接口
- 注册方法: 重写addInterceptors()方法
- 路径配置: 使用addPathPatterns()和excludePathPatterns()
- 顺序控制: 按注册顺序决定执行顺序
配置示例:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 先注册的拦截器先执行
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**");
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
}
}
5.3 设计模式类
5.3.1 拦截器使用了哪些设计模式
答案要点:
- 责任链模式: 多个拦截器按顺序执行,任一中断则停止
- 模板方法模式: HandlerInterceptor接口定义了执行模板
- 策略模式: 不同的拦截器实现不同的拦截策略
- 装饰器模式: 可以对拦截器进行功能增强
模式应用场景:
- 责任链: 权限验证 -> 日志记录 -> 性能监控
- 模板方法: 统一的拦截器执行流程
- 策略: 基于路径、方法、注解的拦截策略
- 装饰器: 为拦截器添加缓存、重试等功能
5.3.2 如何实现自定义拦截器链
答案要点:
- 实现HandlerInterceptor接口: 定义拦截逻辑
- 配置注册: 在WebMvcConfigurer中注册
- 路径匹配: 使用Ant风格路径匹配
- 顺序控制: 通过注册顺序控制执行顺序
实现示例:
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 自定义前置逻辑
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
// 自定义后置逻辑
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
// 自定义完成逻辑
}
}
5.4 应用场景类
5.4.1 拦截器在项目中的典型应用
答案要点:
- 权限验证: 检查用户登录状态和访问权限
- 日志记录: 记录请求日志、性能监控
- 跨域处理: 设置CORS响应头
- 限流控制: 防止接口被恶意调用
- 参数验证: 统一验证请求参数
- 响应处理: 统一处理响应格式
实际案例:
// 权限验证拦截器
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 检查用户登录状态
String token = request.getHeader("Authorization");
if (StringUtils.isEmpty(token)) {
response.setStatus(401);
return false;
}
// 验证token有效性
User user = userService.validateToken(token);
if (user == null) {
response.setStatus(401);
return false;
}
// 将用户信息存入请求属性
request.setAttribute("currentUser", user);
return true;
}
}
5.4.2 如何实现异步拦截器
答案要点:
- 实现AsyncHandlerInterceptor接口: 支持异步请求
- afterConcurrentHandlingStarted方法: 异步请求开始后执行
- 异步上下文: 使用AsyncContext处理异步请求
- 线程安全: 注意异步环境下的线程安全问题
实现示例:
public class AsyncInterceptor implements AsyncHandlerInterceptor {
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 异步请求开始后的处理逻辑
logger.info("异步请求开始处理: {}", request.getRequestURI());
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 异步请求的前置处理
return true;
}
}
5.5 性能优化类
5.5.1 拦截器性能优化策略
答案要点:
- 减少不必要的拦截器: 只注册必需的拦截器
- 路径精确匹配: 避免使用过于宽泛的路径模式
- 异步处理: 对于耗时操作使用异步处理
- 缓存机制: 缓存拦截器的计算结果
- 懒加载: 延迟初始化拦截器资源
优化示例:
@Component
public class OptimizedInterceptor implements HandlerInterceptor {
private final Cache<String, Boolean> pathCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String path = request.getRequestURI();
// 使用缓存避免重复计算
Boolean shouldIntercept = pathCache.getIfPresent(path);
if (shouldIntercept != null) {
return shouldIntercept;
}
// 计算是否需要拦截
boolean result = calculateIntercept(path);
pathCache.put(path, result);
return result;
}
private boolean calculateIntercept(String path) {
// 复杂的路径匹配逻辑
return path.startsWith("/api/") && !path.startsWith("/api/public/");
}
}
5.5.2 拦截器异常处理
答案要点:
- 统一异常处理: 在afterCompletion中处理异常
- 异常分类: 区分业务异常和系统异常
- 日志记录: 详细记录异常信息
- 用户友好: 返回用户友好的错误信息
处理示例:
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
if (ex != null) {
// 记录异常日志
logger.error("拦截器执行异常: {}", ex.getMessage(), ex);
// 根据异常类型返回不同响应
if (ex instanceof BusinessException) {
response.setStatus(400);
response.getWriter().write("{\"code\":400,\"message\":\"" + ex.getMessage() + "\"}");
} else {
response.setStatus(500);
response.getWriter().write("{\"code\":500,\"message\":\"系统内部错误\"}");
}
}
}
6. 总结
6.1 学习路径图
6.2 核心优势总结
优势 | 说明 | 重要性 |
---|---|---|
灵活性 | 可以动态添加、移除、调整拦截器 | ⭐⭐⭐⭐⭐ |
可扩展性 | 支持自定义拦截器实现 | ⭐⭐⭐⭐⭐ |
性能友好 | 相比AOP性能开销更小 | ⭐⭐⭐⭐ |
易于理解 | 执行流程清晰,易于调试 | ⭐⭐⭐⭐ |
Spring集成 | 与Spring MVC无缝集成 | ⭐⭐⭐⭐⭐ |
6.3 适用场景总结
场景 | 适用性 | 推荐程度 |
---|---|---|
权限验证 | 高 | ⭐⭐⭐⭐⭐ |
日志记录 | 高 | ⭐⭐⭐⭐⭐ |
性能监控 | 高 | ⭐⭐⭐⭐⭐ |
跨域处理 | 中 | ⭐⭐⭐⭐ |
限流控制 | 中 | ⭐⭐⭐⭐ |
参数验证 | 中 | ⭐⭐⭐ |
响应处理 | 中 | ⭐⭐⭐ |
6.4 注意事项总结
注意事项 | 说明 | 影响程度 |
---|---|---|
执行顺序 | 拦截器按注册顺序执行,需注意依赖关系 | ⭐⭐⭐⭐ |
异常处理 | 在afterCompletion中处理异常,避免影响正常流程 | ⭐⭐⭐⭐⭐ |
性能影响 | 拦截器过多会影响请求处理性能 | ⭐⭐⭐⭐ |
线程安全 | 注意ThreadLocal的使用和清理 | ⭐⭐⭐⭐ |
路径匹配 | 合理配置路径模式,避免误拦截 | ⭐⭐⭐ |
6.5 学习建议
学习阶段 | 重点内容 | 建议时间 |
---|---|---|
初级阶段 | 基础概念、简单使用 | 1-2天 |
中级阶段 | 源码分析、设计模式 | 3-5天 |
高级阶段 | 自定义实现、性能优化 | 5-7天 |
实战阶段 | 项目应用、问题解决 | 持续学习 |
6.6 发展方向
方向 | 技能要求 | 发展前景 |
---|---|---|
Spring专家 | 深入Spring生态,掌握拦截器原理 | ⭐⭐⭐⭐⭐ |
架构师 | 设计拦截器框架,制定最佳实践 | ⭐⭐⭐⭐⭐ |
性能专家 | 优化拦截器性能,解决性能瓶颈 | ⭐⭐⭐⭐ |
安全专家 | 设计安全拦截器,防护安全威胁 | ⭐⭐⭐⭐⭐ |
6.7 最终建议
- 理论与实践结合: 先理解概念,再动手实践,最后深入源码
- 循序渐进: 从简单拦截器开始,逐步增加复杂度
- 关注性能: 在实际项目中注意拦截器的性能影响
- 持续学习: 关注Spring版本更新,学习新特性
- 总结归纳: 建立自己的知识体系,形成最佳实践
通过系统学习Java拦截器,你将能够:
- 深入理解Spring MVC的执行机制
- 掌握拦截器的设计思想和实现原理
- 在实际项目中灵活运用拦截器解决各种问题
- 在面试中展现扎实的技术功底
- 为后续学习Spring生态其他组件打下坚实基础
更多推荐
所有评论(0)