使用 WebClient 将带有标头的请求发送到第三方 api
Posted
技术标签:
【中文标题】使用 WebClient 将带有标头的请求发送到第三方 api【英文标题】:Sending request with headers to third parts api with WebClient 【发布时间】:2019-07-14 01:28:24 【问题描述】:我真的很喜欢 RestTemplate
的解决方案,但很快它就会随着未来的春季版本而贬值。我正在尝试使用 WebClient
向第三方 api 发送一些文本@
String text = URLEncoder.encode(text,"UTF-8");
WebClient webClient = WebClient.builder()
.baseUrl(BASE_URL)
.defaultHeader("Key","af999-e99-4456-b556-4ef9947383d")
.defaultHeader("src", srcLang)
.defaultHeader("tgt", tgtLang)
.defaultHeader("text", text)
.build();
然后在这里发帖:
Mono<String> response = webClient.post().uri("/google/rtv/text")
.retrieve()
.bodyToMono(String.class);
尝试根据旧响应进行解析:
private String parseJson( Mono<String> response)
ObjectMapper mapper = new ObjectMapper();
JsonNode root = null;
JsonNode review = null;
//TODO: create an object and map it here. We need to save the original review too.
try
root = mapper.readTree(response.toString());
review = root.path("message");
catch (IOException e)
e.printStackTrace();
return review.asText();
稍后我需要解析响应,但现在我收到一条错误消息:
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'MonoFlatMap': was expecting ('true', 'false' or 'null')
at [Source: (String)"MonoFlatMap"; line: 1, column: 23]
及以后:
java.lang.NullPointerException: null
我想要完成的事情就像我对 RestTemplate
所做的那样。
像这样:
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString(URL)
.queryParam("src", src)
.queryParam("tgt", tgt)
.queryParam("text", text);
ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, request, String.class);
然后全局设置我的订阅标头。
private ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException
request.getHeaders().add("Key","af999-e99-4456-b556-4ef9947383d");
ClientHttpResponse response = execution.execute(request, body);
return response;
@Bean
public RestTemplate restTemplate()
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Collections.singletonList(this::intercept));
return restTemplate;
建议?
【问题讨论】:
从外观上看,Jackson 似乎正在尝试序列化返回的Mono
。您能否提供更多关于 Mono
的使用位置以及使用方式的背景信息?
那么Mono<String>
在哪里使用以及如何使用?我这样问是因为问题的根源可能在那里,而不是在您的代码 sn-p 中。
【参考方案1】:
问题发生在这里:
root = mapper.readTree(response.toString());
这段代码 sn-p 试图将 Mono<String>
序列化为字符串,而 Mono
是一种最终可以提供 String
值的反应类型。
你可以调用response.block()
并得到String
的结果,但这将是一个阻塞调用,如果在响应式执行的中间,Reactor 会禁止它。这样做是有充分理由的,因为这会阻塞您的 Web 应用程序正在使用的少数线程之一,并可能导致它停止服务其他请求。
您可以改为:
Mono<String> review = response.map(r -> parseJson(r);
然后重复使用该新值。
请注意,WebClient
本身支持 JSON 反序列化,您可以像这样反序列化整个有效负载:
Mono<Review> review = webClient.post().uri("/google/rtv/text")
.retrieve()
.bodyToMono(Review.class);
【讨论】:
以上是关于使用 WebClient 将带有标头的请求发送到第三方 api的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 WebClient 的 spring-security-oauth2 自定义 OAuth2 令牌请求的授权标头?
如何使用 WebClient 反应式 Web 客户端发送带有 zip 正文的 POST 请求
WebClient 未向 Windows Phone 中的 Web 服务发送授权标头
如何记录 spring-webflux WebClient 请求 + 响应详细信息(正文、标头、elasped_time)?