您的位置:首页 > 编程语言 > Java开发

Spring RestTemplate出现乱码解决方法

2018-03-02 19:06 453 查看
发起Http请求有很多方法,Spring本身提供了RestTemplate类,简化了发起HTTP请求以及处理响应的过程,并且支持REST

我们一般都是在xml配置文件中注入RestTemplate实现单例,一般初始化时会指定一些Converter用于不同的请求解析,下面是我之前的配置

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean
class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text"/>
<constructor-arg index="1" value="plain"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="json"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>


出现中文乱码的原因一般都是因为StringHttpMessageConverter这个类,查看源码可以知道它的默认编码是ISO-8859-1,但是有提供给我们一个构造方法来初始化编码

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
private final Charset defaultCharset;
private final List<Charset> availableCharsets;
private boolean writeAcceptCharset;

public StringHttpMessageConverter() {
this(DEFAULT_CHARSET);
}

public StringHttpMessageConverter(Charset defaultCharset) {
super(new MediaType[]{new MediaType("text", "plain", defaultCharset), MediaType.ALL});
this.writeAcceptCharset = true;
this.defaultCharset = defaultCharset;
this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
}
.......
}


因此配置成下面这样可以使用于大部分情况

<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>


之所以说是大部分情况,是因为我如此修改以后发现乱码的问题并没有解决,原因我使用的是multipartform/data的请求,也就是表单提交,使用的是FormHttpMessageConverter,查看源码可知

public class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Charset charset;
private Charset multipartCharset;
private List<MediaType> supportedMediaTypes;
private List<HttpMessageConverter<?>> partConverters;

public FormHttpMessageConverter() {
this.charset = DEFAULT_CHARSET;
this.supportedMediaTypes = new ArrayList();
this.partConverters = new ArrayList();
this.supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
this.supportedMediaTypes.add(MediaType.MULTIPART_FORM_DATA);
this.partConverters.add(new ByteArrayHttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
this.partConverters.add(stringHttpMessageConverter);
this.partConverters.add(new ResourceHttpMessageConverter());
}
....
}


FormHttpMessageConverter默认使用的是ISO-8859-1编码的StringHttpMessageConverter,并且没有提供方法修改,方法就是手动注入UTF-8格式的StringHttpMessageConverter.对上面的配置文件进行修改,修改后的配置基本就可以适用所有的情况了

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
<value>multipart/form-data;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/xml;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="partConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
<value>multipart/form-data;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/xml;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text"/>
<constructor-arg index="1" value="plain"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="json"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="multipart"/>
<constructor-arg index="1" value="form-data"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="text"/>
<constructor-arg index="1" value="plain"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="application"/>
<constructor-arg index="1" value="json"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
<bean class="org.springframework.http.MediaType">
<constructor-arg index="0" value="multipart"/>
<constructor-arg index="1" value="form-data"/>
<constructor-arg index="2" value="UTF-8"/>
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/x-www-form-urlencoded;charset=UTF-8</value>
<value>multipart/form-data;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>application/xml;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>


这里的配置还有需要注意的:

MappingJackson2HttpMessageConverter

和名字一样,用于json数据转换的,我当前的环境是spring4,spring3及之前版本中使用的是MappingJacksonHttpMessageConverter,并且最好对支持的MediaType进行配置,指定text/plain,application/json形式的请求编码为UTF-8

并且不仅在AllEncompassingFormHttpMessageConverter的partConverter中需要指定MappingJackson2HttpMessageConverter,在外层RestTemplate的messageConverters中也需要配置这个Converter,因为AllEncompassingFormHttpMessageConverter只对上传的数据进行转换,获取返回数据的时候如果刚好是json格式的就报错了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: