news 2026/4/27 23:42:12

FeignRequestInterceptor 原理详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FeignRequestInterceptor 原理详解

FeignRequestInterceptor是 OpenFeign 的请求拦截器机制,其工作原理如下:

1. 核心设计模式

责任链模式:Feign 通过拦截器链在请求发送前和接收后执行自定义逻辑。

// 拦截器接口定义 public interface RequestInterceptor { void apply(RequestTemplate template); }

2. 请求处理流程

Controller ↓ Feign Client ↓ RequestInterceptor.apply() ← 在这里修改请求 ↓ Encoder.encode() ← 序列化请求体 ↓ Client.execute() ← 发送HTTP请求 ↓ Decoder.decode() ← 反序列化响应 ↓ ResponseInterceptor ← 响应拦截器(如果存在) ↓ 返回结果

3. 拦截器工作原理

3.1 注册机制
@Configuration public class FeignConfig { // Spring会自动发现并注册所有RequestInterceptor Bean @Bean public RequestInterceptor myInterceptor() { return template -> { // 拦截逻辑 }; } }
3.2 拦截时机
// Feign内部的执行流程 public class SynchronousMethodHandler { public Object invoke(Object[] argv) { // 1. 构建请求模板 RequestTemplate template = buildTemplateFromArgs.create(argv); // 2. 应用所有拦截器 for (RequestInterceptor interceptor : requestInterceptors) { interceptor.apply(template); } // 3. 发送请求 return client.execute(template, options); } }

4. RequestTemplate 结构

public class RequestTemplate { private String method; // HTTP方法 private String url; // 请求URL private Map<String, String> headers; // 请求头 private byte[] body; // 请求体 private Map<String, String> queries; // 查询参数 // 修改header的方法 public header(String name, String... values) {} public query(String name, String... values) {} }

5. 多拦截器执行顺序

@Component @Order(1) public class AuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 1. 添加认证header template.header("Authorization", "Bearer token"); } } @Component @Order(2) public class LoggingInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 2. 添加日志header template.header("X-Request-Id", UUID.randomUUID().toString()); } } // 执行顺序:AuthInterceptor → LoggingInterceptor

6. 实际应用场景

场景1:传递上游请求头
@Component public class PassThroughInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 从当前线程获取请求上下文 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { HttpServletRequest request = attributes.getRequest(); // 传递认证信息 String authHeader = request.getHeader("Authorization"); if (authHeader != null) { template.header("Authorization", authHeader); } // 传递追踪ID String traceId = request.getHeader("X-Trace-Id"); if (traceId != null) { template.header("X-Trace-Id", traceId); } } } }
场景2:添加统一header
@Component public class CommonHeaderInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 服务标识 template.header("X-Service-Name", "a-service"); // 调用时间戳 template.header("X-Request-Time", Instant.now().toString()); // 版本号 template.header("X-API-Version", "v1.0"); } }
场景3:请求签名
@Component public class SignInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 1. 获取请求参数 String method = template.method(); String url = template.url(); String body = new String(template.body()); // 2. 计算签名 String sign = calculateSign(method, url, body); // 3. 添加签名header template.header("X-Signature", sign); } }

7. 与 Spring 上下文集成

7.1 获取 Spring Bean
@Component public class TokenInterceptor implements RequestInterceptor { @Autowired private TokenService tokenService; // 可以注入其他Bean @Override public void apply(RequestTemplate template) { String token = tokenService.getToken(); template.header("Authorization", "Bearer " + token); } }
7.2 条件性拦截
@Component public class ConditionalInterceptor implements RequestInterceptor, ApplicationContextAware { private ApplicationContext context; @Override public void setApplicationContext(ApplicationContext context) { this.context = context; } @Override public void apply(RequestTemplate template) { // 根据环境决定是否添加header Environment env = context.getEnvironment(); String profile = env.getActiveProfiles()[0]; if ("prod".equals(profile)) { template.header("X-Env", "production"); } } }

8. 调试和日志

@Component @Slf4j public class LoggingInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 记录请求信息 log.info("Feign Request: {} {}", template.method(), template.url()); log.info("Headers: {}", template.headers()); // 添加请求ID以便追踪 String requestId = UUID.randomUUID().toString(); template.header("X-Request-ID", requestId); MDC.put("requestId", requestId); // 设置到日志上下文 } }

9. 错误处理和重试

@Component public class RetryInterceptor implements RequestInterceptor { private ThreadLocal<Integer> retryCount = new ThreadLocal<>(); @Override public void apply(RequestTemplate template) { Integer count = retryCount.get(); if (count == null) { count = 0; } // 标记重试次数 template.header("X-Retry-Count", String.valueOf(count)); retryCount.set(count + 1); } }

10. 性能考虑

@Component public class PerformanceInterceptor implements RequestInterceptor { private ThreadLocal<Long> startTime = new ThreadLocal<>(); @Override public void apply(RequestTemplate template) { startTime.set(System.currentTimeMillis()); } // 响应拦截器(Feign 6+ 支持) public void handleResponse(Response response) { Long start = startTime.get(); if (start != null) { long duration = System.currentTimeMillis() - start; log.info("Feign请求耗时: {}ms", duration); } } }

工作原理总结

