Spring Boot 中请求到底先进入过滤器还是拦截器?

Spring Boot 中请求到底先进入过滤器还是拦截器?

编程文章jaq1232025-07-28 16:56:236A+A-

在 Spring Boot 开发的日常中,你是否遇到过这样的情况:在过滤器和拦截器里精心编写了日志打印代码,可运行后输出顺序却让人摸不着头脑,不禁疑惑,请求到底是先进入过滤器,还是先进入拦截器呢?相信不少在互联网大厂从事后端开发的小伙伴,都被这个问题困扰过。

过滤器与拦截器:功能相似却各有不同

在 Spring Boot 项目开发的 “工具箱” 中,过滤器(Filter)和拦截器(Interceptor)是两个非常重要的 “工具”,它们在请求处理过程中都起着关键作用 。但由于功能上有一定相似性,很多开发者容易混淆二者。

过滤器是 Servlet 规范的一部分,依赖于 Servlet 容器,它就像是一个 “全能门卫”,可以对几乎所有的请求进行过滤处理,比如我们常见的字符编码设置、请求参数校验等;而拦截器则是 Spring MVC 框架中的概念,基于 Java 反射机制,它更像是 Spring MVC 框架专属的 “安检员”,主要针对 Spring MVC 管理的请求进行拦截,常用于权限验证、记录请求耗时等操作。二者的工作原理和作用范围的差异,也就导致了它们在请求处理流程中执行顺序的不同。

请求处理顺序:过滤器在前,拦截器在后

其实,在 Spring Boot 这个 “请求处理工厂” 里,请求是先进入过滤器,再进入拦截器的。具体来说,当一个请求进入 Spring Boot 应用时,首先会经过 Servlet 容器中的过滤器链,过滤器可以对请求进行预处理,例如修改请求头、判断请求是否合法等操作,就像在进入工厂大门前,先经过一轮全面检查。当过滤器链执行完毕,请求才会进入到 Spring MVC 框架中,这时候拦截器才开始发挥作用,拦截器会在控制器方法执行前后进行一系列操作,比如权限检查、日志记录等,就像是进入特定车间前的二次安检。

代码示例验证执行顺序

为了让大家更清晰地理解,我们来看一个简单的代码示例。首先创建一个过滤器:

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

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("进入拦截器postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("进入拦截器afterCompletion");
    }
}
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入过滤器");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("离开过滤器");
    }

    @Override
    public void destroy() {
        // 销毁操作
    }
}

再创建一个拦截器:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("进入拦截器postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("进入拦截器afterCompletion");
    }
}

然后在配置类中注册拦截器:

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 WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/*");
    }
}

当我们发起一个请求时,控制台的输出顺序会是:“进入过滤器” -> “进入拦截器 preHandle” -> 控制器方法执行 -> “进入拦截器 postHandle” -> “进入拦截器 afterCompletion” -> “离开过滤器”,这就像一份清晰的 “请求处理流程说明书”,展示了请求先经过过滤器,再经过拦截器的流程。

所以,下次再遇到关于过滤器和拦截器执行顺序的问题,你就可以自信满满地解答啦!如果你在实际开发中还有其他关于 Spring Boot 的疑问,欢迎在评论区留言分享,大家一起探讨学习。也别忘了点赞、收藏这篇文章,方便随时回顾,让我们一起在后端开发的道路上不断进步!

点击这里复制本文地址 以上内容由jaq123整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

苍茫编程网 © All Rights Reserved.  蜀ICP备2024111239号-21