1. 拦截器与过滤器的本质区别
很多Java开发者对拦截器(Interceptor)和过滤器(Filter)的区别停留在表面认知,这在实际开发中容易导致技术选型错误。让我们从底层架构开始,彻底理解这两者的差异。
1.1 架构层级差异
过滤器是Servlet规范定义的组件,它的工作层级在Servlet容器(如Tomcat)中。当HTTP请求到达服务器时,最先接触的就是过滤器链。这意味着:
- 过滤器能拦截所有进入容器的请求,包括静态资源(如CSS/JS文件)
- 过滤器执行时,Spring容器可能还未完全初始化
- 过滤器处理的是最原始的ServletRequest/ServletResponse对象
拦截器则是Spring MVC框架的组成部分,它的工作层级在DispatcherServlet内部。关键特性包括:
- 只能拦截经过DispatcherServlet的请求(通常是Controller请求)
- 天然集成Spring容器,可以直接使用依赖注入
- 处理的是经过封装的HttpServletRequest/HttpServletResponse
重要提示:在Spring Boot应用中,虽然可以通过@Component方式让过滤器使用Spring Bean,但此时过滤器初始化顺序可能早于某些Bean的初始化,容易引发NPE问题。
1.2 执行时机对比
一个HTTP请求在Spring MVC应用中的完整生命周期如下:
- 容器接收到HTTP请求
- 执行过滤器链(Filter Chain)
- 进入DispatcherServlet
- 执行拦截器preHandle方法
- 调用目标Controller方法
- 执行拦截器postHandle方法
- 视图渲染(如有)
- 执行拦截器afterCompletion方法
- 返回过滤器链继续执行
- 响应返回客户端
这个流程中,过滤器的doFilter方法像是一个"夹心层" - 前半段在Controller执行前,后半段在视图渲染后。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 过滤器深度解析
2.1 过滤器接口详解
过滤器的核心接口仅包含三个方法:
java复制public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {}
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
default void destroy() {}
}
实际开发中最常用的是doFilter方法,它包含了请求处理的核心逻辑。一个典型的日志过滤器实现如下:
java复制@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestLogFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(RequestLogFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
long startTime = System.currentTimeMillis();
// 请求前处理
log.info("Request started: {} {}", req.getMethod(), req.getRequestURI());
