论SpringBoot 中 Filter 和 Interceptor

注:在 Spring Boot 项目中,Filter 和 Interceptor 都是常用于处理 HTTP 请求的机制,但它们的执行顺序有所不同。理解它们的执行顺序非常重要,特别是当你有一个用来生成 requestId 的过滤器和一个用来获取 requestId 的拦截器时。

两者的执行顺序分析

  • Filter:在 Servlet 容器级别工作,负责请求进入 Spring 框架之前的处理。过滤器是基于 Servlet 规范实现的,它在请求进入 Spring MVC 控制器之前就被执行。

  • Interceptor:在 Spring MVC 框架中工作,它是在请求进入 Spring 的控制器之前(即业务逻辑执行之前)和响应返回客户端之前执行的。拦截器是 Spring 提供的机制,适用于 Spring MVC 控制器的处理。

总结

  • Filter 会在 Interceptor 之前执行;
  • Filter 先对请求进行处理,可以修改请求对象、设置响应头或进行其他操作;
  • Interceptor 会在请求进入 Spring 控制器之前执行,通常是用于业务逻辑层的处理或某些操作,如记录日志、权限校验等。

结合Controller 的顺序图解

  1. 请求到达服务器
    → Filter 处理请求 → Interceptor 处理请求 → Controller 处理请求
  2. 响应返回客户端
    → Interceptor 处理响应 → Filter 处理响应

代码实例

假设有一个 RequestIdFilter 过滤器来生成 requestId,同时有一个 RequestIdInterceptor 拦截器来获取 requestId。
  1. RequestIdFilter 过滤器
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

public class RequestIdFilter implements Filter {

    private static final String REQUEST_ID_HEADER = "X-Request-Id";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化过滤器
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 获取请求头中的 requestId,如果没有则生成新的 requestId
        String requestId = httpRequest.getHeader(REQUEST_ID_HEADER);
        if (requestId == null || requestId.isEmpty()) {
            requestId = UUID.randomUUID().toString();  // 使用 UUID 生成唯一的 requestId
        }

        // 将 requestId 设置到请求上下文中
        httpRequest.setAttribute(REQUEST_ID_HEADER, requestId);

        // 设置到响应头中,返回给客户端
        httpResponse.setHeader(REQUEST_ID_HEADER, requestId);

        // 继续处理请求
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // 销毁过滤器
    }
}

  1. RequestIdInterceptor 拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RequestIdInterceptor implements HandlerInterceptor {

    private static final String REQUEST_ID_HEADER = "X-Request-Id";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取过滤器设置的 requestId
        String requestId = (String) request.getAttribute(REQUEST_ID_HEADER);
        if (requestId != null) {
            // 在日志或者其他地方使用 requestId
            System.out.println("RequestId in Interceptor: " + requestId);
        }
        return true;  // 继续执行后续操作
    }
}

  1. 注册 Filter:使用 FilterRegistrationBean 注册过滤器
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<RequestIdFilter> loggingFilter() {
        FilterRegistrationBean<RequestIdFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new RequestIdFilter());
        registrationBean.addUrlPatterns("/api/*");  // 只拦截 /api/* 路径
        return registrationBean;
    }
}

  1. 注册 Interceptor:使用 WebMvcConfigurer 注册拦截器
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) {
        // 注册 RequestIdInterceptor 拦截器,拦截所有请求
        registry.addInterceptor(new RequestIdInterceptor())
                .addPathPatterns("/**");
    }
}

小结
Filter 和 Interceptor 执行顺序是:Filter 先执行,Interceptor 后执行。
过滤器通常用于请求的预处理和响应的后处理,拦截器则更多用于业务逻辑层的拦截,例如验证、日志记录等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值