问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

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

创作时间:
作者:
@小白创作中心

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

引用
CSDN
1.
https://blog.csdn.net/m0_70871140/article/details/144638166

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

过滤器(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 表示请求被拦截,后续的拦截器和目标方法不会被执行。

常见场景

  • 权限检查:检查用户是否已登录、是否有权限访问某个资源。
  • 日志记录:记录请求的详细信息,比如请求参数、请求时间等。
    1. 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 访问限制。
  • 字符集设置。
  • 日志记录。
  • 数据压缩。

拦截器适合场景

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

六、总结

  • 过滤器面向底层,关注请求和响应的整体生命周期,适合处理通用功能。
  • 拦截器面向业务层,关注控制器方法的调用,适合处理业务逻辑相关功能。
  • 两者各有侧重点,开发时需根据具体需求选择合适的工具来实现功能。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号