Thursday, January 13, 2011

springmvc 中ajax提交发生乱码问题

这个问题目前只是在springmvc项目中碰到,在IE和Chrome中,当用jQuery.post()方法发起ajax请求时,Controller中收到的中文内容变成乱码了,而在firefox中用jQuery.post()进行ajax请求时是正常的。
在Controller中调用如下代码(项目为UTF-8编码):


// name 是post收到的字符串变量名
System.out.println(new String(name.getBytes(HTTP.ISO_8859_1), HTTP.UTF_8));

可以看到乱码恢复正常,说明IE和Chrome提交的ajax请求中的内容被编码成 ISO-8859-1 编码了。
而实际上,对于IE而已,所有的ajax请求都是以UTF-8方式发起的,通过以下方式设置ajax请求的编码为GBK实际是没有用的,服务器收到仍然是UTF-8编码的请求体:

xmlhttp.setRequestHeader( "Content-Type", "text/html;charset=GBK" );
// or
xmlhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=GBK");

因此可以肯定是springmvc在收到POST请求后,将请求体的数据用 ISO-8859-1 编码来处理了,最后传到Controller中时变成了乱码,但是为何firefox中提交的却仍然是正确的呢?
在firebug中观察firefox中的ajax请求头,可以看到firebug中的提示:

Content-Type application/x-www-form-urlencoded; charset=UTF-8

而在IE中用http analysis工具看到的却是:

Content-Type application/x-www-form-urlencoded

google Chrome中与IE一样,ajax请求头中没有指明编码,所以Chrome和IE一样将发生乱码了。
查看jquery-1.4.4.js源码可以看到,jQuery中原来的 contentType设置为"application/x-www-form-urlencoded",IE和Chrome中的请求头显示是正确的,没有问题,反而是firefox将contentType中设置了编码。
从这个请求头分析来看,应该是springmvc没有得到请求的编码,而将其内容设置为ISO-8859-1了,因此发生了乱码的情况。

解决方法还是参考firefox的请求头,在contentType中指定编码,明确告诉服务器端,当前请求体的编码方式为UTF-8。

xmlhttp.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");

如果使用jQuery发起ajax请求,javascript的代码改为如下方式发起ajax请求,而不是以$.post()和$.get()等快捷方法:

$.ajax({
url: url,
type: "POST",
dataType: "html",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: data,
complete:function(data) {
}
});

No comments :