下午,计划2个小时搞定,个人官网第6次升级,就可以干点轻松的事了,结果,下午多搞了2个小时,晚上又搞了2个小时,才搞定。
最后一个世界难题是,URL传递中文参数。
问题大致是这么出现的:我为“博客雷观” 这个栏目,增加了“全文搜索”功能,用lucene实现的。因此,需要传递中文参数。搜索框表单提交,传递中文,很简单就搞定了。 搜索之后的分页url,需要带上当前的“搜索词” ,比如“程序员”,我在本地很轻松就搞定了。无非就是这样:search/search.html?keyword=${keyword}" keyword就是中文词汇,比如“程序员”。 我本以为,扔到服务器上,重启一次,就万事大吉了,结果点击第2页的时候,没有搜索到任何文章。查看日志,发现搜索词是“乱码” 。 我第一反应是,传递的中文“程序员” 没有正确地进行url编码,所以:
<#setting url_escaping_charset='utf-8'>
<#assign url="${base}/search/search.html?keyword=${keyword?url}"/> 把搜索词编码之后,再附带在Url之后,但是:Windows本地环境,ok,worked。但是,线上Linux环境,仍然不行。围绕着是否正确了编码,在QQ、Chrome、IE上反复尝试了N次。结果,无论是否进行url编码,本地Windows的所有浏览器都能够正常地传递中文参数,线上Linux都失败。既然不是URL编码的问题,我觉得应该是中文编码的问题。(在初学JavaWeb开发的第1年,遇到了各种各样的编码问题,所以现在很有经验了。)
String a = "ç¨åºå";
byte[] b = a.getBytes("iso8859-1");
System.out.println(new String(b, "utf-8"));
最终打印出来的是“程序员” ,这充分说明,linux线上环境是由于“中文编码解码不一致”导致的“乱码问题”。@RequestMapping("search")
public String search( String keyword)。最开始,我仍然搞错了一点,以为keyword还是url编码,还需要一次解码。后来发现,SpringMVC接收参数的时候,会自动进行url解码,这个时候的keyword已经是“字符” 了。我的解决方法:
log.info("searchKey=" + keyword);
searchService.search(luceneIndexDir, keyword, pageVo);
//可能是参数乱码导致的
if (pageVo.getTotalCount() <= 0) {
//浏览器发送的中文参数虽然是url编码的,但是spring也会自动解码,之所以乱码,应该是url编码和url解码的“字符集编码”不同导致的。
//如果遇到这种情况,线上linux遇到了,再把iso5559-1的字符串转换为utf-8的
log.info("search url iso8859-1,when in is:"+keyword);
byte[] b =keyword.getBytes("iso8859-1");
keyword=new String(b, "utf-8");
searchService.search(luceneIndexDir, keyword, pageVo);
log.info("search url iso8859-1,when out is:"+keyword);
}
如果第一次,没有查询到任何结果,很有可能就是“中文乱码”,再转换成正确的字符,再查询一次。我的这种方法,真心不是最好的。但是,我暂时没能尝试出万能的一次性解法,Windows上正常,Linux不正常,很难搞。
只能,通过2次查询来确保,不是由于乱码,查询不到内容。-----------------------------
上面是,14日写的。
今天补充一个“最佳解决方案”:
服务器上修改Tomcat的URIEncoding为UTF-8
对于URL传递中文参数乱码这个问题,其处理方法比较特殊,仅仅转换这个中文字符串或者设置JSP页面显示编码都是不能解决问题的,需要修改Tomcat服务器的配置文件才能解决问题。在这里修改Tomcat的conf目录下的server.xml配置文件,具体改后的代码如下
server.xml
<Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8"
connectionTimeout="20000"
redirectPort="8443" />
在原来代码中添加URI编码设置URIEncoding=“UTF-8”即可,重启Tomcat服务器可以得到正确的页面。其原理也和上面的情况类似,就是向程序指明编码类型,然后显示就正常了。
看这篇文章的时候,想到应该是这个问题。
我一般不喜欢修改Tomcat的配置,喜欢用“默认”的。