@Headers 注解在 Netflix Feign 中用于定义请求头(HTTP Headers)信息。它允许你在 Feign 客户端接口方法上指定一系列固定的请求头,这些请求头会在每次调用该方法发送请求时自动添加到 HTTP 请求中。这对于需要传递认证信息、内容类型说明或者其他固定的请求头信息的场景非常有用。
(1)如果将 @Headers 注解放在接口上,则接口下面所有的方法将会共享该 @Headers,如下:
@Headers("Content-Type: application/xml") interface SoapApi { // ... @RequestLine("GET /simple/get1") String get1(); @RequestLine("GET /simple/get2") String get2(); // ... }
上述示例中,get1 和 get2 发起的请求上均会自动添加“Content-Type: application/xml”请求头。
(2)在方法上添加 @Headers 注解,则仅会在该方法发起的请求中添加请求头。下面将在请求中添加“Cache-Control”请求头。如下:
@RequestLine("GET /") @Headers("Cache-Control: max-age=640000") String index();
如果传递多个请求头,示例如下:
@RequestLine("POST /") @Headers({ "X-Foo: Bar", "X-Ping: {token}" }) void post(@Param("token") String token);
注意:上述示例中,{token} 变量将被解析为 token 的实际值。
如果你想在请求头部中直接使用花括号("{}"),需要对其进行 URL 编码。
如果请求头中具有相同名称的请求头,请求头不会相互覆盖,所有请求头都将包含在请求中。
Feign 与 JAXRS 的关系,以下两种形式是相同的:
Feign:
@RequestLine("POST /") @Headers({ "X-Ping: {token}" }) void post(@Named("token") String token);
JAX-RS:
@POST @Path("/") void post(@HeaderParam("X-Ping") String token);
假设你有一个服务需要进行纯文本数据交互并且需要传递认证信息。可以像下面这么做:
(1)服务代码:
@GetMapping("/header1") public String header1(@RequestHeader("Custom-Header") String customHeader, @RequestHeader("Authorization") String token, @RequestHeader("Content-Type") String contentType) { return "Custom-Header=" + customHeader + "<br/>Authorization=" + token + "<br/>Content-Type=" + contentType; }
(2)Feign 客户端接口定义:
@Headers("Custom-Header: SimpleFeign.java") public interface SimpleFeign { //... @RequestLine("GET /simple/header1") @Headers({ "Authorization: Bearer {token}", "Content-Type: text/plain" }) String header1(@Param("token") String token); //... }
(3)调用 Feign 客户端:
@GetMapping("/") public String index() { return SimpleFeign.create().header1("hello world"); }
输出结果如下:
上面示例中,@Headers 注解定义了两个请求头。一个是 Content-Type 请求头,指定了请求的数据格式为纯文本。另一个是 Authorization 请求头,用于传递认证令牌(这里假设是基于 Bearer 认证的方式),服务端可以根据这个令牌来验证请求的合法性。
注意:还在类上面添加了“Custom-Header”请求头。
下面是 Headers 源码:
package feign; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Headers { // 定义 HTTP 请求头 String[] value(); }
源码中,value 是属性名,它的返回值类型是 String 数组。这意味着当我们在使用 @Headers 注解时,可以通过给 value 属性赋值来定义一系列的 HTTP 请求头。