近日用Spring3的MVC写东西,深感其之于Webwork/Struts2的便利,但是在通过@ResponseBody这个annotation输出一个json字符串的时候,发现页面上获得的json字符串中文字符出现了乱码的现象。通过firefox观察返回的字符串,中文部分全部变成了???????的形式,初步判定是返回时,spring处理@ResponseBody使用了错误的编码。
因为我在web.xml中已经配置了Spring的CharacterEncodingFilter,并且强制将request和response的编码都指定为utf-8,所以出现乱码的原因肯定是在Spring内部某处的逻辑了。
把log4j中关于spring的输出级别调为debug,通过访问出问题的地址,发现Spring在处理@ResponseBody这个annotation的时候,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter使用了org.springframework.http.converter.StringHttpMessageConverter进行处理,于是打开了Spring的源码,看看这个类究竟做了哪些事情。
不看不要紧,一看吓一跳,里面竟然是这样定义其默认编码的:
1 |
public static final Charset
DEFAULT_CHARSET = Charset.forName("ISO-8859-1"); |
顿时心生N种不爽:堂堂Spring,竟然还在其中用西欧字符集作为其默认编码,坑爹啊!(很多spring的类中,涉及编码的已经都是utf-8了,比如负责JSON视图的MappingJacksonHttpMessageConverter,就是默认使用UTF-8)。本来想直接修改spring的源码重新打包一个jar出来,后来看spring的java doc发现,其父类org.springframework.http.converter.AbstractHttpMessageConverter中的getDefaultContentType方法是可以重写的:
By default, this returns the first element of the supportedMediaTypes property, if any. Can be overridden in subclasses.
心想这下就简单了,你的DEFAULT_CHARSET不是final么?那我自己继承一个出来,按照我的需求定义为utf-8不就得了?代码如下:
01 |
public class UTF8StringHttpMessageConverter extendsStringHttpMessageConverter
{ |
03 |
private static final MediaType
utf8 = new MediaType("text","plain", |
04 |
Charset.forName("UTF-8")); |
05 |
private boolean writeAcceptCharset
= true; |
08 |
protected MediaType
getDefaultContentType(String dumy) { |
12 |
protected List<Charset>
getAcceptedCharsets() { |
13 |
return Arrays.asList(utf8.getCharSet()); |
16 |
protected void writeInternal(String
s, HttpOutputMessage outputMessage) |
18 |
if (this.writeAcceptCharset)
{ |
19 |
outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets()); |
21 |
Charset
charset = utf8.getCharSet(); |
22 |
FileCopyUtils.copy(s, newOutputStreamWriter(outputMessage.getBody(), |
26 |
public boolean isWriteAcceptCharset()
{ |
27 |
return writeAcceptCharset; |
30 |
public void setWriteAcceptCharset(boolean writeAcceptCharset)
{ |
31 |
this.writeAcceptCharset
= writeAcceptCharset; |
然后,在spring的配置文件中添加如下bean声明,用自己写的类替换掉原有的StringHttpMessageConverter:
1 |
<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> |
2 |
<property name="messageConverters"> |
4 |
<bean id="utf8StringHttpMessageConverter"class="xxx.xxx.UTF8StringHttpMessageConverter" /> |
再看通过@ResponseBody返回的json字符串,终于中文都可以正常显示了。
- Spring @ResponseBody 返回乱码 的优雅解决办法
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 返回的结果中,中文全部被问号(?)代替的解决办法: *-servlet.xml的部分配置如下: <bean id=&quo ...
- 发布mvc遇到的HTTP错误 403.14-Forbidden解决办法
发布mvc遇到的HTTP错误 403.14-Forbidden解决办法 <system.webServer> <validationvalidateIntegratedMod ...
- Linux下Oracle中SqlPlus时上下左右键乱码问题的解决办法
window下的sqlplus可以通过箭头键,来回看历史命令,用起来非常的方便. 但是在Linux下,会出现各种乱码,非常不方便,如下图所示,每次打错一个字符就需要重新打一遍. 解决办法:rlwrap ...
- jmete察看结果树和body data乱码问题的解决办法
jmeter察看结果树乱码问题的解决办法: (1)在jmeter的bin目录下找到jmeter.properties这个文件添加sampleresult.default.encoding=utf-8 ...
- PHP JSON乱码简洁的解决办法
PHP JSON乱码简洁的解决办法 $arr = array('ret'=>400, 'msg'=>'服务器地址不允许', 'data'=>''); foreach ( $arr a ...
- eclipse中js中文乱码问题的解决办法
在Eclipse中编辑JS文件简直是一种折磨,但是却总是很无奈得要去适应. 这里说一下Eclipse中,编辑JS文件时候,出现中文乱码问题的解决办法. 这个问题很容易想到是文件编码的问题,因此通常是修 ...
- 20190713_(转)IIS上部署MVC网站,打开后ExtensionlessUrlHandler-Integrated-4.0解决办法 (转)
此文为转载; 原文链接地址: https://www.cnblogs.com/mrma/p/3529859.html ----------------------------------------- ...
- (tamcat控制台乱码)在idea中运行toncat后控制台出现乱码的情况解决办法(教程附图)。
详细教程: (tamcat控制台乱码)在idea中运行toncat后控制台出现乱码的情况解决办法(教程附图)._IT打工酱的博客-CSDN博客
- Spring Mvc中@ResponseBody中文乱码解决,以及修改返回的Content-Type
http://www.codeif.com/topic/784 spring 3 mvc 的 @ResponseBody返回数据用起来很方便,但是中文乱码,而且返回的Content-Type不带编码信 ...
随机推荐
- sql中奇怪的sum(1),sum(2),count(1),count(6),count(*):统计总数
sql的统计函数 sql统计函数有 count 统计条数,配合group用 sum 累加指定字段数值 但注意sum(1)就特殊 sum(1)等同于count(*) sum(1)统计个数,功能和coun ...
- Eclipse 主题
Eclipse开发环境默认都是白底黑字的,看到同事的Xcode中设置的黑灰色背景挺好看的,就去网络上查了一下.发现Eclipse也可以设置主题. http://eclipsecolorthemes.o ...
- UE4利用Save Game创建全局变量
因为盲目的做了一个UE4的项目,没有用到UE4的无缝加载,我只能在一个个关卡中手动切换,然后每次的数据都会重置,这对于项目来说,造成了体验感的极度下降. 然而我查了一下怎样在UE4中创建全局变量,找到 ...
- 从JDK源码角度看java并发线程的中断
线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...
- Uva - 11853 - Paintball
先判断是否有解,从上到下dfs判断连通性,如果有从顶部到底部连通图,则无解.再判断最北的进出位置,从上边界开始遍历,沿途检查与边界相交的圆.这些圆的左边界的交点中最靠南边的一个就是所有的最北进入位置, ...
- sql中with的用法(CTE公用表表达式):应用子查询嵌套,提高sql性能
一.WITH AS的含义 WITH AS短语,也叫子查询部分(subquery factoring),定义一个SQL片断,该片断会被整个SQL语句所用到. 有时是为了让SQL语句的可读性更高些,也可能 ...
- android官方技术文档翻译——Case 标签中的常量字段
本文译自androd官方技术文档<Non-constant Fields in Case Labels>,原文地址:http://tools.android.com/tips/non-co ...
- (五十一)KVC与KVO详解
KVC的全称为key value coding,它是一种使用字符串间接更改对象属性的方法. 假设有一个Person类和一个Student类,其中Person类有age.name两个属性,Student ...
- (二十八)QQ好友列表的展开收缩
要通过监听HeaderView上面的Button来进行操作: 通过addTarget方法即可,应该将按钮的点击方法封装在HearView控制器内部. 列表收起来的原理: tableView: numb ...
- hive基本的操作语句(实例简单易懂,create table XX as select XX)
hive建表语句DML:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-Cr ...