`
jejoker
  • 浏览: 25057 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Spring MVC 3.2.4 ResponseBody 编码问题解决

 
阅读更多

首先请确保Spring版本为3.2.4

问题1:使用@ResponseBody注解,返回对象类型时,如Map,中文字符,在客户端会显示为???

解决办法:请检查依赖jar包,确保spring-context-support.jar的版本也是3.2.4,则可显示中文;

 

问题2:使用@ResponseBody注解,返回String时,中文字符,在客户端会显示为???,并且contextType中会缺失encoding值,即为text/html但是,没有后面的encode

解决办法:首先需要知道,在spring3.2以后,@RequestMapping使用了RequestMappingHandlerAdapter来处理请求,对于@ResponseBody,当为string时,会调用默认构造方法里面add的StringHttpMessageConverter,需要注意的是,这个converter默认的编码是“ISO-8859-1”,中文的大敌啊,而且这个converter是new出来的,因此无法采用替代注入的方式,而只能注入messageConverters,因此,我们需要重新申明一个RequestMappingHandlerAdapter,如下:

 

	<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<beans:property name="messageConverters">
			<beans:list>
				<beans:bean class="org.springframework.http.converter.StringHttpMessageConverter">
					<beans:constructor-arg value="UTF-8" />
					<beans:property name="writeAcceptCharset" value="false"/>
				</beans:bean>
				<beans:bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></beans:bean>
				<beans:bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></beans:bean>
				<beans:bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"></beans:bean>
			</beans:list>
			
		</beans:property>
	</beans:bean>

 为什么除了StringHttpMessageConverter还有其他3个converter呢,因为默认RequestMappingHandlerAdapter构造函数是增加了4个converter的,如果不全写上,可能导致其他返回类型无法被转换,自己可以试试看,StringHttpMessageConverter有个writeAcceptCharset的设置,请自行查看源码。

 

重新定义了RequestMappingHandlerAdapter以后,中文能被正确写入到response,但是,默认情况下,客户端会看到response返回的contentType可能为"text/html",仍然没有编码显示,这时,需要主动设置response的encoding,或者采用filter。如果使用spring的CharacterEncodingFilter,请将forceEncoding设置为true。至此,客户端会看到contentType为 text/html;charset=UTF-8

 

!!补充:实际上,根据3.2.4文档可以看到,RequestMappingHandlerAdapter不仅add了以上默认的4个converter,而是更多,debug可以看到实际上是7个converter,这个是由mvc命名空间默认增加的,至于源码什么地方做的,我没找到。后来去看spring-mvc.xsd,学习到,annotation-driven标签下的message-converters可以直接替换或者增加converter,于是,我将自己做的StringHttpMessageConverter增加到了里面,而去掉了RequestMappingHandlerAdapter的bean,如下:

	<annotation-driven>
		<message-converters>
			<!-- default StringHttpMessageConverter, solve encoding problem -->
			<beans:bean	class="org.springframework.http.converter.StringHttpMessageConverter">
				<beans:constructor-arg value="UTF-8" />
				<beans:property name="writeAcceptCharset" value="false" />
			</beans:bean>
		</message-converters>
	</annotation-driven>

 这可能是更好的解决办法,但是,现在converter就会变成8个,会有2个String的converter存在,目前测试没问题,自己做的converter优先级是最高的,可能这才是最好的解决办法。

分享到:
评论
1 楼 zhengyiwei 2016-11-15  
666666666

相关推荐

Global site tag (gtag.js) - Google Analytics