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

Spring MVC 拦截器与过滤器的区别

拦截器和过滤器都是请求处理链中的重要组件,但它们属于不同框架,作用范围和使用场景各不相同。

基本定义

组件所属框架实现接口
过滤器Servlet容器javax.servlet.Filter
拦截器Spring MVCorg.springframework.web.servlet.HandlerInterceptor

核心区别对比

对比项过滤器拦截器
所属框架Servlet容器(Tomcat等)Spring MVC
依赖Spring
作用范围所有请求(含静态资源)仅Controller请求
执行时机Servlet前后Controller前后
获取Handler信息不能
访问Spring Bean需要额外配置可直接注入
多个组件执行顺序按注册顺序preHandle顺序,其他逆序

执行流程对比

Java
HTTP请求
    ↓
Filter1.doFilter() ─→ Filter2.doFilter() ─→ Filter3.doFilter()
    ↓                                              ↓
DispatcherServlet                            请求继续传递
    ↓
Interceptor1.preHandle() → Interceptor2.preHandle()
    ↓
Controller处理
    ↓
Interceptor2.postHandle() → Interceptor1.postHandle()
    ↓
View渲染
    ↓
Interceptor2.afterCompletion() → Interceptor1.afterCompletion()
    ↓
Filter3响应处理 ← Filter2响应处理 ← Filter1响应处理
    ↓
HTTP响应

过滤器实现

Java
@Component
public class LoggingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化逻辑
    }

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

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        log.info("过滤器 - 请求开始: {} {}", req.getMethod(), req.getRequestURI());

        // 前置处理
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);

        // 继续执行后续过滤器或Servlet
        chain.doFilter(request, response);

        // 后置处理
        long duration = System.currentTimeMillis() - startTime;
        log.info("过滤器 - 请求完成: {} {}, 耗时: {}ms, 状态: {}",
            req.getMethod(), req.getRequestURI(), duration, res.getStatus());
    }

    @Override
    public void destroy() {
        // 清理逻辑
    }
}

拦截器实现

Java
@Component
public class LoggingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        log.info("拦截器 - preHandle: {} {}", request.getMethod(), request.getRequestURI());
        request.setAttribute("startTime", System.currentTimeMillis());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        log.info("拦截器 - postHandle: {}", request.getRequestURI());
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        long duration = System.currentTimeMillis()
            - (Long) request.getAttribute("startTime");
        log.info("拦截器 - afterCompletion: {} {}, 耗时: {}ms",
            request.getMethod(), request.getRequestURI(), duration);
    }
}

过滤器注册方式

方式一:@WebFilter注解

Java
@WebFilter(urlPatterns = "/*", filterName = "loggingFilter")
@Component
public class LoggingFilter implements Filter {
    // ...
}

方式二:FilterRegistrationBean

Java
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<LoggingFilter> loggingFilterRegistration() {
        FilterRegistrationBean<LoggingFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new LoggingFilter());
        registration.addUrlPatterns("/*");
        registration.setName("loggingFilter");
        registration.setOrder(1);    // 顺序控制
        return registration;
    }
}

使用场景选择

场景推荐组件原因
登录验证拦截器只需拦截Controller,可获取Handler信息
权限控制拦截器需要Spring Bean,获取Controller信息
日志记录拦截器或过滤器根据是否需要Handler信息决定
跨域处理过滤器需处理所有请求(含静态资源)
编码设置过滤器需处理所有请求
XSS防护过滤器需处理所有请求参数
静态资源处理过滤器拦截器不拦截静态资源
性能监控拦截器只关注Controller响应时间

典型应用示例

过滤器:跨域处理

Java
@Component
public class CorsFilter implements Filter {

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

        HttpServletResponse res = (HttpServletResponse) response;
        HttpServletRequest req = (HttpServletRequest) request;

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

        if ("OPTIONS".equalsIgnoreCase(req.getMethod())) {
            res.setStatus(HttpServletResponse.SC_OK);
            return;
        }

        chain.doFilter(request, response);
    }
}

拦截器:权限控制

text
@Component
public class PermissionInterceptor implements HandlerInterceptor {

    @Autowired
    private PermissionService permissionService;

    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            // 获取方法上的权限注解
            RequirePermission annotation =
                handlerMethod.getMethodAnnotation(RequirePermission.class);

            if (annotation != null) {
                User user = UserContext.getUser();
                if (!permissionService.hasPermission(user, annotation.value())) {
                    response.setStatus(403);
                    response.getWriter().write("{\"code\":403,\"message\":\"无权限\"}");
                    return false;
                }
            }
        }
        return true;
    }
}

拦截器优势

  1. 可获取Handler信息:能获取Controller类、方法、参数等
  2. 直接访问Spring Bean:可注入Service等组件
  3. 更精确的拦截范围:只拦截Controller,不拦截静态资源
  4. postHandle能力:可在Controller执行后修改响应

过滤器优势

  1. 不依赖Spring:可在Spring容器初始化前执行
  2. 拦截范围广:可拦截所有请求(含静态资源)
  3. 容器级控制:适合底层通用处理
  4. 执行时机早:在DispatcherServlet之前执行

要点总结

  • 过滤器属于Servlet容器,拦截器属于Spring MVC
  • 过滤器拦截所有请求,拦截器只拦截Controller
  • 过滤器不能获取Handler信息,拦截器可以
  • 登录验证、权限控制推荐用拦截器
  • 跨域、编码、安全防护推荐用过滤器
  • 可同时使用两者处理不同层次的逻辑

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

← 上一篇 Spring MVC 实现HandlerInterceptor接口
下一篇 → Spring MVC 拦截器实现日志记录
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

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

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