弹簧休息模板中的mime类型无效?

时间:2018-02-15 03:06:29

标签: java spring resttemplate spring-rest jackson2

我只是想做一个简单的REST请求,如下面的

String url = "some url";
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.AUTHORIZATION, "some authorization");
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
Body body = new Body();
body.setRemarks("test");
org.springframework.http.HttpEntity request = new org.springframework.http.HttpEntity(body, headers);
try {
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, request, String.class);
    System.out.println("Status Response: "+ response.getStatusCode() +". Body: "+ response.getBody());
} catch (HttpClientErrorException | HttpServerErrorException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

问题是我每次在Java中执行此操作时结果都是不可预测的,我通常会一直收到此错误。

org.springframework.http.InvalidMediaTypeException: Invalid mime type "text/plain, application/json, application/json, application/*+json, application/*+json, */*; charset=UTF-8": Invalid token character ',' in token "plain, application/json, application/json, application/*+json, application/*+json, */*"
at org.springframework.http.MediaType.parseMediaType(MediaType.java:452)
at org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:745)
at org.springframework.web.client.DefaultResponseErrorHandler.getCharset(DefaultResponseErrorHandler.java:115)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)

然而,当我通过邮递员尝试相同的请求时,它可以工作。我错过了一些非常简单的事情,我不知道是什么。

我查看了Postman和标题的回复,它们似乎保持良好状态Content-Type →application/json; charset=UTF-8,响应也很好。

我也无法确定请求或响应是针对哪个Rest模板出现问题的哪个部分。

1 个答案:

答案 0 :(得分:2)

在我的案例中,简短的回答是在提出请求之前添加这些额外的标题。

headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.name());

答案很长:感谢Nikolay Shevchenko's建议使用调试器来挖掘出当服务器上出现错误时RestTemplate试图从响应中收集所有标题和正文以创建合理的异常消息。在尝试从响应中创建该消息时,它获得了mime类型

text/plain, application/json, application/json, application/*+json, application/*+json, */*; charset=UTF-8

Postman针对同一请求显示的整个文本长度而不是application/json; charset=UTF-8。因此,在我尝试parse over上面提供的mime类型的旧版Spring rest模板版本的情况下,它会失败,产生此消息。

org.springframework.http.InvalidMediaTypeException: Invalid mime type "text/plain, application/json, application/json, application/*+json, application/*+json, */*; charset=UTF-8": Invalid token character ',' in token "plain, application/json, application/json, application/*+json, application/*+json, */*"

因此,不是获得服务器错误,而是更精细的mime类型异常从更深的堆栈中冒出来,对于您正在搜索的内容没有任何意义。

根据this post RestTemplate M. Deinum StringHttpMessageConverter使用restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); 的最终结果如何,尽管我已将Jackson指定为Http Message转换器,如下所示。

StringHttpMessageConverter

正如前面提到的writeAcceptCharset true {{}}} {{}}} {{}}} {{}}} {{}} {{}} {{}} {{}}在上面提到的帖子中,解决方案是将writeAcceptCharset设为false或不写简单字符串但使用对象然后将其编组为字符串。

对于我的用例,我希望响应类型为application/json且字符集为UTF-8,因此在配置中设置这些接受标头可以解决我的问题。