在我们解决问题前,先来查看这样一张图
由此可知SpringMVC接收和响应数据时都会经过HttpMessageConverter接口类
而我们的问题是响应json字符串(String),那么自然会调用HttpMessageConverter的某一实现类来完成相关数据的编码转换。
可以发现在org.springframework.http.converter.StringHttpMessageConverter是实现此过程的实现类。因此我们如要解决乱码问题需要从此处下手。
解决方案1
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
我们发现StringHttpMessageConverter类里面默认编码是ISO-8859-1,所以我们在返回json串时会乱码,因此我们可以重写一个类继承自StringHttpMessageConverter,重写其内部方法,并且设置默认编码为UTF-8
public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private volatile List<Charset> availableCharsets;
private boolean writeAcceptCharset;
public UTF8StringHttpMessageConverter() {
this(DEFAULT_CHARSET);
}
public UTF8StringHttpMessageConverter(Charset defaultCharset) {
super(defaultCharset, new MediaType[]{MediaType.TEXT_PLAIN, MediaType.ALL});
this.writeAcceptCharset = true;
}
public void setWriteAcceptCharset(boolean writeAcceptCharset) {
this.writeAcceptCharset = writeAcceptCharset;
}
@Override
public boolean supports(Class<?> clazz) {
return String.class == clazz;
}
@Override
protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
return StreamUtils.copyToString(inputMessage.getBody(), charset);
}
@Override
protected Long getContentLength(String str, MediaType contentType) {
Charset charset = this.getContentTypeCharset(contentType);
try {
return (long)str.getBytes(charset.name()).length;
} catch (UnsupportedEncodingException var5) {
throw new IllegalStateException(var5);
}
}
@Override
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
if (this.writeAcceptCharset) {
outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
}
Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
StreamUtils.copy(str, charset, outputMessage.getBody());
}
protected List<Charset> getAcceptedCharsets() {
if (this.availableCharsets == null) {
this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
}
return this.availableCharsets;
}
private Charset getContentTypeCharset(MediaType contentType) {
return contentType != null && contentType.getCharset() != null ? contentType.getCharset() : this.getDefaultCharset();
}
}
然后只需要将该类,注册到Spring的annotaion 处理序列中即可,下次SpringMVC返回json数据时会自动调用用户自定义的converter
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.javazhan.controller.UTF8StringHttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
解决方案2
对springMVC框架内默认的Converter进行重新配置,配置其对于UTF-8等编码的支持
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>application/xml;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
解决方案3
使用produces属性
在RequestMapping使用(produces = “text/html; charset=utf-8”)produces 作用根据请求头中的Accept进行匹配,如请求头“Accept:text/html”时即可匹配。
如果类型是:application/json ,设置为:produces = “application/json; charset=utf-8”
解决方案4
在以前学servlet过程中,记得是可以设置响应的数据编码格式的,这样也可以完成乱码问题的解决
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println(data.toString());
out.flush();
out.close();