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 执行时序图
Client DispatcherServlet HandlerExecutionChain Interceptor1 Interceptor2 Handler ViewResolver HTTP请求 获取处理器执行链 前置处理阶段 preHandle() 返回true/false 中断执行 响应 alt [返回false] loop [所有拦截器] 执行处理器 执行目标方法 返回结果 后置处理阶段 postHandle() loop [所有拦截器(倒序)] 视图渲染 解析视图 完成处理阶段 afterCompletion() loop [所有拦截器(倒序)] 最终响应 Client DispatcherServlet HandlerExecutionChain Interceptor1 Interceptor2 Handler ViewResolver
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 模式结构
«interface»
HandlerInterceptor
+preHandle()
+postHandle()
+afterCompletion()
LogInterceptor
+preHandle()
+postHandle()
+afterCompletion()
AuthInterceptor
+preHandle()
+postHandle()
+afterCompletion()
HandlerExecutionChain
-interceptorList: List
+applyPreHandle()
+applyPostHandle()
+triggerAfterCompletion()
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 拦截器与过滤器的区别

答案要点:

  1. 作用范围: 拦截器只拦截Spring MVC请求,过滤器拦截所有Web请求
  2. 执行时机: 拦截器在Controller方法前后执行,过滤器在Servlet前后执行
  3. 依赖框架: 拦截器依赖Spring MVC,过滤器依赖Servlet容器
  4. 性能开销: 拦截器开销较低,过滤器开销最低
  5. 使用场景: 拦截器适合业务逻辑处理,过滤器适合通用处理

扩展问题:

  • 拦截器能拦截静态资源吗?
  • 过滤器能获取Spring容器中的Bean吗?
5.1.2 拦截器的执行顺序

答案要点:

  1. 前置处理: 按拦截器注册顺序执行preHandle()
  2. 目标方法: 执行Controller方法
  3. 后置处理: 按拦截器注册倒序执行postHandle()
  4. 完成处理: 按拦截器注册倒序执行afterCompletion()

代码示例:

// 注册顺序: A -> B -> C
// 执行顺序:
// preHandle: A -> B -> C
// postHandle: C -> B -> A  
// afterCompletion: C -> B -> A

5.2 源码实现类

5.2.1 HandlerExecutionChain如何管理拦截器

答案要点:

  1. 拦截器存储: 使用List <HandlerInterceptor>存储所有拦截器
  2. 执行索引: 使用interceptorIndex记录当前执行到的拦截器位置
  3. 前置处理: 正序遍历执行preHandle(),任一返回false则中断
  4. 后置处理: 倒序遍历执行postHandle()
  5. 完成处理: 从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 拦截器注册机制

答案要点:

  1. 配置类实现: 实现WebMvcConfigurer接口
  2. 注册方法: 重写addInterceptors()方法
  3. 路径配置: 使用addPathPatterns()和excludePathPatterns()
  4. 顺序控制: 按注册顺序决定执行顺序

配置示例:

@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 拦截器使用了哪些设计模式

答案要点:

  1. 责任链模式: 多个拦截器按顺序执行,任一中断则停止
  2. 模板方法模式: HandlerInterceptor接口定义了执行模板
  3. 策略模式: 不同的拦截器实现不同的拦截策略
  4. 装饰器模式: 可以对拦截器进行功能增强

模式应用场景:

  • 责任链: 权限验证 -> 日志记录 -> 性能监控
  • 模板方法: 统一的拦截器执行流程
  • 策略: 基于路径、方法、注解的拦截策略
  • 装饰器: 为拦截器添加缓存、重试等功能
5.3.2 如何实现自定义拦截器链

答案要点:

  1. 实现HandlerInterceptor接口: 定义拦截逻辑
  2. 配置注册: 在WebMvcConfigurer中注册
  3. 路径匹配: 使用Ant风格路径匹配
  4. 顺序控制: 通过注册顺序控制执行顺序

实现示例:

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 拦截器在项目中的典型应用

答案要点:

  1. 权限验证: 检查用户登录状态和访问权限
  2. 日志记录: 记录请求日志、性能监控
  3. 跨域处理: 设置CORS响应头
  4. 限流控制: 防止接口被恶意调用
  5. 参数验证: 统一验证请求参数
  6. 响应处理: 统一处理响应格式

实际案例:

// 权限验证拦截器
@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 如何实现异步拦截器

答案要点:

  1. 实现AsyncHandlerInterceptor接口: 支持异步请求
  2. afterConcurrentHandlingStarted方法: 异步请求开始后执行
  3. 异步上下文: 使用AsyncContext处理异步请求
  4. 线程安全: 注意异步环境下的线程安全问题

实现示例:

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 拦截器性能优化策略

答案要点:

  1. 减少不必要的拦截器: 只注册必需的拦截器
  2. 路径精确匹配: 避免使用过于宽泛的路径模式
  3. 异步处理: 对于耗时操作使用异步处理
  4. 缓存机制: 缓存拦截器的计算结果
  5. 懒加载: 延迟初始化拦截器资源

优化示例:

@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 拦截器异常处理

答案要点:

  1. 统一异常处理: 在afterCompletion中处理异常
  2. 异常分类: 区分业务异常和系统异常
  3. 日志记录: 详细记录异常信息
  4. 用户友好: 返回用户友好的错误信息

处理示例:

    @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 学习路径图

Java拦截器学习
基础概念
源码分析
设计模式
应用场景
面试准备
拦截器定义
执行流程
与过滤器区别
HandlerInterceptor接口
HandlerExecutionChain
注册机制
责任链模式
模板方法模式
策略模式
装饰器模式
权限验证
日志记录
性能监控
跨域处理
限流控制
基础概念类
源码实现类
设计模式类
应用场景类
性能优化类

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 最终建议

  1. 理论与实践结合: 先理解概念,再动手实践,最后深入源码
  2. 循序渐进: 从简单拦截器开始,逐步增加复杂度
  3. 关注性能: 在实际项目中注意拦截器的性能影响
  4. 持续学习: 关注Spring版本更新,学习新特性
  5. 总结归纳: 建立自己的知识体系,形成最佳实践

通过系统学习Java拦截器,你将能够:

  • 深入理解Spring MVC的执行机制
  • 掌握拦截器的设计思想和实现原理
  • 在实际项目中灵活运用拦截器解决各种问题
  • 在面试中展现扎实的技术功底
  • 为后续学习Spring生态其他组件打下坚实基础
Logo

惟楚有才,于斯为盛。欢迎来到长沙!!! 茶颜悦色、臭豆腐、CSDN和你一个都不能少~

更多推荐