在 Netflix Feign 中,请求拦截器(Request Interceptor)是一个非常有用的组件。它允许你在每个 Feign 请求发送之前对请求进行自定义操作,比如添加请求头、修改请求参数、记录请求日志等。
请求拦截器在实现诸如认证、授权、统一日志记录等功能时非常方便。如下图:
要创建一个请求拦截器,需要实现 feign.RequestInterceptor 接口。这个接口只有一个方法apply(RequestTemplate template),在这个方法中可以对 RequestTemplate 对象进行操作,该对象包含了即将发送的请求的所有信息,如请求 URL、请求头、请求体等。
以下是一个简单的示例,用于在每个请求中添加一个“X-Forwarded-For”请求头:
// 自定义请求拦截器 static class ForwardedForInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { template.header("X-Forwarded-For", "origin.host.com"); } }
上面示例中,ForwardedForInterceptor 类实现了 RequestInterceptor 接口。在 apply() 方法中,通过template.header() 方法添加了一个名为“X-Forwarded-For”,值为“origin.host.com”的请求头到请求模板中。
当使用 Feign.builder() 创建 Feign 客户端时,可以通过 requestInterceptor() 方法添加请求拦截器。例如:
// 创建Feign客户端实例的静态方法 static InterceptorFeign create() { return Feign.builder() .encoder(new Encoder.Default()) .decoder(new Decoder.Default()) .contract(new Contract.Default()) // 添加请求拦截器 .requestInterceptor(new ForwardedForInterceptor()) .target(InterceptorFeign.class, "http://localhost:8090"); }
下面是请求拦截器示例的完整代码:
(1)服务端代码,定义了一个简单的查询服务“/simple/interceptor”,如下:
@GetMapping("/interceptor") public String interceptor(@RequestHeader("X-Forwarded-For") String xForwardedFor, @RequestParam("msg") String msg) { return "xForwardedFor=" + xForwardedFor + "<br/>msg=" + msg; }
(2)定义 Feign 客户端代码,如下:
package com.hxstrive.demo_netflix_feign.feign; import feign.*; import feign.codec.Decoder; import feign.codec.Encoder; /** * Feign 请求拦截器 * @author HuangXin */ public interface InterceptorFeign { // Feign 请求接口方法 @RequestLine("GET /simple/interceptor?msg={msg}") String interceptor(@Param("msg") String message); // 自定义请求拦截器 static class ForwardedForInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { template.header("X-Forwarded-For", "origin.host.com"); } } // 创建Feign客户端实例的静态方法 static InterceptorFeign create() { return Feign.builder() .encoder(new Encoder.Default()) .decoder(new Decoder.Default()) .contract(new Contract.Default()) // 添加请求拦截器 .requestInterceptor(new ForwardedForInterceptor()) .target(InterceptorFeign.class, "http://localhost:8090"); } }
(3)调用 Feign 客户端,如下:
@GetMapping("/") public String index() { return InterceptorFeign.create().interceptor("hello"); }
运行结果如下图:
从上面的输出信息可知,通过请求拦截器成功添加了“X-Forwarded-For”请求头信息。