首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bodyType=不支持文本内容类型‘org.springframework.web.reactive.function.UnsupportedMediaTypeException: /html;charset=iso-8859-1’

bodyType=不支持文本内容类型‘org.springframework.web.reactive.function.UnsupportedMediaTypeException: /html;charset=iso-8859-1’
EN

Stack Overflow用户
提问于 2021-03-24 20:20:49
回答 2查看 435关注 0票数 0

使用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创建一个适当的响应。

例如:

代码语言:javascript
复制
Documentresponse response = invoiceDeliveryControllerApi.deliverInvoiceUsingPOST(request,"test").block(); 
代码语言:javascript
复制
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);
    }
代码语言:javascript
复制
 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);
    }
代码语言:javascript
复制
   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。有谁知道发生了什么事吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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)}.

要根据状态代码实现错误处理:

代码语言:javascript
复制
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的内容。

票数 0
EN

Stack Overflow用户

发布于 2021-03-26 18:16:01

回答我自己的问题:

在预期的404状态码的情况下,客户端给我UnsupportedMediaTypeException的奇怪行为是由重定向307和302发现引起的,这是由我使用http url而不是https url引起的。

我不知道为什么只有404状态码才会这样。但在将baseURI更改为https后,我不再收到redirect或unsupportedMediaTypeExceptions,而是收到预期的WEbClientResponseExceptions。

现在我将尝试使用Serg Vasylchak的答案来处理错误,而不捕获异常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66780925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档