Spring Rest 模板中的哑剧类型无效?

Soh*_*ham 2 java spring resttemplate spring-rest jackson2

我只是想发出一个简单的 REST 请求,如下所示

\n\n
String url = "some url";\nMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();\nheaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);\nheaders.add(HttpHeaders.AUTHORIZATION, "some authorization");\nRestTemplate restTemplate = new RestTemplate();\nrestTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());\nBody body = new Body();\nbody.setRemarks("test");\norg.springframework.http.HttpEntity request = new org.springframework.http.HttpEntity(body, headers);\ntry {\n    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, request, String.class);\n    System.out.println("Status Response: "+ response.getStatusCode() +". Body: "+ response.getBody());\n} catch (HttpClientErrorException | HttpServerErrorException e) {\n    e.printStackTrace();\n} catch (Exception e) {\n    e.printStackTrace();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
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, */*"\nat org.springframework.http.MediaType.parseMediaType(MediaType.java:452)\nat org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:745)\nat org.springframework.web.client.DefaultResponseErrorHandler.getCharset(DefaultResponseErrorHandler.java:115)\nat org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:63)\nat org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:700)\nat org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:653)\nat org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)\nat org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,当我通过邮递员尝试相同的请求时,它起作用了。我错过了一些非常简单的东西,但我不知道是什么。

\n\n

我检查了邮差和标题的响应,它们似乎保持良好的状态,Content-Type \xe2\x86\x92application/json; charset=UTF-8并且响应也格式良好。

\n\n

我也无法确定请求或响应的哪一部分存在问题。

\n

Soh*_*ham 7

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

headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.ACCEPT_CHARSET, StandardCharsets.UTF_8.name());
Run Code Online (Sandbox Code Playgroud)

长答案:感谢尼古拉·舍甫琴科(Nikolay Shevchenko)的建议,使用调试器来挖掘当服务器上出现错误时RestTemplate尝试从响应中收集所有标头和正文以创建合理的异常消息。在尝试从响应创建该消息时,它获得了 mime 类型

text/plain, application/json, application/json, application/*+json, application/*+json, */*; charset=UTF-8
Run Code Online (Sandbox Code Playgroud)

是的,整个文本长度而不是像Postmanapplication/json; charset=UTF-8的相同请求所示。因此,在我的较旧的 Spring Rest 模板版本的情况下,当它尝试解析上面提供的 mime 类型时,它会失败,并产生此消息。

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, */*"
Run Code Online (Sandbox Code Playgroud)

因此,不会出现服务器错误,而是会从更深的堆栈中冒出更细粒度的 mime 类型异常,这对您正在搜索的内容毫无意义。

根据M. Deinum这篇文章,尽管我已指定 Jackson 到 Http 消息转换器,但最终使用的方式如下所示。 RestTemplateStringHttpMessageConverter

restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
Run Code Online (Sandbox Code Playgroud)

正如前面提到的帖子中提到的,StringHttpMessageConverterwriteAcceptCharset带来true了具有几乎所有可能值的 mime 类型的长格式。在提到的帖子中,解决方案是要么编写writeAcceptCharsetfalse或不编写纯字符串,而是使用对象,然后将其编组为字符串。

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