情况大体是这样的:一个头页面header.jsp上有一个搜索框,输入关键字之后提交到另一个搜索页面search.jsp输出搜索结果;header.jsp在业务应用下,search.jsp在发布系统的应用下,两个应用使用同一个tomcat。关键字keyword作为参数传递到搜索页面search.jsp,也就是window.location.href='search.jsp?keyword=关键字'。两个页面设置的编码格式都是UTF-8;但是具体测试中出现了很奇怪的问题,就是在firefox下一切正常,参数传递是正常的,搜索中文英文都没有问题;但是在IE下就不行了,搜索汉字时,汉字个数是偶数个时一切正常,奇数个时最后一个汉字接受过来就是乱码;也就是说,search.jsp?keyword=关键,这样是正常的,但是search.jsp?keyword=关键字,这样时你取到的keyword参数最后一个字“字”就是乱码。 查了不少资料,说汉字在UTF-8编码格式下是占3个字节的,而在unicode编码格式下是占2个字节,参数传递的时候需要在unicode编码格式下传递,所以不管你页面中设置的是什么编码格式,传递之前浏览器都会给你自动做编码转化。当汉字个数是偶数个的时候,字节总数也是偶数可以被正常转化,但是当汉字个数是奇数时,字节总数是奇数,无法被2整除,所以最后一个汉字显示乱码。至于firefox下为什么正常,估计是firefox下参数的编码格式转化机制不同所致。
查询到不少解决办法,有的说用js的encodeURI 进行一次编码转换,有的也说用post方式传递,试了之后都不行。 最后的解决办法是在传递之前就对关键字进行一次编码格式的转换,这是网上的代码:
function EncodeUtf8(s1) { var s = escape(s1); var sa = s.split("%"); var retV =""; if(sa[0] != "") { retV = sa[0]; } for(var i = 1; i < sa.length; i ++) { if(sa[i].substring(0,1) == "u") { retV += Hex2Utf8(Str2Hex(sa[i].substring(1,5))); } else retV += "%" + sa[i]; } return retV; } function Str2Hex(s) { var c = ""; var n; var ss = "0123456789ABCDEF"; var digS = ""; for(var i = 0; i < s.length; i ++) { c = s.charAt(i); n = ss.indexOf(c); digS += Dec2Dig(eval(n)); } //return value; return digS; } function Dec2Dig(n1) { var s = ""; var n2 = 0; for(var i = 0; i < 4; i++) { n2 = Math.pow(2,3 - i); if(n1 >= n2) { s += '1'; n1 = n1 - n2; } else s += '0'; } return s; } function Dig2Dec(s) { var retV = 0; if(s.length == 4) { for(var i = 0; i < 4; i ++) { retV += eval(s.charAt(i)) * Math.pow(2, 3 - i); } return retV; } return -1; } function Hex2Utf8(s) { var retS = ""; var tempS = ""; var ss = ""; if(s.length == 16) { tempS = "1110" + s.substring(0, 4); tempS += "10" + s.substring(4, 10); tempS += "10" + s.substring(10,16); var sss = "0123456789ABCDEF"; for(var i = 0; i < 3; i ++) { retS += "%"; ss = tempS.substring(i * 8, (eval(i)+1)*8); retS += sss.charAt(Dig2Dec(ss.substring(0,4))); retS += sss.charAt(Dig2Dec(ss.substring(4,8))); } return retS; } return ""; }
不过,这样编码转换只是针对IE浏览器,如果在firefox下也这样操作会出现乱码的。无奈,需要添加一个浏览器类型的判断。 以上是我自己的理解,有经验的朋友欢迎交流。