日期:2014-05-16  浏览次数:20387 次

jsp之请求参数中的中文读取问题
        HTTP协议规定浏览器向web服务器传递的参数信息中不能出现某些特殊字符,而必须对这些字符进行URL编码后再传递。对于URL中的一些特殊字符,浏览器会自动进行编码。这些字符除了"/?&"等外,还包括unicode字符,比如汉字。这时的编码比较特殊。IE有一个选项"总是使用UTF- 8发送URL",当该选项有效时,IE将会对特殊字符进行UTF-8编码,同时进行URL编码。如果改选项无效,则使用默认编码"GBK",并且不进行 URL编码。但是,对于URL后面的参数,则总是不进行编码,相当于UTF-8选项无效。比如"中文.html?a=中文",当UTF-8选项有效时,将发送链接"%e4%b8%ad%e6%96%87.html?a=x4ex2dx65x87";而UTF-8选项无效时,将发送链接"x4ex2dx65x87.html?a=x4ex2dx65x87"。注意后者前面的"中文"两个字只有4个字节,而前者却有18个字节,这主要时URL编码的原因。
       当web server(tomcat)接收到该链接时,将会进行URL解码,即去掉"%",同时按照ISO8859-1编码(上面已经描述,可以使用URLEncoding来设置成其它编码)识别。上述例子的结果分别是"ue4ub8uadue6u96u87.html?a=u4eu2du65u87"和"u4eu2du65u87.html?a=u4eu2du65u87",注意前者前面的"中文"两个字恢复成了6个字符。这里用"u",表示是unicode。
所以,由于客户端设置的不同,相同的链接,在服务器上得到了不同结果。

2种情况的解决方案:
      1.对于HTTP请求消息的请求行中的URL地址后的参数(get方法提交表单),getParameter等方法进行URL解码时所采用的字符集编码在Servelt规范中没有明确规定,它由各个Servlet引擎厂商自行决定。对于这种情况,Tomcat中的ServletRequest对象的getParameter等方法默认采用ISO8859-1进行解码。        
       ServletRequest接口中定义了一个setCharacterEncoding方法来设置请求消息中的实体内容的字符集编码名称,request.getParameter方法以该方法设置的字符集编码对实体内容进行URL解码。setCharacterEncoding方法来设置的字符集只影响getParameter方法对POST过来的内容进行URL解码的结果,而不能影响URL地址后的参数进行URL解码的结果,所以及时使用setCharacterEncoding方法来设置请求消息中的实体内容的字符集编码名称也不管用
      解决方案:
         a)在Tomcat配置中,连接器(HTTP Connector)属性中有一个URIEncoding和useBodyEncodingForURI属性,这两个属性设置对URL后的附加参数进行URL解码时该如何选择字符集编码。URIEncoding用于制定URL后的附加参数的字符集编码,useBodyEncodingForURI则说明是否采用实体内容的字符集编码设置来替代URIEncoding的设置,也就是说当useBodyEncodingForURI属性设置为true时,ServletRequest.setCharacterEncoding方法设置的字符集编码也影响getParameter等方法对URL地址后的参数进行URL解码的结果。(在/%TomCat_Home%/
conf\server.xml文件中找到标记,然后在后面加上useBodyEncodingForURI=true)
         b)前面我们讲到,即使IE选项"总是使用UTF- 8发送URL"被选中,URL后面的参数也不会进行编码,所以URL后面的中文参数最好还是手动进行URL编码。可以采用java.net.URLEncoder.encode()方法进行编码,然后浏览器中所显示出来的就是一堆百分号之类的字符,见例子

MyJsp.jsp
<body>
   <%
   String name = "米兰,我爱你";
   //name = java.net.URLEncoder.encode(name,"utf-8");
    %>
    <a href="<%=request.getContextPath()%>/jsp/compactInfo/jsp1.jsp?name=<%=name%>">中文参数请求</a>
  </body>


jsp1.jsp
<body>
   <%
     String name = request.getParameter("name");
     name = java.net.URLDecoder.decode(name,"utf-8");
    // name = new String(name.getBytes("iso8859-1"),"utf-8");
    %>
    收到中文参数:<%=name %>
  </body>


2.对于post方式下的"application/x-www-form-urlencoded"编码格式的实体内容,getParameter等方法以ServletRequest对象的getCharacterEncoding()方法返回的字符集对其进行URL解码。如果getCharacterEncoding()方法返回null,则采用ISO8859-1