关于get传递参数乱码及长度为奇数时最后一个字符乱码的问题

JSP中文传参数乱码问题。

如果是post加过滤器或者加入

request.setCharacterEncode("gbk")(管输入)
response.setCharacterEncode("gbk")(管输出)

 

如果是url的get提交参数带中文的
可以改下面这个文件,加入一个URIEncoding="GBK"
X:\Tomcat \conf\Server.xml 
 

Xml代码
  1. <Connector    
  2.         port="8080"    
  3.         redirectPort="8443"    
  4.         minSpareThreads="25"    
  5.         connectionTimeout="30"    
  6.         maxThreads="150"    
  7.         maxSpareThreads="75"    
  8. URIEncoding="GBK">   

一、概况:ie7正常,ie6参数就会出现中文接受信息错误,表现为长度是奇数时最后一个字符出现乱码。

二、具体表现:

1、全是汉字时,无论奇数还是偶数,都无乱码。

2、如果是英文中文混合,并且英文字符数是奇数时,就会出现最后有一个“?”号。

3、如果是英文中文混合,并且英文字符数是偶数时,无乱码。

三、原因:ie7支持UTF8编码,但是ie6支持不好。

环境: jdk1.5,tomcat5.5,ie6.0 ,所有jsp页面,xml配置文件URIEncoding 都设置成utf-8,也保存成utf-8格式。

当用ie提交时,单个汉字会出现这个问题。(如果所有的都设置成gbk,则不会出现此问题)

开始以为是tomcat源码问题,通过跟踪tomcat,调试 tomcat org.apache.coyote.http11.Http11BaseProtocol.java可知:

如果输入单汉字“你”->tomcat的侦听的byte流应该时:%E4%BD%A0,而实际收到的是 %E4%BD,第3个byte没有收到。

而同样的配置,如果用firefox1.5测试,则完全正常。!!!!!

所以,这个是ie发送信息时转码错误!!



四、解决方法:

1、用post发送,这个方法当然不出错了,但是,有时候必须用get传递参数的方法,那就没辙了,只能用第二个方法。

2、习惯把中文字符串显示长度设置为偶数。

现在的处理逻辑是:在业务方法里进行判断,如果输入的字符个数为奇数,则给其拼接上一个全角的空格,如果是半角的空格,也还是会有乱码问题。
当你要传值时,故意在汉字结尾处加一个半角字符,比如:

index.jsp?name=我爱你_

我要传的是“我爱你”,但是我故意加一个“_”在后面。

然后在servlet里接收时,用substring()去掉这个“_”:

String name = request.getParameter("name");
name = name.substring(0, name.length()-1);

 

 

 

在网页中的超链接,例如 <a href="/servlet?id=1&name=世界">click me</a>,如果超链接里的地址有中文就如上面的'name=世界'一样,即使在web.xml中设置转换字符集的filter,在servlet中得到的值还是乱码。下面是我的几个实验,

(1) 首先,在web.xml中没有字符集转换的filter下,在表单中提交中文的情况,HTML片段如下

Html代码 复制代码  收藏代码
  1. <form action="./servlet/MyServlet" method="get">  
  2.         <input type="text" name="name">  
  3.         <input type="submit">  
  4. </form>  
Html代码 复制代码  收藏代码
  1. <form action="./servlet/MyServlet" method="get">  
  2.         <input type="text" name="name">  
  3.         <input type="submit">  
  4. </form>  
<form action="./servlet/MyServlet" method="get">

    	<input type="text" name="name">

    	<input type="submit">

</form>

在文本框中输入'世界', 毫无疑问这个时候在servlet中得到的name的值是乱码 例如:name = ????

(2)现在再把form中的method方法换成post并且仍然是在web.xml中没有字符集转换的filter下,看在表单中提交中文会不会有乱码,HTML片段如下

Html代码 复制代码  收藏代码
  1. <form action="./servlet/MyServlet" method="post">  
  2.         <input type="text" name="name">  
  3.         <input type="submit">  
  4. </form>  
