使用Java11,Springt Boot WebClient
创建了一个REST WebService(Service1),它试图使用一个REST WebService(Service2),它将返回映射到我的自定义响应对象的JSON。但是因为要消费的服务(Service 2)目前没有在线,我将收到404 not found。
问题似乎是404响应以'text/html;charset=iso-8859-1‘的形式出现,并且不能映射到我的DocumentResponse对象上。
Webclient被配置为接受xml和json。
如何在不得到此异常的情况下拦截和处理这些http状态响应。
通常,我会通过请求链上的using.block()接收响应,并为使用此响应的服务1创建一个适当的响应。
例如:
Documentresponse response = invoiceDeliveryControllerApi.deliverInvoiceUsingPOST(request,"test").block(); public Mono<Documentresponse> deliverInvoiceUsingPOST(Documentrequest request, String name) throws WebClientResponseException {
Object postBody = request;
// verify the required parameter 'request' is set
if (request == null) {
throw new WebClientResponseException("Missing the required parameter 'request' when calling deliverInvoiceUsingPOST", HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, null);
}
// create path and map variables
final Map<String, Object> pathParams = new HashMap<String, Object>();
final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders headerParams = new HttpHeaders();
final MultiValueMap<String, String> cookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> formParams = new LinkedMultiValueMap<String, Object>();
queryParams.putAll(apiClient.parameterToMultiValueMap(null, "name", name));
final String[] localVarAccepts = {
"application/xml", "text/xml"
};
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"application/xml", "text/xml"
};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
ParameterizedTypeReference<Documentresponse> localVarReturnType = new ParameterizedTypeReference<Documentresponse>() {};
return apiClient.invokeAPI("/api/v1/deliverinvoice", HttpMethod.POST, pathParams, queryParams, postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType);
} public <T> Mono<T> invokeAPI(String path, HttpMethod method, Map<String, Object> pathParams, MultiValueMap<String, String> queryParams, Object body, HttpHeaders headerParams, MultiValueMap<String, String> cookieParams, MultiValueMap<String, Object> formParams, List<MediaType> accept, MediaType contentType, String[] authNames, ParameterizedTypeReference<T> returnType) throws RestClientException {
final WebClient.RequestBodySpec requestBuilder = prepareRequest(path, method, pathParams, queryParams, body, headerParams, cookieParams, formParams, accept, contentType, authNames);
return requestBuilder.retrieve().bodyToMono(returnType);
} public static WebClient buildWebClient(ObjectMapper mapper) {
ExchangeStrategies strategies = ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper, MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper, MediaType.APPLICATION_JSON));
}).build();
WebClient.Builder webClient = WebClient.builder().filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).exchangeStrategies(strategies);
return webClient.build();
}现在,我想找到一种方法来对这些html响应做出反应,并为服务1创建一个响应,该响应将告诉用户在调用服务2时出现http连接错误。
有什么建议吗?
PS:客户端代码是使用openapi代码生成器生成的,并针对日志目的进行了略微调整。
编辑:我发现,通常情况下,它就像在.block()中捕获WebClientException一样简单,并且使用状态代码,我可以生成令人满意的响应消息。
但是我发现了一个奇怪的行为,如果服务2的响应是f.e.400错误请求它以text/html的形式提供,没有字符集=iso-8859-1附加。
在这种情况下,它会导致预期的WebClientResponseException。但是对于实例404not found文本/html charset=iso-8859-1将被传递并通向UnexpectedMediaTypeException。有没有办法解释原因?
更让我困惑的是,在expected 404的情况下,我通过WebClientFilters的日志记录提供了状态307重定向(到我一开始调用的同一个url )和302,文本/html字符集=iso-8859-1也指向MediaTypeException。而具有完全相同数据的相同呼叫通过邮递员传送404。有谁知道发生了什么事吗?
发布于 2021-03-24 21:51:03
来自WebBlient#bodyToMono java文档:
Extract the body to a {@code Mono}. By default, if the response has status code 4xx or 5xx, the {@code Mono} will contain a {@link WebClientException}. This can be overridden with {@link #onStatus(Predicate, Function)}.
要根据状态代码实现错误处理:
requestBuilder
.retrieve()
.onStatus(HttpStatus::is4xxClientError, res -> Mono<? extends Throwable>)
.onStatus(HttpStatus::is5xxServerError, res -> Mono<? extends Throwable>)
.bodyToMono(responseType)
.onErrorResume(Status400Throwable.class, th -> Mono.just(fallbackResponseHere))
.onErrorResume(Status500Throwable.class, th -> Mono.just(fallbackResponseHere));如果您不希望缺省错误处理程序返回WebClientResponseException,请查看WebClient.ResponseSpec#onStatus java文档以及类似Mono#onErrorResume的内容。
发布于 2021-03-26 18:16:01
回答我自己的问题:
在预期的404状态码的情况下,客户端给我UnsupportedMediaTypeException的奇怪行为是由重定向307和302发现引起的,这是由我使用http url而不是https url引起的。
我不知道为什么只有404状态码才会这样。但在将baseURI更改为https后,我不再收到redirect或unsupportedMediaTypeExceptions,而是收到预期的WEbClientResponseExceptions。
现在我将尝试使用Serg Vasylchak的答案来处理错误,而不捕获异常。
https://stackoverflow.com/questions/66780925
复制相似问题