过滤器和拦截器的区别详解

过滤器和拦截器的区别详解

过滤器(Filter)和拦截器(Interceptor) 是 Web 开发中常用的工具,它们可以在请求处理流程中拦截请求或响应,用于完成某些通用功能或业务逻辑控制。尽管它们有很多相似之处,但本质上是两个完全不同的概念。以下是两者的详细区别及使用场景。


一、基本概念

1. 过滤器(Filter)

  • 定义:过滤器是基于 Servlet 规范的,运行在 Servlet 容器中,作用于请求和响应的整个生命周期。
  • 实现:实现 Java EE 的 javax.servlet.Filter 接口,必须在 Web 应用的部署描述文件(如 web.xml)中配置,或者通过注解配置。
  • 功能:
    • 请求预处理(例如请求参数校验、敏感词过滤)。
    • 响应后处理(例如统一格式化响应数据、压缩响应内容)。
    • 主要用于处理通用的、横切的功能。

2. 拦截器(Interceptor)

  • 定义:拦截器是基于框架(如 Spring)的组件,运行在应用层,作用于业务方法的调用前后。
  • 实现:实现 HandlerInterceptor 接口,并在 Spring 配置中声明。
  • 功能:
    • 拦截业务层方法调用(如权限校验、日志记录)。
    • 更接近业务逻辑,可以操作 Spring 上下文中的 Bean 和其他资源。

二、核心区别

特性过滤器(Filter)拦截器(Interceptor)
来源属于 Java EE Servlet 规范的一部分。属于 Spring 框架的一部分。
触发时机在请求进入 Servlet 之前和响应离开 Servlet 之后执行。在控制器(Controller)方法调用的前后执行。
作用范围针对所有资源(静态资源、动态资源),甚至包括 JSP 和 HTML。仅针对 Spring MVC 的控制器方法(如 @RequestMapping)。
实现方式实现 javax.servlet.Filter 接口。实现 HandlerInterceptor 接口。
依赖容器依赖于 Servlet 容器(如 Tomcat)。依赖于 Spring 框架。
执行顺序比拦截器先执行(更靠近底层)。比过滤器后执行(更靠近业务逻辑)。
配置方式配置在 web.xml 文件中或使用 @WebFilter 注解。配置在 Spring 的配置类中,或使用 @ComponentWebMvcConfigurer
应用场景通用功能(如跨域、编码设置、数据压缩等)。业务逻辑相关(如权限验证、登录校验、日志记录等)。

三、执行流程对比

请求从客户端到服务器的执行顺序为:

  1. 过滤器(Filter):处理所有请求。
  2. Servlet:核心业务逻辑处理。
  3. 拦截器(Interceptor):控制器方法调用前后拦截请求。

请求的处理流程通常为:
客户端请求 → 容器 → 过滤器 → Servlet → 拦截器 → 控制器(Controller)方法 → 响应

这种触发顺序使得过滤器更适合处理底层的通用逻辑,而拦截器更贴近业务逻辑。

在这里插入图片描述


四、具体实现

1. 过滤器的实现

基于函数回调机制,通过调用 FilterChain.doFilter() 来控制请求的继续执行。

使用 javax.servlet.Filter 接口开发过滤器,需要实现以下三个方法:
示例代码如下:

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")
public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
        // 这里可以初始化一些还没被加载的配置等
        System.out.println("过滤器初始化:init() 方法执行。");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("过滤器执行前逻辑:请求处理开始。");
        chain.doFilter(request, response); // 放行请求,交给下一个过滤器或 Servlet。
        System.out.println("过滤器执行后逻辑:响应处理结束。");
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁:destroy() 方法执行。");
    }
}
常用场景:
  • 日志记录:记录每个请求的 IP、URL 等信息。
  • 安全过滤:屏蔽不合法的请求。
  • 设置编码:统一请求和响应的字符集编码。
  • 数据压缩:对返回的数据进行 gzip 压缩。

2. 拦截器的实现

基于动态代理实现,通过 HandlerInterceptor 接口定义拦截逻辑。拦截器通常需要注册到 Spring 配置中,执行流程包括:

2.1. preHandle 方法
  • 作用:请求方法执行前调用,用于处理请求前的逻辑。通常用于权限验证、日志记录、输入验证等。
  • 返回值:必须返回 truefalsetrue 表示请求继续往下处理(进入下一个拦截器或目标方法),false 表示请求被拦截,后续的拦截器和目标方法不会被执行。

