`
guoyiqi
  • 浏览: 967543 次
社区版块
存档分类
最新评论

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

    博客分类:
  • jsp
 
阅读更多

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>  
<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>  
<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>  
<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>  
<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. }  
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>  
<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. }  
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>  
<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的一段代码:

	public static void main(String[] args) throws UnsupportedEncodingException {
		//给定某3个汉字
		String src = "你好啊";
		//String src = "一二三";
		
		//浏览器进行utf-8编码,并传送到服务器
		byte[] bytes1 = src.getBytes("utf-8");
		System.out.println(bytes1.length);//9
		
		//tomcat以gbk方式解码(这个片段的说明仅针对gbk处理汉字的情况)
		//如果一对汉字字节不符合gbk编码规范,则每个字节使用'?'(ascii 63)代替
		//万幸的话,只是最后一个(第9个)字节因不能成对,变成问号(比如当src="你好啊"时)
		//不幸的话,中间某些字节就通不过gbk编码规范出现'?'了(比如当src="一二三"时)
		//总之temp的最后一位必定是问号'?'
		String temp = new String(bytes1, "gbk"); 
		
		//你的action中的代码
		//由于以上的tomcat以gbk解释utf-8不能成功
		//所以此时bytes2和bytes1不一样
		byte[] bytes2 = temp.getBytes("gbk");
		System.out.println(bytes2.length);
		for (int i = 0; i < bytes1.length; i++) {
			System.out.print(bytes1[i] & 0xff);
			System.out.print("\t");
		}
		System.out.println();
		for (int i = 0; i < bytes2.length; i++) {
			System.out.print(bytes2[i] & 0xff);
			System.out.print("\t");
		}
		System.out.println();

		//构建出来的dest自然不是原先的src
		String dest = new String(bytes2, "utf-8");
		System.out.println(dest);
		
	}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics