RestTemplate ResponseEntity<String> body中文乱码

5,637 阅读2分钟

欢迎来到我有一个朋友系列。坦白讲,从没想过总结什么的,但从事java开发这几年,多少还是有些要总结记录的。不会畏惧从零开始,只要够持久。 


 我有一个朋友开发中遇到一个问题,使用restTemplate的postForEntity方法,返回值为ResponseEntity
时,发现getBody时中文为乱码以及???,怎么这个样子。 大概代码Demo如下:

public ResponseModel test(){   
 ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://ip:port/something"
                                    ,new HttpEntity<String>("{}",new HttpHeaders(){{setContentType(MediaType.APPLICATION_JSON); }}),String.class);
 return ResponseModel.ok(responseEntity.getBody());}

指定了contentType APPLICATION_JSON

并且restTemplate使用的是默认配置直接注入

先说这边的两个解决方案

1.配置restTemplate,替换默认StringHttpMessageConverter

restTemplate.getMessageConverters().set(1,new StringHttpMessageConverter(StandardCharsets.UTF_8));

2.Header中添加Accept,以及修改ContentType

new HttpHeaders(){{   
 setContentType(MediaType.APPLICATION_JSON_UTF8);   
 setAccept(new ArrayList<MediaType>(){{    
    add(MediaType.APPLICATION_JSON_UTF8);   
 }});
}}

这边说一下自己并没有底气的个人理解:

首先,restTemplate默认配置中使用的StringConverter点进去可以看到,默认编码格式

public static final Charset DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;

所以我们使用一个新的UTF-8 converter替换,至于为什么set(1,x),部分空构造器代码如下

public RestTemplate() {  
 this.messageConverters.add(new ByteArrayHttpMessageConverter()); 
 this.messageConverters.add(new StringHttpMessageConverter());   //在这在这在这
 this.messageConverters.add(new ResourceHttpMessageConverter(false));   
 try {     
    this.messageConverters.add(new SourceHttpMessageConverter<>());  
 }   catch (Error err) {   
   // Ignore when no TransformerFactory implementation is available  
 }


第二种呢,之前只添加了一个Accept MediaType.APPLICATION_JSON_UTF8

Accept 请求头用来告知(服务器)客户端可以处理的内容类型,这种内容类型用MIME类型来表示

结果,返回第一层的message信息成功展示为中文,but,对象中的用户名依然为???

???????

修改contentType 为 MediaType.APPLICATION_JSON_UTF8, 大功告成。

这其中有两个小波折,暂存两个小问题

  1. 改的时候发现header有个setAcceptCharset 想当然的使用了这个方法,然后没有任何作用,????????

Accept-Charset 请求头用来告知(服务器)客户端可以处理的字符集类型。

  2.自测demo时发现

/** 
* Public constant media type for {@code application/json;charset=UTF-8}. 
* @deprecated Deprecated as of Spring Framework 5.2 in favor of {@link #APPLICATION_JSON} 
* since major browsers like Chrome
* <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=438464">
* now comply with the specification</a> and interpret correctly UTF-8 special 
* characters without requiring a {@code charset=UTF-8} parameter. 
*/
@Deprecated
public static final MediaType APPLICATION_JSON_UTF8;  

浏览器支持可以,这边restTemplate如果去掉UTF-8貌似没有效果,有点儿方,先记下