springmvc3.0使用@ResponseBody返回参数乱码
阅读(359)
2017-12-06
使用@ResponseBody注解返回的json数据乱码。用户网络上大多数贴都是springmvc3.0以上版本,试了很多办法都不行。只能来点简单粗暴的办法。
发现原因
使用<mvc:annotation-driven />,Spring的StringHttpMessageConverter默认配置是ISO-8859-1的。如下图源代码片段所示:

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
public static final Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");
private final List<Charset> availableCharsets = new ArrayList(Charset.availableCharsets().values());
private boolean writeAcceptCharset = true;
...
}调试返回情况如下图:

{data: "", message: "????", success: 0}解决办法
快刀斩乱麻
第一步:
查看spring的StringHttpMessageConverter的源码,自定义StringHttpMessageConverter类,继承AbstractHttpMessageConverter<String>修改默认编码为UTF-8。
package com.weizhixi.converter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.util.FileCopyUtils;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* Created by cxq on 2017/12/6.
*/
public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private final List<Charset> availableCharsets = new ArrayList(Charset.availableCharsets().values());
private boolean writeAcceptCharset = true;
public StringHttpMessageConverter() {
super(new MediaType[]{new MediaType("text", "plain", DEFAULT_CHARSET), MediaType.ALL});
}
public void setWriteAcceptCharset(boolean writeAcceptCharset) {
this.writeAcceptCharset = writeAcceptCharset;
}
public boolean supports(Class<?> clazz) {
return String.class.equals(clazz);
}
protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = contentType.getCharSet() != null?contentType.getCharSet():DEFAULT_CHARSET;
return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
}
protected Long getContentLength(String s, MediaType contentType) {
if(contentType != null && contentType.getCharSet() != null) {
Charset charset = contentType.getCharSet();
try {
return Long.valueOf((long)s.getBytes(charset.name()).length);
} catch (UnsupportedEncodingException var5) {
throw new InternalError(var5.getMessage());
}
} else {
return null;
}
}
protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
if(this.writeAcceptCharset) {
outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
}
MediaType contentType = outputMessage.getHeaders().getContentType();
Charset charset = contentType.getCharSet() != null?contentType.getCharSet():DEFAULT_CHARSET;
FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset));
}
protected List<Charset> getAcceptedCharsets() {
return this.availableCharsets;
}
}第二步:
弃用<mvc:annotation-driven />,加上2个配置。注意messageConverters使用刚刚自定义的StringHttpMessageConverter。
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" > <property name="messageConverters"> <list> <bean class="com.weizhixi.converter.StringHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" > <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </list> </property> </bean>
以上处理完毕!
尝试再访问下:

{data: "", message: "请先登录", success: 0}已经正常返回了。
原创文章,转载请注明出处:https://www.weizhixi.com/article/21.html