  1. 自动发现:Spring 会自动发现并注册所有RequestInterceptor类型的 Bean

  2. 顺序执行:拦截器按照@Order注解顺序执行,无注解则无序

  3. 线程安全:拦截器是单例的,但每个请求都有自己的RequestTemplate

  4. 可修改性:每个拦截器都可以修改请求的所有部分(URL、header、body 等)

  5. 生命周期:拦截器在每次 Feign 调用时都会执行

  6. 上下文隔离:通过ThreadLocalRequestContextHolder实现请求级别的上下文隔离

使用建议

  1. 保持简单:拦截器逻辑应该简单,避免复杂业务逻辑

  2. 异常处理:拦截器中抛出异常会导致整个请求失败

  3. 性能注意:不要在拦截器中执行耗时操作

  4. 可测试性:设计可测试的拦截器,避免依赖静态方法

  5. 幂等性:确保拦截器的逻辑是幂等的,不会因多次执行产生副作用

通过这种拦截器机制,OpenFeign 实现了灵活的可扩展性,可以在不修改业务代码的情况下统一处理认证、日志、监控等横切关注点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/27 23:40:38

AI 写论文哪个软件最好?虎贲等考 AI 凭 “学术闭环” 登顶首选

毕业季的论文攻坚战&#xff0c;“AI 写论文哪个软件最好” 成了学子圈的终极拷问。有的软件文献引用虚拟无据&#xff0c;有的 AI 痕迹明显被导师打回&#xff0c;有的功能碎片化需反复切换工具 —— 真正靠谱的 AI 写作软件&#xff0c;不仅要 “写得快”&#xff0c;更要 “…

作者头像 李华
网站建设 2026/4/26 9:05:57

网络安全技术核心框架:一文理清从原理到实践的知识体系

1.网络安全的概念 网络安全的定义 ISO对网络安全的定义&#xff1a;网络系统的软件、硬件以及系统中存储和传输的数据受到保护&#xff0c;不因偶然的或者恶意的原因而遭到破坏、更改、泄露&#xff0c;网络系统连续可靠正常地运行&#xff0c;网络服务不中断。 网络安全的属…

作者头像 李华
网站建设 2026/4/25 16:54:12

Aurix TC387 Can配置记录

一、MCMCAN介绍fSYN is supplied from fMCANH and fASYN is supplied from fMCAN from CCU. fSYN is used as the clock source for Register and RAM interface,fASYN is used to generate the nominal and fast CAN FD baudrates. It is recommended to use fASYN as 80, 40,…

作者头像 李华
网站建设 2026/4/19 20:45:23

原理:XinServer 是如何实现开箱即用的后端服务的?

原理&#xff1a;XinServer 是如何实现开箱即用的后端服务的&#xff1f; 不知道你有没有过这种经历&#xff1a;产品经理或者客户拿着一个原型图过来&#xff0c;说“咱们这个App/小程序/管理后台&#xff0c;下个月能上线吗&#xff1f;”你一看&#xff0c;好家伙&#xff0…

作者头像 李华
网站建设 2026/4/27 17:56:56

前端:VUE2

vue官网&#xff1a;https://cn.vuejs.org/服务端渲染 服务器浏览器服务器浏览器#mermaid-svg-7LrgJWuVc08jOSgy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@key…

作者头像 李华
网站建设 2026/4/23 17:12:47

2027年80%平台将出局?数藏行业合规化与技术革命双轨突围指南

引言&#xff1a;当数字藏品陷入“信任危机”2025年&#xff0c;数字藏品市场迎来关键转折点。一方面&#xff0c;全球市场规模突破千亿美元&#xff0c;中国用户规模超2亿&#xff1b;另一方面&#xff0c;行业乱象频发&#xff1a;某头部平台因二级市场炒作被立案调查&#x…

作者头像 李华