Ajax响应中文乱码 [SpringMVC使用@ResponseBody处理Ajax请求]
Spring3.0 MVC @ResponseBody 的作用是把返回值直接写到HTTP response body里。
Spring使用AnnotationMethodHandlerA<wbr>dapter的handleResponseBody方法, AnnotationMethodHandlerA<wbr>dapter使用request header中"Accept"的值和messageConverter支持的MediaType进行匹配,然后会用"Accept"的第一个值写入response的"Content-Type"。一般的请求都是通过浏览器进行的,request header中"Accept"的值由浏览器生成。
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
有人跟踪<strong>@ResponseBody</strong>的实现类发现其默认的编码是<strong>iso-8859-1</strong>,</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
<strong>解决办法,在spring mvc的配置文件中手工配置bean:<br></strong><!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 --><br>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerA<wbr>dapter" ><br>
<property name="messageConverters"><br>
<list><br>
<bean class = "org.springframework.http.converter.StringHttpMessageConvert<wbr>er"><br>
<property name = "supportedMediaTypes"><br>
<list><br>
<value>text/html;charset=UTF-8</value><br>
</list><br>
</property><br>
</bean><br>
</list><br>
</property><br>
</bean><br></wbr></wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
这样通过配置<strong>AnnotationMethodHandlerA<wbr>dapter</wbr></strong>类messageConverters属性来指定编码。<br>
记住,需要把bean部分加入到<context:component-scan base-package="com.zlscw.mvc"/>前面,</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
这样就可以在jquery中直接调用而不出现乱码了。</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
-------------------------------------------这篇文章说的很到位</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
近日用Spring3的MVC写东西,深感其之于Webwork/Struts2的便利,但是在通过@ResponseBody这个annotation输出一个json字符串的时候,发现页面上获得的json字符串中文字符出现了乱码的现象。通过firefox观察返回的字符串,中文部分全部变成了???????的形式,初步判定是返回时,spring处理@ResponseBody使用了错误的编码。</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
因为我在web.xml中已经配置了Spring的CharacterEncodingFilter,并且强制将request和response的编码都指定为utf-8,所以出现乱码的原因肯定是在Spring内部某处的逻辑了。</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
把log4j中关于spring的输出级别调为debug,通过访问出问题的地址,发现Spring在处理@ResponseBody这个annotation的时候,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerA<wbr>dapter使用了org.springframework.http.converter.StringHttpMessageConvert<wbr>er进行处理,于是打开了Spring的源码,看看这个类究竟做了哪些事情。</wbr></wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
不看不要紧,一看吓一跳,里面竟然是这样定义其默认编码的:</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
1<strong>publicstaticfinal</strong>Charset DEFAULT_CHARSET = Charset.forName("ISO-8859-1");</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
顿时心生N种不爽:堂堂Spring,竟然还在其中用西欧字符集作为其默认编码,坑爹啊!(很多spring的类中,涉及编码的已经都是utf-8了,比如负责JSON视图的MappingJacksonHttpMessag<wbr>eConverter,就是默认使用UTF-8)。本来想直接修改spring的源码重新打包一个jar出来,后来看spring的java doc发现,其父类org.springframework.http.converter.AbstractHttpMessageConve<wbr>rter中的getDefaultContentType方法是可以重写的:</wbr></wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
By default, this returns the first element of the supportedMediaTypes property, if any. Can be overridden in subclasses.</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
心想这下就简单了,你的DEFAULT_CHARSET不是final么?那我自己继承一个出来,按照我的需求定义为utf-8不就得了?代码如下:</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
01<strong>publicclass</strong>UTF8StringHttpMessageCon<wbr>verter<strong>extends</strong>StringHttpMessageConvert<wbr>er { 02 03<strong>privatestaticfinal</strong>MediaType utf8 =<strong>new</strong>MediaType("text", "plain", 04 Charset.forName("UTF-8"));
05<strong>privateboolean</strong>writeAcceptCharset =<strong>true</strong>; 06 07 @Override08<strong>protected</strong>MediaType getDefaultContentType(String dumy) { 09<strong>return</strong>utf8; 10 } 11 12<strong>protected</strong>List getAcceptedCharsets()
{ 13<strong>return</strong>Arrays.asList(utf8.getCharSet()); 14 } 15 16<strong>protectedvoid</strong>writeInternal(String s, HttpOutputMessage outputMessage) 17<strong>throws</strong>IOException { 18<strong>if</strong>(<strong>this</strong>.writeAcceptCharset)
{ 19 outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets()); 20 } 21 Charset charset = utf8.getCharSet(); 22 FileCopyUtils.copy(s,<strong>new</strong>OutputStreamWriter(outputMessage.getBody(), 23 charset)); 24 } 25 26<strong>publicboolean</strong>isWriteAcceptCharset()
{ 27<strong>return</strong>writeAcceptCharset; 28 } 29 30<strong>publicvoid</strong>setWriteAcceptCharset(<strong>boolean</strong>writeAcceptCharset) { 31<strong>this</strong>.writeAcceptCharset = writeAcceptCharset; 32 } 33 34}</wbr></wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
然后,在spring的配置文件中添加如下bean声明,用自己写的类替换掉原有的StringHttpMessageConvert<wbr>er:</wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
1<em>"org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerA<wbr>dapter"</wbr></em>> 2<em>"messageConverters"</em>> 3 4<em>"utf8StringHttpMessageCon<wbr>verter"</wbr></em>class=<em>"xxx.xxx.UTF8StringHttpMessageCon<wbr>verter"</wbr></em>/> 5 6 7</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
再看通过@ResponseBody返回的json字符串,终于中文都可以正常显示了。</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
-------------------------------------------下面有一些解释</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
但我们一般会在标注@ResponseBody的方法上返回String或byte[]类型的结果,期望的"Content-Type"的值应为"text/plain"或"application/octet-stream"。<br>
这样导致了浏览器不能正确处理返回的内容。<br>
实际上Spring在用HttpMessageConverter处理的过程中首先会判断response header中有没有写入"Content-Type",如果没有写入的话才会使用request header中"Accept"的第一个值。<br>
但是由于Spring对HttpServletResponse进行了封装,实际上使用的是ServletServerHttpRespons<wbr>e,这个类有一个对真正的HttpServletResponse的引用。<br>
判断response header的过程中使用的是ServletServerHttpRespons<wbr>e的getHeaders()方法,但该方法并没有返回真正的HttpServletResponse中的header。(这应该有问题吧?)<br>
所以我们虽然可以在Controller的方法中加入对HttpServletResponse的引用,然后设置"Content-Type"的值,但是并不会起作用。<br>
来处理@ResponseBody,该类再使用一些HttpMessageConverter来具体处理信息。<br>
Chrome生成的值为application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,**<br>
所以最后写入response中"Content-Type"的值为"application/xml"或"application/x-ms-application"。</wbr></wbr></p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
-------------------------------------------------其实这个注解完全可以不用,直接使用response往输出流里面写。</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
使用jQuery ajax调用的返回json,中文乱码问题</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
Jquery :</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
$.ajax({<br>
url: '/test/testAction.do?method=test',<br>
type: 'POST',<br>
dataType: 'json',<br>
timeout: 5000,<br>
async: false,<br>
error: function(){<br>
alert('获取数据失败!');<br>
},<br>
success: function(json){<br>
jsObject = eval_r(json);<br>
}<br>
});<br>
return jsObject;</p>
<p style="margin-top:0px; margin-bottom:5px; padding-top:0px; padding-bottom:0px; border:0px; list-style:none; word-wrap:normal; word-break:normal">
JSONArray json = JSONArray.fromObject(SysList);//SysList是一个List<br>
// 设置response的ContentType解决中文乱码<br>
response.setContentType("text/html;charset=UTF-8");<br>
response.getWriter().print(json.toString());<br>
return null;</p>
</wbr></wbr>
相关推荐
spring mvc 开发的必须有的架包org.springframework.web.servlet-3.0.5.RELEASE.jar
<bean class="org.springframework.web.servlet.mvc.annotation. AnnotationMethodHandlerAdapter"/> <!-- ③:对模型视图名称的解析,即在模型视图名称添加前后缀 --> class="org.springframework.web....
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <!-- Support JSON --> <bean class="org.spring...
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" /> ...
14. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> 15. 16. <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> 17. <bean class="org....
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <!-- apache.dbcp连接池的配置 --> <bean id="dataSource" class="org.apache.commons.dbcp....
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) at org.springframework.web.servlet.mvc.method....
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HelloController { @RequestMapping("/Login.jsp") public ...
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.org.core.entity.User; import com.org.core.service.UserService; import ...
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> ...
This is a tutorial on Spring MVC, a module in the Spring Framework for rapidly developing web applications. The MVC in Spring MVC stands for Model-View-Controller, a design pattern widely used in ...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> ...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> ...
import org.springframework.web.bind.annotation.RequestMapping; @Controller public class GeneralController { @RequestMapping(value="index.do") public void index_jsp(Model model){ model....
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="0"> <property name="interceptors"> <list> <ref bean="doubleSubmitInterceptor"/> </list> ...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
27.1. The “Spring Web MVC Framework” 27.1.1. Spring MVC Auto-configuration 27.1.2. HttpMessageConverters 27.1.3. Custom JSON Serializers and Deserializers 27.1.4. MessageCodesResolver 27.1.5. Static...
1.项目管理和综合工具:maven(1)Maven安装和配置:参考(2)Eclipse和IDEA配置Maven2.Spring版本:5.0.73.MVC:Spring MVC配置(1)jar包:spring-webmvc.jar(2)web.xml配置SpringMVC监听类:org.springframework.web....