在 Feign 客户端 + Spring Cloud (Brixton RC2) 中使用带有动态值的 @Headers

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37066331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:05:00  来源:igfitidea点击:

Using @Headers with dynamic values in Feign client + Spring Cloud (Brixton RC2)

springspring-cloudspring-cloud-netflix

提问by Hasnain

Is it possible to set dynamic values to a header ?

是否可以为标题设置动态值?

@FeignClient(name="Simple-Gateway")
interface GatewayClient {
    @Headers("X-Auth-Token: {token}")
    @RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
        String getSessionId(@Param("token") String token);
    }

Registering an implementation of RequestInterceptor adds the header but there is no way of setting the header value dynamically

注册 RequestInterceptor 的实现会添加标头,但无法动态设置标头值

@Bean
    public RequestInterceptor requestInterceptor() {

        return new RequestInterceptor() {

            @Override
            public void apply(RequestTemplate template) {

                template.header("X-Auth-Token", "some_token");
            }
        };
    } 

I found the following issue on github and one of the commenters (lpborges) was trying to do something similar using headers in @RequestMappingannotation.

我在 github 上发现了以下问题,其中一位评论者 ( lpborges) 试图在@RequestMapping注释中使用标头做类似的事情。

https://github.com/spring-cloud/spring-cloud-netflix/issues/288

https://github.com/spring-cloud/spring-cloud-netflix/issues/288

Kind Regards

亲切的问候

回答by Hasnain

The solution is to use @RequestHeader annotation instead of feign specific annotations

解决办法是使用@RequestHeader注解而不是feign特定注解

@FeignClient(name="Simple-Gateway")
interface GatewayClient {    
    @RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
    String getSessionId(@RequestHeader("X-Auth-Token") String token);
}

回答by Carlos Alberto Schneider

The @RequestHeader did not work for me. What did work was:

@RequestHeader 对我不起作用。有效的是:

@Headers("X-Auth-Token: {access_token}")
@RequestLine("GET /orders/{id}")
Order get(@Param("id") String id, @Param("access_token") String accessToken);

回答by vijay

@HeaderMap,@Header and @Param didn't worked for me, below is the solution to use @RequestHeader when there are multiple header parameters to pass using FeignClient

@HeaderMap、@Header 和 @Param 对我不起作用,以下是使用 FeignClient 传递多个标头参数时使用 @RequestHeader 的解决方案

@PostMapping("/api/channelUpdate")
EmployeeDTO updateRecord(
      @RequestHeader Map<String, String> headerMap,
      @RequestBody RequestDTO request);

code to call the proxy is as below:

调用代理的代码如下:

Map<String, String> headers = new HashMap<>();
headers.put("channelID", "NET");
headers.put("msgUID", "1234567889");
ResponseDTO response = proxy.updateRecord(headers,requestDTO.getTxnRequest());

回答by Oscar Raig Colon

I have this example, and I use @HeaderParam instead @RequestHeader :

我有这个例子,我用 @HeaderParam 代替 @RequestHeader :

import rx.Single;

import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;


@Consumes(MediaType.APPLICATION_JSON)
public interface  FeignRepository {

  @POST
  @Path("/Vehicles")
  Single<CarAddResponse> add(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, VehicleDto vehicleDto);

}

回答by Muhammad Usman

I use @HeaderMapas it seems very handy if you are working with Open feign. Using this way you can pass header keys and values dynamically.

@HeaderMap如果您正在使用Open feign ,我会使用它似乎非常方便。使用这种方式,您可以动态传递标头键和值。

@Headers({"Content-Type: application/json"})
public interface NotificationClient {

    @RequestLine("POST")
    String notify(URI uri, @HeaderMap Map<String, Object> headers, NotificationBody body);
}

Now create feign REST client to call the service end point, create your header properties map and pass it in method parameter.

现在创建 feign REST 客户端来调用服务端点,创建您的标头属性映射并将其传递到方法参数中。

NotificationClient notificationClient = Feign.builder()
    .encoder(new HymansonEncoder())
    .decoder(customDecoder())
    .target(Target.EmptyTarget.create(NotificationClient.class));

Map<String, Object> headers = new HashMap<>();
headers.put("x-api-key", "x-api-value");

ResponseEntity<String> response = notificationClient.notify(new URI("https://stackoverflow.com/example"), headers, new NotificationBody());

回答by sambuca

https://github.com/spring-cloud/spring-cloud-netflix/issues/760https://github.com/OpenFeign/feign/#basics

https://github.com/spring-cloud/spring-cloud-netflix/issues/760 https://github.com/OpenFeign/feign/#basics

17.3 Creating Feign Clients Manually
http://cloud.spring.io/spring-cloud-static/Dalston.SR4/single/spring-cloud.html#_creating_feign_clients_manually

pojo:

pojo:

public class User...

service:

服务:

@RestController
public class HelloController ...
    public User getUser(@RequestParam("name") String name) {
        User user = new User();
        user.setName(name + "[result]");
        System.out.println("name: " + name);
        return user;
    }
    ...

client:

客户:

public interface HelloClient {
    @RequestLine("POST /getUser?name={name}")
    User getUser(@Param("name") String name);
}

use:

用:

import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.Client;
public class Demo {
    private HelloClient helloClient;
    @Autowired
    public Demo(Decoder decoder, Encoder encoder, Client client) {
        this.userAnotherService = Feign.builder().client(client)
                .encoder(encoder)
                .decoder(decoder)
                // for spring security
                .requestInterceptor(new BasicAuthRequestInterceptor("username", "password"))
                .target(UserAnotherService.class, "http://your-service-name");
    }
...
...method...
// output --> hello spring cloud![result]
System.out.println(helloClient.getUser("hello spring cloud!").getName());
...