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