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

拦截器与过滤器扩展机制

拦截器(Interceptor)和过滤器(Filter)是Web请求处理的两个重要扩展点,执行时机和作用范围不同。

拦截器与过滤器对比

特性拦截器(Interceptor)过滤器(Filter)
所属SpringMVCServlet容器
执行时机DispatcherServlet内DispatcherServlet外
拦截范围Controller请求所有请求(含静态资源)
获取Bean可访问Spring容器无法访问Spring容器
异常处理可被HandlerExceptionResolver处理需自行处理

执行顺序图

Java
请求 → Filter1.doFilter前置
     → Filter2.doFilter前置
     → DispatcherServlet
         → Interceptor1.preHandle
         → Interceptor2.preHandle
         → Handler执行
         → Interceptor2.postHandle
         → Interceptor1.postHandle
         → 视图渲染
         → Interceptor2.afterCompletion
         → Interceptor1.afterCompletion
     → Filter2.doFilter后置
     → Filter1.doFilter后置
     → 响应

拦截器实现

HandlerInterceptor接口

Java
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) {
        return true;
    }

    default void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) {
    }

    default void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            Exception ex) {
    }
}

自定义拦截器

Java
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) {
        String token = request.getHeader("Authorization");
        if (token == null || !validateToken(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json");
            response.getWriter().write("{\"error\":\"未授权\"}");
            return false;
        }

        // 设置用户信息到请求属性
        User user = getUserFromToken(token);
        request.setAttribute("currentUser", user);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        // 清理资源
        request.removeAttribute("currentUser");
    }
}

注册拦截器

Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/public/**")
                .order(1);

        registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**")
                .order(2);

        registry.addInterceptor(new CacheInterceptor())
                .addPathPatterns("/api/data/**")
                .order(3);
    }
}

AsyncHandlerInterceptor

Java
// 异步请求拦截器扩展
public interface AsyncHandlerInterceptor extends HandlerInterceptor {
    default void afterConcurrentHandlingStarted(HttpServletRequest request,
            HttpServletResponse response, Object handler) {
        // 异步处理开始时调用
    }
}

过滤器实现

Filter接口

Java
public interface Filter {
    void init(FilterConfig filterConfig);
    void doFilter(ServletRequest request, ServletResponse response,
                  FilterChain chain);
    void destroy();
}

自定义过滤器

Java
@Component
@Order(1)
public class RequestLoggingFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        long startTime = System.currentTimeMillis();

        // 前置处理
        log.info("请求开始: {} {}", httpRequest.getMethod(), httpRequest.getRequestURI());

        try {
            chain.doFilter(request, response);
        } finally {
            // 后置处理
            long duration = System.currentTimeMillis() - startTime;
            log.info("请求结束: {} {} 耗时{}ms",
                httpRequest.getMethod(), httpRequest.getRequestURI(), duration);
        }
    }
}

注册过滤器

Java
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<RequestLoggingFilter> loggingFilter() {
        FilterRegistrationBean<RequestLoggingFilter> registration =
            new FilterRegistrationBean<>();
        registration.setFilter(new RequestLoggingFilter());
        registration.addUrlPatterns("/*");
        registration.setName("requestLoggingFilter");
        registration.setOrder(1);
        return registration;
    }

    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        FilterRegistrationBean<CorsFilter> registration =
            new FilterRegistrationBean<>();
        registration.setFilter(new CorsFilter());
        registration.addUrlPatterns("/*");
        registration.setName("corsFilter");
        registration.setOrder(0); // CORS优先级最高
        return registration;
    }
}

DelegatingFilterProxy

Java
// 将Servlet过滤器代理到Spring Bean
@Configuration
public class SecurityConfig {
    @Bean
    public FilterRegistrationBean<DelegatingFilterProxy> securityFilter() {
        FilterRegistrationBean<DelegatingFilterProxy> registration =
            new FilterRegistrationBean<>();
        registration.setFilter(new DelegatingFilterProxy("springSecurityFilterChain"));
        registration.addUrlPatterns("/*");
        registration.setName("springSecurityFilterChain");
        return registration;
    }
}

OncePerRequestFilter

Java
// 确保每个请求只执行一次
@Component
public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Max-Age", "3600");

        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpStatus.OK.value());
            return;
        }

        filterChain.doFilter(request, response);
    }
}

拦截器链执行源码

Java
// HandlerExecutionChain
public class HandlerExecutionChain {
    private int interceptorIndex = -1;

    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)) {
                triggerAfterCompletion(request, response, null);
                return false;
            }
            this.interceptorIndex = i;
        }
        return true;
    }

    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);
        }
    }

    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
// ApplicationFilterChain
public final class ApplicationFilterChain implements FilterChain {
    private int pos = 0;
    private int n = 0;
    private Filter[] filters;

    public void doFilter(ServletRequest request, ServletResponse response) {
        if (pos < n) {
            Filter filter = filters[pos++];
            filter.doFilter(request, response, this);
        } else {
            // 所有过滤器执行完毕,调用Servlet
            servlet.service(request, response);
        }
    }
}

异步请求处理

Java
@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());
    }
}

// Controller异步处理
@GetMapping("/async")
public Callable<String> asyncProcess() {
    return () -> {
        Thread.sleep(1000);
        return "result";
    };
}

拦截器获取Spring Bean

text
@Component
public class ServiceInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService; // 可注入Spring Bean

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) {
        User user = userService.getCurrentUser();
        request.setAttribute("user", user);
        return true;
    }
}

拦截器可注入Spring Bean,过滤器需要通过DelegatingFilterProxy代理或ServletContext获取。

要点总结

  1. 过滤器在Servlet容器级别,拦截器在SpringMVC容器级别
  2. 过滤器可拦截所有请求,拦截器只拦截Controller请求
  3. 拦截器可访问Spring容器Bean,过滤器无法直接访问
  4. 拦截器preHandle返回false终止链条
  5. OncePerRequestFilter确保异步请求只执行一次

jwdev/articles/SPRINGMVC/专家/容器级WEB组件扩展/容器级WEB组件扩展/拦截器与过滤器扩展机制.md

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

← 上一篇 拦截器Interceptor
下一篇 → 数据绑定与类型转换
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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