近日做一个小项目,用spring mvc 做到ajax请求获取jquery ztree 异步获取树返回json对象时出现了乱码,试了各种办法,查了各种资料,一开始以为是数据库的编码有问题,经测试没问题,又以为是jetty需要设置下响应头,正在查找时突然想到可能是mvc的responseBody的问题,网上一查,果然是,用了一个设置最简单的办法,解决了问题,特将文章转贴于此,与我一样遇到此问题的朋友们共享。
添加@RequestMapping注解,配置produces的值
1 | @RequestMapping (value = "/add" , produces = { "application/json;charset=UTF-8" }) |
(注:我就是用这种方法解决的,简单实用,呵呵)
SpringMVC的@ResponseBody注解可以将请求方法返回的对象直接转换成JSON对象,但是当返回值是String的时候,中文会乱码,原因是因为其中字符串转换和对象转换用的是两个转换器,而String的转换器中固定了转换编码为"ISO-8859-1",网上也很多种解决方法,有通过配置Bean编码的,也有自己重写转换器的,我这里多次尝试未果,只能自己解决。
有两种解决办法:
1.返回字符串时,将字符串结果转换
1 | return new String( "你好" .getBytes(), "ISO-8859-1" ); |
2.添加@RequestMapping注解,配置produces的值
1 | @RequestMapping (value = "/add" , produces = { "application/json;charset=UTF-8" }) |
(注:我就是用这种方法解决的,简单实用,呵呵)
由于我是为了使用JSONP协议,需要连同callback一起返回,所以我定义的是
1 | @RequestMapping (value = "/add" , params = { "callback" }, produces = { "text/javascript;charset=UTF-8" }) |
以上提供的方法虽然需要额外配置,但相对灵活,喜欢一次性永久搞定的,还是应该考虑网上的方法,修改源码,或者替换默认的字符串转换器。
但是在使用<mvc:annotation-driven />配置的前提下,貌似网上的方法都不可靠,可能跟版本或者配置有关系
这边提供一种修改方法,我这边使用的是3.1的mvc
1.参考网上将默认的StringHttpMessageConverter重写一遍,将其中的编码改为UTF-8
01 | import java.io.IOException; |
02 | import java.io.InputStreamReader; |
03 | import java.io.OutputStreamWriter; |
04 | import java.io.UnsupportedEncodingException; |
05 | import java.nio.charset.Charset; |
06 | import java.util.ArrayList; |
07 | import java.util.List; |
09 | import org.springframework.http.HttpInputMessage; |
10 | import org.springframework.http.HttpOutputMessage; |
11 | import org.springframework.http.MediaType; |
12 | import org.springframework.http.converter.AbstractHttpMessageConverter; |
13 | import org.springframework.util.FileCopyUtils; |
15 | public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> { |
17 | public static final Charset DEFAULT_CHARSET = Charset.forName( "UTF-8" ); |
19 | private final List<Charset> availableCharsets; |
21 | private boolean writeAcceptCharset = true ; |
23 | public UTF8StringHttpMessageConverter() { |
24 | super ( new MediaType( "text" , "plain" , DEFAULT_CHARSET), MediaType.ALL); |
25 | this .availableCharsets = new ArrayList<Charset>(Charset.availableCharsets().values()); |
29 | * Indicates whether the {@code Accept-Charset} should be written to any outgoing request. |
30 | * <p>Default is {@code true}. |
32 | public void setWriteAcceptCharset( boolean writeAcceptCharset) { |
33 | this .writeAcceptCharset = writeAcceptCharset; |
37 | public boolean supports(Class<?> clazz) { |
38 | return String. class .equals(clazz); |
42 | protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { |
43 | Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType()); |
44 | return FileCopyUtils.copyToString( new InputStreamReader(inputMessage.getBody(), charset)); |
48 | protected Long getContentLength(String s, MediaType contentType) { |
49 | Charset charset = getContentTypeCharset(contentType); |
51 | return ( long ) s.getBytes(charset.name()).length; |
53 | catch (UnsupportedEncodingException ex) { |
55 | throw new InternalError(ex.getMessage()); |
60 | protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException { |
61 | if (writeAcceptCharset) { |
62 | outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets()); |
64 | Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType()); |
65 | FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset)); |
69 | * Return the list of supported {@link Charset}. |
71 | * <p>By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses. |
73 | * @return the list of accepted charsets |
75 | protected List<Charset> getAcceptedCharsets() { |
76 | return this .availableCharsets; |
79 | private Charset getContentTypeCharset(MediaType contentType) { |
80 | if (contentType != null && contentType.getCharSet() != null ) { |
81 | return contentType.getCharSet(); |
84 | return DEFAULT_CHARSET; |
2.context配置
01 | <beans xmlns= "http://www.springframework.org/schema/beans" |
02 | xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc= "http://www.springframework.org/schema/mvc" |
03 | xmlns:p= "http://www.springframework.org/schema/p" xmlns:context= "http://www.springframework.org/schema/context" |
04 | xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" |
05 | xsi:schemaLocation="http: |
19 | <mvc:annotation-driven> |
20 | <mvc:message-converters> |
21 | <bean class = "yourpackage.UTF8StringHttpMessageConverter" /> |
22 | </mvc:message-converters> |
23 | </mvc:annotation-driven> |