全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

拦截器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) {
    }
}

三个方法详解

方法执行时机返回值作用
preHandleHandler执行前boolean认证、授权、预处理
postHandleHandler执行后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逆序执行。

要点总结

  1. HandlerInterceptor定义三个拦截点:preHandle、postHandle、afterCompletion
  2. preHandle返回false终止链条,触发已执行拦截器的afterCompletion
  3. postHandle逆序执行,可修改ModelAndView
  4. afterCompletion保证执行,用于资源清理
  5. AsyncHandlerInterceptor扩展异步请求处理

jwdev/articles/SPRINGMVC/专家/容器级WEB组件扩展/容器级WEB组件扩展/拦截器Interceptor.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 异常处理HandlerExceptionResolver
下一篇 → 拦截器与过滤器扩展机制
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库