拦截器和过滤器的区别

拦截器(Interceptor)和过滤器(Filter)都是用于在请求处理过程中进行预处理和后处理的组件,但它们在实现原理、使用场景和功能特点上有显著区别。

拦截器和过滤器的区别

1. 基本概念

过滤器(Filter)

  • 基于函数回调的Java Web组件
  • 实现了Servlet规范,是Servlet技术的一部分
  • 依赖于Servlet容器(如Tomcat)
  • 可以对所有进入容器的请求进行处理

拦截器(Interceptor)

  • 基于Java反射机制的组件
  • 是Spring框架的一部分(Spring MVC中)
  • 不依赖Servlet容器,依赖Spring容器
  • 主要用于拦截Controller层的请求

2. 执行顺序

scss 复制代码
客户端请求
    ↓
Filter1 (前置处理)
    ↓
Filter2 (前置处理)
    ↓
DispatcherServlet
    ↓
Interceptor1 (preHandle)
    ↓
Interceptor2 (preHandle)
    ↓
Controller方法执行
    ↓
Interceptor2 (postHandle)
    ↓
Interceptor1 (postHandle)
    ↓
视图渲染
    ↓
Interceptor2 (afterCompletion)
    ↓
Interceptor1 (afterCompletion)
    ↓
Filter2 (后置处理)
    ↓
Filter1 (后置处理)
    ↓
返回客户端响应

3. 功能对比

特性 过滤器(Filter) 拦截器(Interceptor)
实现原理 基于函数回调 基于Java反射机制
依赖容器 Servlet容器 Spring容器
触发时机 请求进入容器时 请求进入Controller前
拦截范围 所有请求 DispatcherServlet处理的请求
配置方式 web.xml或注解 Spring配置或注解
访问Servlet API 可以直接访问 通过参数访问

4. 代码示例

过滤器示例

java 复制代码
@Component
@WebFilter(urlPatterns = "/*", filterName = "authFilter")
public class AuthFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        // 前置处理
        String token = httpRequest.getHeader("Authorization");
        System.out.println("Filter前置处理: " + httpRequest.getRequestURI());
        
        // 继续执行过滤器链
        chain.doFilter(request, response);
        
        // 后置处理
        System.out.println("Filter后置处理: " + httpRequest.getRequestURI());
    }
}

拦截器示例

java 复制代码
@Component
public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        // 请求处理前执行
        System.out.println("Interceptor前置处理: " + request.getRequestURI());
        return true; // 返回true继续执行,false中断执行
    }
    
    @Override
    public void postHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler, 
                          ModelAndView modelAndView) throws Exception {
        // 请求处理后、视图渲染前执行
        System.out.println("Interceptor后置处理: " + request.getRequestURI());
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                              HttpServletResponse response, 
                              Object handler, 
                              Exception ex) throws Exception {
        // 整个请求完成后执行
        System.out.println("Interceptor完成处理: " + request.getRequestURI());
    }
}

5. 注册方式

过滤器注册

java 复制代码
// 方式1:使用@WebFilter注解
@WebFilter(urlPatterns = "/api/*")
public class MyFilter implements Filter { }

// 方式2:在配置类中注册
@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean<MyFilter> loggingFilter() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter());
        registrationBean.addUrlPatterns("/api/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

拦截器注册

java 复制代码
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    @Autowired
    private AuthInterceptor authInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/login");
    }
}

6. 使用场景

过滤器适用场景

  • 字符编码设置
  • 跨域处理
  • 请求日志记录
  • 权限检查(粗粒度)
  • 请求/响应内容压缩

拦截器适用场景

  • 登录验证
  • 权限检查(细粒度)
  • 性能监控
  • 事务管理
  • 异常处理

7. 性能和开销

  • 过滤器:相对轻量,直接在Servlet容器层面处理,开销较小
  • 拦截器:需要Spring容器管理,会有一些反射调用开销,但功能更强大

两者可以根据具体需求选择使用,也可以结合使用以发挥各自优势。

相关推荐
赵文宇1 分钟前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端
程序员爱钓鱼20 分钟前
Node.js 编程实战:即时聊天应用 —— WebSocket 实现实时通信
前端·后端·node.js
Libby博仙1 小时前
Spring Boot 条件化注解深度解析
java·spring boot·后端
源代码•宸1 小时前
Golang原理剖析(Map 源码梳理)
经验分享·后端·算法·leetcode·golang·map
小周在成长1 小时前
动态SQL与MyBatis动态SQL最佳实践
后端
瓦尔登湖懒羊羊2 小时前
TCP的自我介绍
后端
小周在成长2 小时前
MyBatis 动态SQL学习
后端
子非鱼9212 小时前
SpringBoot快速上手
java·spring boot·后端
我爱娃哈哈2 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端
JavaGuide2 小时前
Maven 4 终于快来了,新特性很香!
后端·maven