常见场景

  • 权限检查:检查用户是否已登录、是否有权限访问某个资源。
  • 日志记录:记录请求的详细信息,比如请求参数、请求时间等。
2. 2. postHandle 方法
  • 作用:请求处理后、视图渲染前调用。通常用于对目标方法返回的模型数据进行修改或增强,或者记录请求处理的时间等。
  • 返回值:没有返回值,ModelAndView 对象可以在该方法中被修改。

常见场景

  • 在响应返回之前,对视图数据进行修改。例如,向模型中添加额外的属性。
  • 记录请求处理的时间,做一些后续的处理,日志记录等。
2.3. afterCompletion 方法
  • 作用:请求处理完成后、视图渲染之后调用。通常用于资源的清理工作,比如释放数据库连接、记录请求处理的完成时间等。
  • 返回值:没有返回值,可以用来处理异常的情况或做一些日志记录工作。

常见场景

  • 资源清理:例如关闭数据库连接、文件流等。
  • 异常处理:可以用于记录异常信息或发送异常报告。
  • 性能监控:记录请求的总处理时间,进行性能分析。
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class TestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.out.println("拦截器 preHandle:请求处理前执行。");
    
        // 检查用户是否已登录
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login"); // 如果未登录,重定向到登录页面
            return false; // 拦截请求,不继续执行
        }

        return true; // 请求继续处理
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        System.out.println("拦截器 postHandle:请求处理后,但未渲染视图时执行。");
        // 可以修改 ModelAndView,比如添加公共的属性到模型
        if (modelAndView != null) {
            modelAndView.addObject("footer", "Footer content");
 	    }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("afterCompletion:请求完全处理后,视图渲染后");
    
        // 记录请求处理的时间
        long startTime = (long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        System.out.println("请求处理时间:" + (endTime - startTime) + "ms");

        // 如果有异常,可以记录或做进一步处理
        if (ex != null) {
            System.out.println("发生了异常:" + ex.getMessage());
        }
    }
}

配置拦截器

将拦截器加入到 Spring 配置中:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor())
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/login", "/static/**"); // 排除特定路径
    }
}

五、应用场景总结

过滤器适合场景

  • 跨域处理(CORS)。
  • URL 访问限制。
  • 字符集设置。
  • 日志记录。
  • 数据压缩。

拦截器适合场景

  • 用户身份验证。
  • 权限控制。
  • 请求统计。
  • 业务逻辑预处理或后置操作。
  • 系统日志记录(业务级别)。

六、总结

  • 过滤器 面向底层,关注请求和响应的整体生命周期,适合处理通用功能。
  • 拦截器 面向业务层,关注控制器方法的调用,适合处理业务逻辑相关功能。
  • 两者各有侧重点,开发时需根据具体需求选择合适的工具来实现功能。

博客主页: 总是学不会.

过滤器拦截器都是在Web开发中用来对请求进行处理的工具,它们都可以实现对请求进行拦截、修改、处理等操作,但是它们之间有一些区别过滤器是在Servlet容器中进行处理的,可以对所有的请求进行拦截处理。过滤器是基于函数回调的,需要在web.xml中配置过滤器的url-pattern,当请求的URL匹配该url-pattern时,过滤器就会被调用。过滤器可以实现对请求的预处理后处理,如编码转换、防止XSS攻击、权限验证等。 而拦截器则是在Spring框架中进行处理的,主要是针对Controller中方法的调用进行拦截处理。拦截器是基于AOP(面向切面编程)思想实现的,可以实现类似于过滤器的功能,同时还能够更灵活地控制请求的处理。拦截器可以对请求进行前置处理、后置处理、异常处理等。 总结一下,过滤器拦截器都是用来对请求进行处理的工具,但是它们之间的区别如下: 1. 运行环境不同:过滤器在Servlet容器中进行处理,而拦截器Spring容器中进行处理; 2. 处理对象不同:过滤器可以对所有的请求进行拦截处理,而拦截器主要针对Controller中方法的调用进行拦截处理; 3. 实现方式不同:过滤器是基于函数回调实现的,而拦截器是基于AOP思想实现的。 它们的作用包括但不限于: 1. 过滤非法请求; 2. 统一处理日志记录; 3. 统一处理异常信息; 4. 处理权限验证等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值