Html代码 复制代码  收藏代码
  1. <form action="./servlet/MyServlet" method="post">  
  2.         <input type="text" name="name">  
  3.         <input type="submit">  
  4. </form>  
<form action="./servlet/MyServlet" method="post">

    	<input type="text" name="name">

    	<input type="submit">

</form>

 在文本框中输入'世界', 这个时候在servlet中得到的name的值仍然是乱码 例如:name = ????

(3)现在在web.xml中加入字符集转换的filter,代码如下

Xml代码 复制代码  收藏代码
  1. <filter>  
  2.         <filter-name>Set Character Encoding</filter-name>  
  3.         <filter-class>filters.SetCharacterEncodingFilter</filter-class>  
  4.         <init-param>  
  5.             <param-name>encoding</param-name>  
  6.             <param-value>GBK</param-value>  
  7.         </init-param>  
  8.     </filter>  
  9.        
  10.     <filter-mapping>  
  11.         <filter-name>Set Character Encoding</filter-name>  
  12.         <url-pattern>/*</url-pattern>  
  13.     </filter-mapping>  
Xml代码 复制代码  收藏代码
  1. <filter>  
  2.         <filter-name>Set Character Encoding</filter-name>  
  3.         <filter-class>filters.SetCharacterEncodingFilter</filter-class>  
  4.         <init-param>  
  5.             <param-name>encoding</param-name>  
  6.             <param-value>GBK</param-value>  
  7.         </init-param>  
  8.     </filter>  
  9.        
  10.     <filter-mapping>  
  11.         <filter-name>Set Character Encoding</filter-name>  
  12.         <url-pattern>/*</url-pattern>  
  13.     </filter-mapping>  
<filter>

        <filter-name>Set Character Encoding</filter-name>

        <filter-class>filters.SetCharacterEncodingFilter</filter-class>

        <init-param>

            <param-name>encoding</param-name>

            <param-value>GBK</param-value>

        </init-param>

    </filter>

    

    <filter-mapping>

        <filter-name>Set Character Encoding</filter-name>

        <url-pattern>/*</url-pattern>

    </filter-mapping>

(4)现在咱们还是现在form的method属性是get时候进行测试,在文本框中输入世界,然后在servlet中得到的name值仍然是乱码,name = ????

(5)然后再在form的method属性是post时候进行测试,在文本框中输入世界,然后在servlet中得到的name值就是正常的值的没有乱码。

我现在用的浏览器是IE,就是表单提交中文时候,如果正确的设置了字符集转换的filter,那么在form中的post方法中提交时,在servlet中得到的正常的值,如果在form中的get方法中提交时候,得到的中文数据居然是乱码,这个有点不可思议。

(6)然后在同样的环境下,在超链接的href属性中提交中文参数值,例如

Html代码 复制代码  收藏代码
  1. <a href='./servlet/MyServlet?name=世界>click me</a> <br>  
Html代码 复制代码  收藏代码
  1. <a href='./servlet/MyServlet?name=世界>click me</a> <br>  
<a href='./servlet/MyServlet?name=世界>click me</a> <br>

 在servlet中得到的是乱码。在这种情况下在servlet中进行转码。例如,

Java代码 复制代码  收藏代码
  1. try {   
  2.      name = new String(name.getBytes("ISO-8859-1"), "gbk");   
  3. catch(Exception e) {   
  4.      e.printStackTrace();   
  5. }  
Java代码 复制代码  收藏代码
  1. try {   
  2.      name = new String(name.getBytes("ISO-8859-1"), "gbk");   
  3. catch(Exception e) {   
  4.      e.printStackTrace();   
  5. }  
try {

     name = new String(name.getBytes("ISO-8859-1"), "gbk");

} catch(Exception e) {

     e.printStackTrace();

}

 或者

java.net.URLDecoder.decode(name) 通过这个语句进行转码也是可以得到正常值的。

(7)同样是在有字符集转换的filter下,在JSP中使用JSTL的 <c:url>标签是否可以避免乱码吗,使用如下的标签

Html代码 复制代码  收藏代码
  1. <c:url value="./servlet/MyServlet" var="url">  
  2.         <c:param name="name" value="${'世界'}" />  
  3. </c:url>  
  4.        
  5. <a href="${url}">Hello</a> <br>  
Html代码 复制代码  收藏代码
  1. <c:url value="./servlet/MyServlet" var="url">  
  2.         <c:param name="name" value="${'世界'}" />  
  3. </c:url>  
  4.        
  5. <a href="${url}">Hello</a> <br>  
<c:url value="./servlet/MyServlet" var="url">

    	<c:param name="name" value="${'世界'}" />

</c:url>

    

<a href="${url}">Hello</a> <br>

 然后在servlet中得到的仍然是乱码,仍然需要(6)中介绍的方法进行转换,才能得到正确的值。

(8)通过post方法提交的表单中的中文值是不需要通过(6)中的进行转码的,如果进行转码的话,反而会造成乱码。那么,在serlvet中,如果让这两种提交方式(超链接提交和表单post方法)都通用的话,如果超链接的值没有中文的话是可以实现通用的,如果超链接提交的参数有中文的话,就会出现问题,那么就必须在超链接提交的URL中另加一个额外的参数来标识是从哪里提交的,以此来决定是否需要对特定的值进行转化。有没有更好的办法在超链接里提交中文时候在servlet中不进行转码呢。答案就是(5)。如果把超链接提交转化为表单的post提交,中文就不会出现乱码,见(9)

(9)

Js代码 复制代码  收藏代码
  1. function linkClick(linkObject) {   
  2.                
  3.     var formObject = document.createElement('form');   
  4.     document.body.appendChild(formObject);   
  5.      formObject.setAttribute('method''post');   
  6.      var url = linkObject.href;   
  7.      var uri = '';   
  8.      var i = url.indexOf('?');   
  9.                
  10.      if(i == -1) {   
  11.         formObject.action = url;   
  12.      } else {   
  13.         formObject.action = url.substring(0, i);   
  14.      }   
  15.                
  16.      if( i >= 0 && url.length >= i + 1) {   
  17.         uri = url.substring(i + 1, url.length);   
  18.      }   
  19.   
  20.      var sa = uri.split('&');   
  21.                
  22.      for(var i = 0; i < sa.length; i++) {   
  23.        var isa = sa[i].split('=');         
  24.        var inputObject = document.createElement('input');   
  25.        inputObject.setAttribute('type''hidden');   
  26.        inputObject.setAttribute('name', isa[0]);   
  27.        inputObject.setAttribute('value', isa[1]);   
  28.        formObject.appendChild(inputObject);   
  29.      }   
  30.                
  31.      formObject.submit();   
  32.                
  33.      return false;   
  34. }  
Js代码 复制代码  收藏代码
  1. function linkClick(linkObject) {   
  2.                
  3.     var formObject = document.createElement('form');   
  4.     document.body.appendChild(formObject);   
  5.      formObject.setAttribute('method''post');   
  6.      var url = linkObject.href;   
  7.      var uri = '';   
  8.      var i = url.indexOf('?');   
  9.                
  10.      if(i == -1) {   
  11.         formObject.action = url;   
  12.      } else {   
  13.         formObject.action = url.substring(0, i);   
  14.      }   
  15.                
  16.      if( i >= 0 && url.length >= i + 1) {   
  17.         uri = url.substring(i + 1, url.length);   
  18.      }   
  19.   
  20.      var sa = uri.split('&');   
  21.                
  22.      for(var i = 0; i < sa.length; i++) {   
  23.        var isa = sa[i].split('=');         
  24.        var inputObject = document.createElement('input');   
  25.        inputObject.setAttribute('type''hidden');   
  26.        inputObject.setAttribute('name', isa[0]);   
  27.        inputObject.setAttribute('value', isa[1]);   
  28.        formObject.appendChild(inputObject);   
  29.      }   
  30.                
  31.      formObject.submit();   
  32.                
  33.      return false;   
  34. }  
function linkClick(linkObject) {

			

    var formObject = document.createElement('form');

    document.body.appendChild(formObject);

     formObject.setAttribute('method', 'post');

     var url = linkObject.href;

     var uri = '';

     var i = url.indexOf('?');

			

     if(i == -1) {

        formObject.action = url;

     } else {

        formObject.action = url.substring(0, i);

     }

			

     if( i >= 0 && url.length >= i + 1) {

        uri = url.substring(i + 1, url.length);

     }



     var sa = uri.split('&');

			

     for(var i = 0; i < sa.length; i++) {

       var isa = sa[i].split('=');		

       var inputObject = document.createElement('input');

       inputObject.setAttribute('type', 'hidden');

       inputObject.setAttribute('name', isa[0]);

       inputObject.setAttribute('value', isa[1]);

       formObject.appendChild(inputObject);

     }

			

     formObject.submit();

			

     return false;

}

 下面是html代码

 

Html代码 复制代码  收藏代码
  1. <a href='./servlet/MyServlet?name=世界&id=1' onclick="return linkClick(this)">click me</a> <br>  
Html代码 复制代码  收藏代码
  1. <a href='./servlet/MyServlet?name=世界&id=1' onclick="return linkClick(this)">click me</a> <br>  
<a href='./servlet/MyServlet?name=世界&id=1' onclick="return linkClick(this)">click me</a> <br>

 这样就OK了,在linkClick方法里面会自己创建一个表单,然后会去解析你的参数并自动转化成hidden,并给hidden域赋值,这样,再也不怕提交中文参数,并且也不需要在servlet中进行麻烦的转码,真是一劳永逸啊,但是需要在JSP的超链接中加上上面的方法。上面的程序用的是IE6和tomcat5。

 

 

1.统一用UTF-8编码,即Tomcat的server.xml、页面、过滤器都用UTF-8
2.
请求参数,需要编码

<a href="newsAction?name=<%=java.net.URLEncoder.encode("表数据管理","UTF-8")%>"
target="frameset">Xls表数据管理 </a>

假如是java代码的话直接写java.net.URLEncoder.encode("测试吗","UTF-8");

下面引用Qieqie的一段代码:

Java代码 复制代码  收藏代码
  1. public static void main(String[] args) throws UnsupportedEncodingException {   
  2.     //给定某3个汉字   
  3.     String src = "你好啊";   
  4.     //String src = "一二三";   
  5.        
  6.     //浏览器进行utf-8编码,并传送到服务器   
  7.     byte[] bytes1 = src.getBytes("utf-8");   
  8.     System.out.println(bytes1.length);//9   
  9.        
  10.     //tomcat以gbk方式解码(这个片段的说明仅针对gbk处理汉字的情况)   
  11.     //如果一对汉字字节不符合gbk编码规范,则每个字节使用'?'(ascii 63)代替   
  12.     //万幸的话,只是最后一个(第9个)字节因不能成对,变成问号(比如当src="你好啊"时)   
  13.     //不幸的话,中间某些字节就通不过gbk编码规范出现'?'了(比如当src="一二三"时)   
  14.     //总之temp的最后一位必定是问号'?'   
  15.     String temp = new String(bytes1, "gbk");    
  16.        
  17.     //你的action中的代码   
  18.     //由于以上的tomcat以gbk解释utf-8不能成功   
  19.     //所以此时bytes2和bytes1不一样   
  20.     byte[] bytes2 = temp.getBytes("gbk");   
  21.     System.out.println(bytes2.length);   
  22.     for (int i = 0; i < bytes1.length; i++) {   
  23.         System.out.print(bytes1[i] & 0xff);   
  24.         System.out.print("\t");   
  25.     }   
  26.     System.out.println();   
  27.     for (int i = 0; i < bytes2.length; i++) {   
  28.         System.out.print(bytes2[i] & 0xff);   
  29.         System.out.print("\t");   
  30.     }   
  31.     System.out.println();   
  32.   
  33.     //构建出来的dest自然不是原先的src   
  34.     String dest = new String(bytes2, "utf-8");   
  35.     System.out.println(dest);   
  36.        
  37. }  

你可能感兴趣的:(传递参数)