提取类型 [class java.lang.Object] 和内容类型 [application/octet-stream] 的响应时出错;

问题描述 投票:0回答:1

这是我的方法,

我调用的API实际上返回了什么?
这将返回二进制响应,响应内容为“application/octet-stream”。
调用此方法的方法来自控制器,控制器将返回 ResponseEntity 到前端。

 @Override
public <V> ResponseEntity<V> getBillingDocPDFFromGCP(String url, HttpMethod method, HttpServletRequest request, String accessToken, Class<V> responseType, Map<String, String> params, BaseStoreModel baseStore, String appDomain) {
    if (StringUtils.isEmpty(url)) {
        throw new ConfigurationException(HttpStatus.NOT_ACCEPTABLE + " : Missing API Uri property in configuration");
    }
    LOG.info("getGCPBillingDocPDF API URL...{}", url);
    MultiValueMap<String, String> headers = getServiceHeadersForGCPPDF(baseStore, accessToken);
    final HttpEntity<Object> requestEntity = new HttpEntity<>(headers);
    final RestTemplate restTemplate = new RestTemplate();
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
    messageConverters.add(converter);
    restTemplate.setMessageConverters(messageConverters);

    try {
        return (ResponseEntity<V>) restTemplate.exchange(url, method, requestEntity, responseType);


    } catch (final HttpClientErrorException httpClientException) {
        LOG.error(UNAUTHORIZED_ERROR + " : " + httpClientException.getMessage(), httpClientException);
        throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED, httpClientException.getMessage());
    } catch (final RestClientException restClientException) {
        LOG.error(REST_CLIENT_ERROR, restClientException);
        throw new RestClientException(REST_CLIENT_REPORTED_ERROR + " : " + restClientException.getMessage(), restClientException);
    }
}

  public MultiValueMap<String, String> getServiceHeadersForGCPPDF(final BaseStoreModel baseStore, final String aceToken) {
    final HttpHeaders headers = new HttpHeaders();
    final String siteId = getCurrentSiteId(baseStore);
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.parseMediaType("application/octet-stream"));
    headers.add("X-API-Key", value);
    return headers;
}

以下是我遇到的错误,请告知如何解决此问题

 Rest Client Error org.springframework.web.client.RestClientException: Error while xtracting response for type [class java.lang.Object] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('%' (code 37)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is 

请指教

更新方法,返回类型配置为 ResponseEntity:

根据迈克尔的建议,我将返回类型更改为 ResponseEntity 但仍然遇到相同的错误

 @Override
public <V> ResponseEntity<byte[]> getBillingDocPDFFromGCP(String url, HttpMethod method, HttpServletRequest request, String accessToken, Class<V> responseType, Map<String, String> params, BaseStoreModel baseStore, String appDomain) {
    if (StringUtils.isEmpty(url)) {
        throw new ConfigurationException(HttpStatus.NOT_ACCEPTABLE + " : Missing API Uri property in configuration");
    }
    LOG.info("getGCPBillingDocPDF API URL...{}", url);
    MultiValueMap<String, String> headers = getServiceHeadersForGCPPDF(baseStore, accessToken);
    final HttpEntity<Object> requestEntity = new HttpEntity<>(headers);
    final RestTemplate restTemplate = new RestTemplate();
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
    messageConverters.add(converter);
    restTemplate.setMessageConverters(messageConverters);

    try {
        return  restTemplate.exchange(url, method, requestEntity, byte[].class);

    } catch (final HttpClientErrorException httpClientException) {
        LOG.error(UNAUTHORIZED_ERROR + " : " + httpClientException.getMessage(), httpClientException);
        throw new HttpClientErrorException(HttpStatus.UNAUTHORIZED, httpClientException.getMessage());
    } catch (final RestClientException restClientException) {
        LOG.error(REST_CLIENT_ERROR, restClientException);
        throw new RestClientException(REST_CLIENT_REPORTED_ERROR + " : " + restClientException.getMessage(), restClientException);
    }
}

我仍然遇到的错误是

Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class [B] and content type [application/octet-stream]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('%' (code 37)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('%' (code 37)): expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
java resttemplate
1个回答
0
投票

根据您的错误和预期返回类型

[application/octet-stream]
,您希望收到二进制信息。但是你的方法返回
ResponseEntity<V>
顺便说一句,你没有显示你如何调用你的方法以及你的类型 V 实际上是什么。接收您的响应的转换器需要一个有效的 JSON,并且在错误中,它抱怨返回的内容不是有效的 JSON。那么,您调用的 API 实际上返回了什么?它是标头值
[application/octet-stream]
所建议的二进制信息还是文本 JSON 信息?如果它是 JSON,那么您的响应类型是错误的。如果它是二进制信息,那么您的类型 V 应该是字节数组或
ByteBuffer


我还建议您使用比 RestTemplate 简单得多的 HTTP 客户端。特别是如果您的返回类型实际上是二进制信息。在这种情况下,我建议的 Http 客户端实际上具有返回
ByteBuffer
的方法,您可以自己处理它,而不必担心告诉您的 Http 客户端应该转换什么以及如何转换。这个 Http 客户端附带了由我编写和维护的 MgntUtils 开源 java 库。此外,如果您将请求发送到同一 URL,此 Http 客户端还允许多个请求,而无需重置每个请求的 URL 和标头。 您的代码可能如下所示:

public class MyHttpClient {
  private HttpClient client = new HttpClient();

  public MyHttpClient() {
     client.setConnectionUrl(myUrlStr);
     client.setRequestHeader(headerName1Str, headerValue1Str)
     .setRequestHeader(headerName2Str, headerValue2Str)
     .setRequestHeader(headerName3Str, headerValue3Str);     
  }

  public ByteArray getBillingDocPDFFromGCP(...) {
    ByteBuffer result = null;
    try {
      //Here you can change connection URL if it is different than the pre-set one 
      // and add or modify headers
      HttpClient.HttpMethod httpMethod = HttpClient.HttpMethod.valueOf(httpMethodStr);
      ResponseHolder<ByteBuffer> response = sendHttpRequestForBinaryResponse(httpMethod);
      result = response.getResponseContent();
   } catch(HttpClientCommunicationException e) {
      ResponseHolder errorResponse  = e.getResponseHolder();
      logger.error(errorResponse.getResponseCode() + " " + errorResponse.getResponseMessage());
  }
  return result;
}

这里是 HttpClient 类的 JavaDoc 。 MgntUtils 库可以作为 maven 工件 或从 Github 获取(包括源代码和 Javadoc)

© www.soinside.com 2019 - 2024. All rights reserved.