之前介绍了常见的三个拦截器HandlerInterceptor、okhttp3.Interceptor、feign.RequestInterceptor 的用法:

这3个拦截器都是基于 责任链模式(Chain of Responsibility),支持多个拦截器顺序执行;核心目标一致,为了解决 横切关注点(Cross-Cutting Concerns),但所属层级和拦截阶段不一样, 这里对比下三者的区别和使用场景。

1. 核心功能对比

维度

HandlerInterceptor

 (Spring MVC)

okhttp3.Interceptor 

(OkHttp)

feign.RequestInterceptor 

(OpenFeign)

层级位置服务端 Web 层客户端网络传输层客户端接口抽象层
所属框架Spring Web MVC / Spring BootOkHttp 网络库OpenFeign (声明式HTTP客户端)
框架定位服务端 Web 框架客户端网络库声明式 HTTP 客户端框架
作用对象HTTP 请求/响应的 服务端处理阶段HTTP 请求/响应的 网络传输阶段在Feign客户端构造请求的阶段
拦截阶段Controller 方法的执行前后网络请求的发送和响应接收的原始字节流阶段在Feign将方法调用转换为HTTP请求的过程中
操作对象HttpServletRequest/ResponseOkHttp的 Request/Response (原始字节流或封装对象)Feign的RequestTemplate (请求模板对象)
主要用途权限校验、日志、全局业务处理修改请求头、添加认证、重试机制、日志记录统一添加请求头、认证信息
能否修改请求体✅ (需包装请求对象HttpServletRequest)✅ (直接操作 Request 和 Response)✅ (通过模板RequestTemplate修改)
能否修改响应体✅ (需包装响应对象)✅ (直接操作)❌ (不处理响应)
请求中断能力✅ (返回 false 或直接响应)✅ (抛出异常或返回自定义 Response)❌ (仅修改请求)
典型依赖关系内置于 Spring MVC独立网络库依赖 OpenFeign


2. 区别分析

1. 设计定位差异

  • HandlerInterceptor 服务于 Spring MVC 服务端框架,拦截目标是 Controller 方法的执行,属于 Web 请求处理链的一部分:

    • preHandle():Controller 执行前(权限校验)
    • postHandle():Controller 执行后(日志记录)
    • afterCompletion():视图渲染后(资源清理)
  • okhttp3.Interceptor 作用于 OkHttp 客户端网络库,拦截的是 HTTP 网络请求/响应的原始字节流,用于在发送请求前或接收响应后修改数据:

    • 操作原始字节流(如 Gzip 压缩)
    • 可修改请求/响应头、体
    • 支持网络级重试、熔断
  • feign.RequestInterceptor 作用于 Feign 声明式HTTP客户端,在Feign将接口方法转化为HTTP请求的过程中,允许修改请求模板(RequestTemplate)。它工作在请求被发送到网络之前,属于更高层次的请求构造拦截:

    • 在 Java 接口方法转 HTTP 请求时介入
    • 只能修改请求模板(如统一添加 Authorization 头)
    • 不接触实际网络传输

2. 技术能力对比

能力HandlerInterceptorokhttp3.Interceptorfeign.RequestInterceptor
修改 URL 参数✅✅✅
修改请求头✅✅✅
修改请求体内容⚠️ (需复杂包装)✅✅
拦截响应并修改数据✅✅❌
实现自动重试机制❌✅❌
直接操作网络套接字❌✅❌
与业务逻辑深度集成✅❌⚠️ (浅层集成)

3. 代码结构差异

// Spring 的 HandlerInterceptor
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //在服务端记录请求日志 & 鉴权
        log.info("Request URL: {}", request.getRequestURL());
        if (!isValid(request.getHeader("Token"))) {
            response.setStatus(401);
            return false; // 中断请求
        }
        return true;
    }
}

// OkHttp 的 Interceptor
public class LoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        // 在OkHttp中添加统一User-Agent
        Request request = chain.request();
        Request newRequest = originalRequest.newBuilder()
                .header("User-Agent", "MyApp/1.0")
                .build();
        return chain.proceed(request); // 执行网络请求
    }
}

// Feign 的 RequestInterceptor
public class FeignAuthInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        template.header("API-Key", "xxxxxx"); // 在Feign客户端请求中添加认证头
    }
}

3.三者协作演示

场景描述:

  1. 当通过 Feign 客户端 调用 @FeignClient 接口时:

    • feign.RequestInterceptor 先添加统一的 API-Key 请求头
  2. OkHttp 底层发送请求时:

    • okhttp3.Interceptor 添加 User-Agent 并记录原始日志
    • 实现失败自动重试(如 503 状态码重试 3 次)
  3. 请求到达 Spring Boot 服务端:

    • HandlerInterceptor 校验请求头中的 Token 有效性
    • 校验失败直接返回 401 响应,不会进入 Controller

对应微服务架构中的工作流:

4. 如何选择

需求场景推荐拦截器原因
在 Spring MVC 中实现权限控制HandlerInterceptor深度集成服务端生命周期
需要修改网络层细节(如重试/压缩)okhttp3.Interceptor直接操作网络流量
为所有 Feign 请求添加统一参数feign.RequestInterceptor声明式修改接口级请求模板
需要同时修改请求和响应原始字节okhttp3.Interceptor唯一支持双向字节流操作
在请求进入 Controller 前记录业务日志HandlerInterceptor可获取到 Spring 上下文业务数据

5.相关阅读

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