get中文乱码

项目里面写了一个window.location.href=''"。参数中带有中文时,服务器收到的是乱码。开始以为是框架动了,spring security哪里设置了编码,后来发现只是因为get和post的区别,以前都是全部用post,没有注意到这个问题。

http://www.jb51.net/web/12714.html

这篇文章介绍的不错。

结论是全部使用post。

我认为,get的存在还是自有他的道理,Post这里不提,对于get方式:

1:不可以设置tomcat  connector的编码方式,应该使用默认的iso-8859-1,原因下面讲。

2:程序可以控制的办法是,js里面使用<%UrlEncoder.encode(mbName,"gbk")%>显式指定编码方式编码。在java端同样要用一次UrlDecoder.decode(mbName,"gbk")解码。

3:因为浏览器用户可以直接在地址栏输入url,而不经过js,所以get方式不能完全避免乱码,除非在服务器接收数据时特意判断出浏览器使用的编码方式,是utf8还是gbk。

对于中文字符浏览器和tomcat的编码解码方式:

这里只说get。post上面的文章里面有讲到,很简单。

1:浏览器分两步,先使用浏览器默认的编码格式,用UrlEncoder转为%形式,我的火狐是25.0.1最新版,设置默认编码格式在 选项->内容->高级->后备字符编码。比如‘张’,UTF8得到的是三位,%E5%BC%A0,GBK或者GB2312得到的是两位,%D5%C5;然后将这些常规字符转为字节码在互联网传输,转换格式有人说是iso-8859-1,总之这一步对应的tomcat解析过程使用的编码是一致的,无法自定义的。

2:tomcat分两步,与浏览器相逆,第一步得到包含%的url。这一步是确定无疑的。

第二部将%解码为中文,乱码都是出现在这一个环节。设置tomcat的connector编码也是改变这一个环节的解码方式。

3:如果tomcat设置为utf8,这时浏览器设置为gbk的话,java是没有办法解码还原出中文字符的!如果tomcat设置为gbk,浏览器为utf8时,同样无法解码。原因是一个占3位,一个占2位,造成一位多余或者缺失变成?,这个?还原不了!而只有iso-8859-1不会丢失!tomcat默认是iso-8859-1。

贴上代码,有点乱。

package com.huateng.net;

import java.net.URLDecoder;
import java.net.URLEncoder;

public class EncoderTest{

	public static void main(String[] args) throws Exception {
		String name = "张";
		//请求url 为 ...?mbName=张
		//浏览器使用utf-8对中文编码
		String utf8EncoderName = URLEncoder.encode(name,"utf-8");
		System.out.println(utf8EncoderName);//%E5%BC%A0
		
		//请求url实际变为 ...?mbName=%E5%BC%A0
		//将url编码为字节码传到tomcat服务端
		//tomcat将字节码解码为url
		//这里对于字节码的编码解码方式两者必然一致,无法自定义
		
		//tomcat接受到的url为...?mbName=%E5%BC%A0,与浏览器端必然一致,与编码格式无关
		
		//tomcat做完字节码解码以后,还要做一步url中%字符的解码。乱码发生在这一步
		//tomcat默认使用iso-8859-1对url中非ascii字符解码
		
		String isoDecoderName = URLDecoder.decode(utf8EncoderName,"iso-8859-1");//tomcat默认解码出的name
		System.out.println(isoDecoderName);//??
		String defaultDecoderName = URLDecoder.decode(utf8EncoderName);//eclipse默认解码出的name
		System.out.println(defaultDecoderName);//寮?
		//说明eclipse默认是gbk的解码方式。'寮'在gbk或者gbk2312中占两个字节,%E5%BC,正好是'张'的前两个字节
		String utf8DecoderName = URLDecoder.decode(utf8EncoderName,"utf-8");
		System.out.println(utf8DecoderName);//张
		//---------------------------------------------------------------------------
		
		//在servlet端接收到的数据,及处理
		name = defaultDecoderName;//寮?
		System.out.println(URLEncoder.encode(name,"gbk"));//%E5%BC%3F
		//gbk最后一个字符丢失,数据变错。使用utf-8编码的字符,如果用gbk解码会丢失、错误
		System.out.println(URLEncoder.encode(name)+","+URLEncoder.encode(name,"utf-8"));//%E5%BC%3F,%E5%AF%AE%EF%BF%BD
		
		System.out.println(URLEncoder.encode(isoDecoderName,"iso-8859-1"));//%E5%BC%A0
		//iso方式不会丢失,可以还原。tomcat默认是iso
		System.out.println("----------------------------------------------------------------------------");
		
		System.out.println(new String(name));//寮?
		System.out.println(new String(name.getBytes("gbk"),"utf-8"));//??
		System.out.println(new String(isoDecoderName.getBytes("iso-8859-1")));//寮? 
		//说明先用iso编码为初始的字节码,然后用默认的gbk解码
		System.out.println(new String(isoDecoderName.getBytes("iso-8859-1"),"utf-8"));//张  正确写法
		
		
		/**
		 * 所以,浏览器使用utf8编码的字符,可以使用iso解码,不能使用gbk
		 * isoDecoderName是tomcat默认解码出的name,使用iso解码,解码完成为乱码,但是可以用Encoder还原
		 * 还原为初始的%形式,然后再使用utf8解码出正确字符
		 * defaultDecoderName是eclipse默认解码出的name,使用gbk解码,解码完成也是乱码,但是还原后造成字节丢失
		 * 丢失后无法使用utf8解码
		 */
		
		/**
		 * 浏览器是utf8。如果服务器用iso,取得的值是iso对其解码出的乱码,对于这个乱码可以还原重新解码
		 * 但是如果服务器使用gbk,取得的值依然是乱码,对于这个乱码就无法还原了。因为utf8占3字节,gbk只取2字节,
		 * 剩下的1字节被处理为?,还原时?变为固定不变的%3F。
		 */
		
		//---------------------------------------------------------------
		//浏览器使用gbk编码
		name = "张";
		String gbkEncoderName = URLEncoder.encode(name,"gbk");
		System.out.println(gbkEncoderName);//%D5%C5
		
		isoDecoderName = URLDecoder.decode(gbkEncoderName,"iso-8859-1");//tomcat默认解码出的name
		System.out.println(isoDecoderName);//??
		String gbkDecoderName = URLDecoder.decode(gbkEncoderName);
		System.out.println(gbkDecoderName);//张
		utf8DecoderName = URLDecoder.decode(gbkEncoderName,"utf-8");
		System.out.println(utf8DecoderName);//??
		
		//-------------------------------还原------------------------------------
		System.out.println(URLEncoder.encode(isoDecoderName,"iso-8859-1"));//%D5%C5
		System.out.println(URLEncoder.encode(utf8DecoderName,"utf-8"));//%EF%BF%BD%EF%BF%BD
		//实际上,任何字这里都会打印出%EF%BF%BD%EF%BF%BD。因为?在utf8中是%EF%BF%BD
		System.out.println(new String(isoDecoderName.getBytes("iso-8859-1"),"gbk"));//张
		System.out.println(new String(utf8DecoderName.getBytes("utf-8"),"gbk"));//锟斤拷
		System.out.println(new String(utf8DecoderName.getBytes("utf-8"),"utf-8"));//??
		
		/***
		 * 所以,浏览器使用gbk时,服务器也不能使用utf8。iso是通用的。
		 */
	}
}




猜你喜欢

转载自blog.csdn.net/u010653311/article/details/17038423