编程,让人无语的就是,业务逻辑都写好了,什么都弄好了,但是乱码出现了。研究乱码的这一段时间,让我也有了一点点对处理乱码的心得。现在,我来说说我对乱码的看法。
乱码案例
前台-jsp(utf-8):
1 | <form action="相应的action" method="@"><input name="test" value="测试" type="submit"/> |
后台-servlet :
如果@=post:
1
2 doPost(...){System.out.println(request.getparameter("test")); //显示的是???è??,乱码出现
System.out.println(request.getQueryString()); //显示null,无值如果@=get:
1
2 doGet(...){System.out.println(request.getparameter("test")); //显示的是???è??,乱码出现
System.out.println(request.getQueryString()); //显示test=%E6%B5%8B%E8%AF%95,获取到编码后的test
分析问题
由上可以看出几点:
- post提交时,
request.getQueryString()
方法获取不到值,只有get提交才行。 - jsp向后台提交数据,自动进行所设置的编码格式进行编码。因此后台获取的都是编码好的数据,如get提交时,地址栏的显示即可印证:http://10.110.10.11:8080/test1/test?test=%E6%B5%8B%E8%AF%95。
那我就要说道说道了,test传到后台是%E6%B5%8B%E8%AF%95,为什么request.getparameter("test")
获取到的却是???è??呢?
那是因为request方法获取值时,会自动进行一次解码工作,而且是默认的ISO-8859-1(可设置request.setCharacterEncoding(“utf-8”)改变默认的ISO-8859-1)。
乱码解决
那么,如何获取正确格式的数据呢?同样分两种:
如果@=post:
request.setCharacterEncoding(“utf-8”); //输出时显示的是 测试。
如果@=get:
request.setCharacterEncoding(“utf-8”); //输出时显示的仍是 ???è??。
由上可以看出:
- post提交,只需调用getparameter之前,设置
request.setCharacterEncoding("utf-8");
即可避免乱码。post提交因此十分方便,不容易出现乱码,所以我们重点是说说get提交! - get提交,以上方法就然并卵了。那么,如果我们用
java.net.URLDecoder.decode(String,"utf-8");
进行utf-8解码呢?1
System.out.println(java.net.URLDecoder.decode(request.getparameter("test"), "utf-8"));
直接输出结果怎样,结果任然是???è??。为什么呢?因为前面已经说了jsp向后台提交数据自动进行一次编码,而request.getparameter("test")
的方法,会自动做一次解码的工作,因此以上方法进行解码是解码了两次:request解码一次,URLDecoder解码一次!印证该观点很简单:1
2System.out.println(request.getparameter("test")); //输出???è??,进行了一次解码
System.out.println(java.net.URLDecoder.decode("??è??","utf-8")); //输出 ??è??,也看出了当对一个已编码的数据重复解码时,仍然解出的是一样的。
既然都知道了原因,那就知道解决办法了,既然前台编码一次,后台用request.getparameter(“test
“),并设置request解码方式为utf-8在get提交里面行不通,那我们就在前台编码两次呗,而以上URLDecoder解码反正不就是解码了两次么。前台进行第二次编码:
jsp:1
2<!--超链接 href也可以写一个Action,后台web.xml或者Struts.xml能拦截到就行。 对表单的编码,等以后找到方法了再加进来。-->
<a href="test2.jsp?url=<%=java.net.URLEncoder.encode(String,"utf-8")%>">进行编码</a>
js:1
window.open(url+"?name="+encodeURI(encodeURI(document.getElementByName("name").value)));
记住:要想用JS实现jsp的java.net.URLEncoder.encode
必须用两次编码:encodeURI(encodeURI(str));
,因为js不会像jsp一样自动进行一次编码。后台使用System.out.println(java.net.URLDecoder.decode(request.getparameter("test"), "utf-8"));
可以输出”测试”。
其实,像这样前面两次,后面两次的,真的很麻烦。有人问了,还有没有什么简单一点的办法啊?—办法嘛,还是有的,那就是在前台不做任何处理的情况下,后台只需用以下代码即可实现get提交乱码问题(post提交,同样有效):1
2String name =new String(request.getParameter("test").getBytes("iso8859-1"),"utf-8"); //意思就是new一个String,把request解码后的String转换成utf-8。嗯,这个是转换,不是第二次解码了。
System.out.println(name);//输出"测试"
一个完美解决乱码的办法,又有人说了,那你直接拿出最后一个办法就行了嘛,前面说一大堆干嘛,我只想说五个字:让我装个逼! 哈哈,开个玩笑,其实不然,有时我写代码时,发现这个万能办法有时也不管用,后台仍然是乱码,具体是为什么,我也不知道,问题涉及得太高深,我还不懂,只能继续学习强化自己了。还有就是,比如,你用ajax实现异步刷新页面,提交的时候那一定是js提交吧,对于json的编码,你还不是要用到先前的办法。
更多文章,请关注:开猿笔记