【问题标题】:How to set multiple headers at once in Spring WebClient?如何在 Spring WebClient 中一次设置多个标头?
【发布时间】:2020-03-26 17:54:59
【问题描述】:

我试图为我的休息客户端设置标题,但每次我都必须写

webclient.get().uri("blah-blah")
         .header("key1", "value1")
         .header("key2", "value2")...

如何使用 headers() 方法同时设置所有标题?

【问题讨论】:

标签: spring-boot java-8 resttemplate rest-client spring-webclient


【解决方案1】:

如果这些标头在每个请求的基础上发生变化,您可以使用:

webClient.get().uri("/resource").headers(httpHeaders -> {
    httpHeaders.setX("");
    httpHeaders.setY("");
});

这并没有节省多少打字;因此对于不会从一个请求更改为另一个请求的标头,您可以在构建客户端时将它们设置为默认标头:

WebClient webClient = WebClient.builder().defaultHeader("...", "...").build();
WebClient webClient = WebClient.builder().defaultHeaders(httpHeaders -> {
    httpHeaders.setX("");
    httpHeaders.setY("");
}).build();

【讨论】:

  • 无法理解 httpHeaders -> {} 部分..你能用一个适当的例子解释一下吗?
  • 这是一个恰当的例子,实际上它是一个非常好的例子。如果您不理解它,您可能需要研究 lambda 和函数式接口。如果刚开始,不要指望它是一件快速学习的事情,第一次很难掌握它:)
  • @PlickPlick,如果 WebClient 的请求返回 401 UNAUTHORIZED,您是否知道我们可以将其用作网络拦截器?所以我们可以调用一个逻辑来刷新令牌,然后调用最后一次调用?
  • 检查 onSuccess onError 和 onErrorResume。 baeldung.com/spring-webflux-errors
  • 但我实际上并不确定您所说的网络拦截器是什么意思。另外我最近开始使用网络客户端,所以可能不是合适的人问?
【解决方案2】:

消费者是正确的,尽管很难想象,尤其是。因为您可以在处理完标头后继续在 webclient 构造中使用其他 fluent-composition 方法调用。

....假设您有一个 HttpHeaders(或 MutliValue 映射)将您的标头保存在范围内。这是一个示例,使用来自 spring 云网关的交换对象:

final HttpHeaders headersFromExchangeRequest = exchange.getRequest().headers();
webclient.get().uri("blah-blah")
    .headers( httpHeadersOnWebClientBeingBuilt -> { 
         httpHeadersOnWebClientBeingBuilt.addAll( headersFromExchangeRequest );
    }
)...

addAll 可以采用多值映射。如果这是有道理的。如果没有,请让您的 IDE 成为您的向导。

为了让消费者更清楚,我们把上面的内容改写如下:

private Consumer<HttpHeaders> getHttpHeadersFromExchange(ServerWebExchange exchange) {
    return httpHeaders -> {
        httpHeaders.addAll(exchange.getRequest().getHeaders());
    };
}
.
.
.
webclient.get().uri("blah-blah")
    .headers(getHttpHeadersFromExchange(exchange))
    ...

【讨论】:

    【解决方案3】:

    我发现这个问题又出现了,这次我是直接使用 WebClient 编写 groovy。同样,我试图驱动的示例是使用 Consumer 作为 headers 方法调用的参数。

    在groovy中,额外的问题是groovy闭包语法和java lambda语法都使用-&gt;

    groovy 版本在这里:

    def mvmap = new LinkedMultiValueMap<>(headersAsMap)
    def consumer = { it -> it.addAll(mvmap) } as Consumer<HttpHeaders>
    
    WebClient client = WebClient.create(baseUrlAsString)
    def resultAsMono = client.post()
            .uri(uriAsString).accept(MediaType.APPLICATION_JSON)
            .headers(consumer)
            .body(Mono.just(payload), HashMap.class)
            .retrieve()
            .toEntity(HashMap.class)
    

    java版本在这里:

    LinkedMultiValueMap mvmap = new LinkedMultiValueMap<>(headersAsMap);
    Consumer<HttpHeaders> consumer = it -> it.addAll(mvmap);
    
    WebClient client = WebClient.create(baseUrlAsString);
    Mono<ResponseEntity<HashMap>> resultAsMono = client.post()
            .uri(uriAsString).accept(MediaType.APPLICATION_JSON)
            .headers(consumer)
            .body(Mono.just(payload), HashMap.class)
            .retrieve()
            .toEntity(HashMap.class);
    

    【讨论】:

      猜你喜欢
      • 2011-09-27
      • 2012-01-12
      • 1970-01-01
      • 2020-06-15
      • 2018-02-24
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      相关资源
      最近更新 更多