拦截器跟过滤器的区别?拦截器需要注册吗?过滤器需要注册吗?

这是一个非常经典且重要的 Java Web 开发问题。下面从作用机制、执行时机、依赖环境、注册方式 等多个维度,清晰解释 拦截器(Interceptor)过滤器(Filter) 的区别,并回答你关于"是否需要注册"的问题。


✅ 一、核心区别总览

特性 过滤器(Filter) 拦截器(Interceptor)
所属规范 Servlet 规范(Java EE) Spring MVC / Spring Boot 框架
依赖容器 Servlet 容器(如 Tomcat) Spring IoC 容器
作用范围 所有 Web 资源(Servlet、JSP、HTML、图片等) 仅 Spring MVC 的 Controller 请求
执行时机 DispatcherServlet 之前 DispatcherServlet 之后,Controller 之前/后
能否注入 Spring Bean ❌ 不能直接注入(需手动获取) ✅ 可直接 @Autowired
执行顺序 Filter → DispatcherServlet → Interceptor → Controller

📌 关键记忆点
Filter 是"外层守门员",Interceptor 是"Spring 内部管家"


🔍 二、详细对比说明

1. 作用阶段不同

  • Filter
    工作在 Servlet 容器层面 ,请求一进来就触发,连静态资源(如 /js/app.js)也能拦截。
  • Interceptor
    工作在 Spring MVC 流程中 ,只有经过 DispatcherServlet 分发的请求(即映射到 @Controller 的请求)才会被拦截。

💡 举例:

访问 http://localhost:8080/logo.png

  • Filter 会执行 ✅
  • Interceptor 不会执行

2. 对 Spring 生态的支持

  • Filter
    不属于 Spring 管理,无法直接使用 @Service@Repository 等 Bean。
    若需使用,必须通过:

    复制代码
    WebApplicationContextUtils.getWebApplicationContext(servletContext)
        .getBean(UserService.class);
  • Interceptor
    是 Spring Bean,可直接注入:

    复制代码
    @Component
    public class AuthInterceptor implements HandlerInterceptor {
        @Autowired
        private UserService userService; // 直接注入 ✅
    }

3. 方法粒度控制

  • Filter :只能按 URL 模式匹配(如 /*, /api/*),无法精确到某个 Controller 方法
  • Interceptor :可通过 addPathPatterns()excludePathPatterns() 精细控制,甚至结合注解实现方法级拦截。

✅ 三、是否需要注册?

过滤器(Filter)------ 必须注册!

否则 Servlet 容器不知道它的存在。

注册方式(任选其一):
  1. 注解方式(Servlet 3.0+)

    复制代码
    @WebFilter(urlPatterns = "/*")
    public class LogFilter implements Filter { ... }

    ⚠️ 需在主启动类加 @ServletComponentScan

  2. 配置类方式(推荐,尤其 Spring Boot)

    复制代码
    @Configuration
    public class FilterConfig {
        @Bean
        public FilterRegistrationBean<LogFilter> logFilter() {
            FilterRegistrationBean<LogFilter> bean = new FilterRegistrationBean<>();
            bean.setFilter(new LogFilter());
            bean.addUrlPatterns("/*");
            return bean;
        }
    }

拦截器(Interceptor)------ 必须注册!

Spring 不会自动发现你实现的 HandlerInterceptor

注册方式(唯一标准方式):
复制代码
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/login");
    }
}

❌ 如果不注册,即使加了 @Component也不会生效

推荐】结构化写法:定义与注册分离(适合大型项目)

组件定义注册逻辑 完全解耦,代码更清晰、易测试、易维护。

1. 定义 Filter

java

编辑

复制代码
// src/main/java/com/example/filter/LogFilter.java
@Component
public class LogFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        long start = System.currentTimeMillis();
        chain.doFilter(request, response);
        System.out.println("请求耗时: " + (System.currentTimeMillis() - start) + "ms");
    }
}

2. 定义 Interceptor

java

编辑

复制代码
// src/main/java/com/example/interceptor/AuthInterceptor.java
@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 鉴权逻辑
        return true;
    }
}

3. 统一注册配置类

复制代码
// src/main/java/com/example/config/WebConfig.java
@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final LogFilter logFilter;
    private final AuthInterceptor authInterceptor;

    public WebConfig(LogFilter logFilter, AuthInterceptor authInterceptor) {
        this.logFilter = logFilter;
        this.authInterceptor = authInterceptor;
    }

    // 注册 Filter
    @Bean
    public FilterRegistrationBean<LogFilter> logFilterRegistration() {
        FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(logFilter);
        registration.addUrlPatterns("/*");
        registration.setOrder(1);
        return registration;
    }

    // 注册 Interceptor
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/public/**");
    }
}

优点

  • 职责分离:Filter/Interceptor 只关注逻辑,配置类只关注注册
  • 支持单元测试(可单独测试 AuthInterceptor
  • 易于扩展(新增拦截器只需加一行注册)

🧪 四、执行顺序图示

复制代码
客户端请求
     ↓
[ Filter 1 ] → doFilter()
     ↓
[ Filter 2 ] → doFilter()
     ↓
DispatcherServlet(Spring MVC 入口)
     ↓
[ Interceptor.preHandle() ]
     ↓
Controller 方法执行
     ↓
[ Interceptor.postHandle() ]
     ↓
视图渲染
     ↓
[ Interceptor.afterCompletion() ]
     ↓
[ Filter 2 ] → chain.doFilter() 之后的代码
     ↓
[ Filter 1 ] → chain.doFilter() 之后的代码
     ↓
响应返回客户端

🔥 注意:Filter 的 doFilter()chain.doFilter() 之前 是请求预处理,之后是响应后处理。


✅ 五、如何选择?

场景 推荐
设置全局字符编码(request.setCharacterEncoding("UTF-8") ✅ Filter(必须在 DispatcherServlet 前)
拦截静态资源(如防盗链) ✅ Filter
登录校验、权限控制、日志记录(针对 API) ✅ Interceptor(可注入 Service)
全局 CORS、安全头(如 XSS 防护) ✅ Filter
需要修改 ModelAndView 或捕获 Controller 异常 ✅ Interceptor

✅ 总结

问题 答案
拦截器需要注册吗? ✅ 需要!通过 WebMvcConfigurer.addInterceptors()
过滤器需要注册吗? ✅ 需要!通过 @WebFilter + @ServletComponentScanFilterRegistrationBean
谁先执行? Filter 先于 Interceptor
能互相替代吗? ❌ 不能!作用层级不同,应根据场景选择

💡 最佳实践

  • 底层通用处理(编码、安全、静态资源)→ 用 Filter
  • 业务逻辑相关(鉴权、日志、参数处理)→ 用 Interceptor

理解这一点,你就掌握了 Spring Web 请求处理的核心流程!

相关推荐
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-相关技术栈(分布式场景下事件机制)
java·spring boot·分布式·ddd
独自破碎E2 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
冻感糕人~2 小时前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
啦啦啦_99992 小时前
Redis实例-2
java
alice--小文子2 小时前
cursor-mcp工具使用
java·服务器·前端
进阶小白猿2 小时前
Java技术八股学习Day33
java·开发语言·学习
程序员敲代码吗2 小时前
如何通过命令行启动COMSOL的参数化、批处理和集群扫描
java·c#·bash
MX_93592 小时前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
市场部需要一个软件开发岗位2 小时前
JAVA开发常见安全问题:纵向越权
java·数据库·安全