如何使用 UTF-8 编码告诉 RestTemplate POST?
How can I tell RestTemplate to POST with UTF-8 encoding?
我在使用 RestTemplate 使用 UTF-8 编码发布 JSON 时遇到问题。 JSON 的默认编码是 UTF-8,因此媒体类型甚至不应该包含字符集。我尝试将字符集放入 MediaType,但它似乎不起作用。
我的代码:
String dataJson = "{\"food\": \"smörrebröd\"}";
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
headers.setContentType(mediaType);
HttpEntity<String> entity = new HttpEntity<String>(dataJson, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> formEntity = restTemplate.exchange(postUrl, HttpMethod.POST, entity, Boolean.class);
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_16LE));
String response = restTemplate.getForObject(url, String.class);
您需要将 StringHttpMessageConverter 添加到 rest 模板的字符集 UTF-8 消息转换器。像这样
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
添加新的 StringHttpMessageConverter 没有帮助。
在现有的 StringHttpMessageConverter 中,我们需要将 writeAcceptCharset 设置为 false
并使用我们想要的字符集构建 httpheader。
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> c = restTemplate.getMessageConverters();
for(HttpMessageConverter<?> mc :c){
if (mc instanceof StringHttpMessageConverter) {
StringHttpMessageConverter mcc = (StringHttpMessageConverter) mc;
mcc.setWriteAcceptCharset(false);
}
}
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
HttpEntity<String> entity = new HttpEntity<String>(jsonPayload, headers);
restTemplate.postForEntity(postResourceUrl, entity, String.class);
@mushfek0001 的回答产生两个StringHttpMessageConverter
将发送两个text/plain
和*/*
,例如调试图片。
连client的Accept
header也会是:
text/plain, text/plain, */*, */*
所以更好的方法是删除 ISO-8859-1 StringHttpMessageConverter
并使用单个 UTF-8 StringHttpMessageConverter
.
使用这个:
RestTemplate restTemplate = new RestTemplate();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
restTemplate.getMessageConverters().remove(i);
restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
break;
}
}
(由mushfek0001和zhouji添加到解决方案中)
默认情况下,RestTemplate 具有 ISO-8859-1 StringHttpMessageConverter,用于将 JAVA object 转换为请求负载。
UTF-8 和 ISO-8859 的区别:
UTF-8 is a multibyte encoding that can represent any Unicode
character. ISO 8859-1 is a single-byte encoding that can represent the
first 256 Unicode characters. Both encode ASCII exactly the same way.
解决方案 1(从 mushfek001 复制):
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
解决方案 2:
虽然上述解决方案有效,但正如周记指出的那样,它会添加两个字符串转换器,可能会导致一些回归问题。
如果您在 http header 中设置了正确的内容类型,那么 ISO 8859 将负责更改 UTF 字符。
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
或
// HttpUriRequest request
request.addHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
最好先删除 StringHttpMessageConverter,然后再添加新的。这样一来,您将在我们的 MessageConverters 列表中拥有一个 StringHttpMessageConverter 实例。
RestTemplate restTemplate = new RestTemplate();
final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
while (iterator.hasNext()) {
final HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
iterator.remove();
}
}
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
删除现有转换器,但使用 Java 8(为什么人们仍然编写 Java 7 代码?)
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters.removeIf(httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter);
converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
试试这个
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(Charsets.UTF_8));
如果您使用 Spring Boot,如果您使用 RestTemplateBuilder 创建 RestTemplate 实例,它将使用高优先级 UTF-8 字符集 StringHttpMessageConverter 自动配置 RestTemplate。例如。 restTemplateBuilder.build()
我在使用 RestTemplate 使用 UTF-8 编码发布 JSON 时遇到问题。 JSON 的默认编码是 UTF-8,因此媒体类型甚至不应该包含字符集。我尝试将字符集放入 MediaType,但它似乎不起作用。
我的代码:
String dataJson = "{\"food\": \"smörrebröd\"}";
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
headers.setContentType(mediaType);
HttpEntity<String> entity = new HttpEntity<String>(dataJson, headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> formEntity = restTemplate.exchange(postUrl, HttpMethod.POST, entity, Boolean.class);
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_16LE));
String response = restTemplate.getForObject(url, String.class);
您需要将 StringHttpMessageConverter 添加到 rest 模板的字符集 UTF-8 消息转换器。像这样
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
添加新的 StringHttpMessageConverter 没有帮助。 在现有的 StringHttpMessageConverter 中,我们需要将 writeAcceptCharset 设置为 false 并使用我们想要的字符集构建 httpheader。
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> c = restTemplate.getMessageConverters();
for(HttpMessageConverter<?> mc :c){
if (mc instanceof StringHttpMessageConverter) {
StringHttpMessageConverter mcc = (StringHttpMessageConverter) mc;
mcc.setWriteAcceptCharset(false);
}
}
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
HttpEntity<String> entity = new HttpEntity<String>(jsonPayload, headers);
restTemplate.postForEntity(postResourceUrl, entity, String.class);
@mushfek0001 的回答产生两个StringHttpMessageConverter
将发送两个text/plain
和*/*
,例如调试图片。
连client的Accept
header也会是:
text/plain, text/plain, */*, */*
所以更好的方法是删除 ISO-8859-1 StringHttpMessageConverter
并使用单个 UTF-8 StringHttpMessageConverter
.
使用这个:
RestTemplate restTemplate = new RestTemplate();
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
stringHttpMessageConverter.setWriteAcceptCharset(true);
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) {
if (restTemplate.getMessageConverters().get(i) instanceof StringHttpMessageConverter) {
restTemplate.getMessageConverters().remove(i);
restTemplate.getMessageConverters().add(i, stringHttpMessageConverter);
break;
}
}
(由mushfek0001和zhouji添加到解决方案中)
默认情况下,RestTemplate 具有 ISO-8859-1 StringHttpMessageConverter,用于将 JAVA object 转换为请求负载。
UTF-8 和 ISO-8859 的区别:
UTF-8 is a multibyte encoding that can represent any Unicode character. ISO 8859-1 is a single-byte encoding that can represent the first 256 Unicode characters. Both encode ASCII exactly the same way.
解决方案 1(从 mushfek001 复制):
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
解决方案 2:
虽然上述解决方案有效,但正如周记指出的那样,它会添加两个字符串转换器,可能会导致一些回归问题。
如果您在 http header 中设置了正确的内容类型,那么 ISO 8859 将负责更改 UTF 字符。
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
或
// HttpUriRequest request
request.addHeader("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
最好先删除 StringHttpMessageConverter,然后再添加新的。这样一来,您将在我们的 MessageConverters 列表中拥有一个 StringHttpMessageConverter 实例。
RestTemplate restTemplate = new RestTemplate();
final Iterator<HttpMessageConverter<?>> iterator = restTemplate.getMessageConverters().iterator();
while (iterator.hasNext()) {
final HttpMessageConverter<?> converter = iterator.next();
if (converter instanceof StringHttpMessageConverter) {
iterator.remove();
}
}
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
删除现有转换器,但使用 Java 8(为什么人们仍然编写 Java 7 代码?)
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters.removeIf(httpMessageConverter -> httpMessageConverter instanceof StringHttpMessageConverter);
converters.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
试试这个
restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(Charsets.UTF_8));
如果您使用 Spring Boot,如果您使用 RestTemplateBuilder 创建 RestTemplate 实例,它将使用高优先级 UTF-8 字符集 StringHttpMessageConverter 自动配置 RestTemplate。例如。 restTemplateBuilder.build()