文档章节

web开发中的中文编码问题

littleatp
 littleatp
发布于 2015/03/28 20:15
字数 1862
阅读 6
收藏 0

一、发起http请求时的字符编码方式通常有两种:

   1  以某种编码直接发送字符,比如发送“飞”的gbk编码,程序如果以Latin1(iso-8859-1)字符集去识别它,将得到”难读“的字符信息:"·É"

        要转换为正常的字符需要如下处理:

String correct = new String(word.getBytes("iso-8859-1"),"gbk");    //word为上述的难读的latin1字符串

 

   2  以某种编码如GBK进行Base64编码的转换,如"飞"字符以GBK进行Base64转换可得:"%B7%C9";以UTF-8进行Base64转换得:”%E9%A3%9E“

       要转换为正常的字符需要如下处理:

 

String correct = URLDecoder.decode(word, "gbk");       //如果是utf-8转来的则使用utf-8

 

二、而通过浏览器发起http请求通常有以下几种行为:

  1  在浏览器地址栏输入地址进行访问
  2  页面表单的get和post提交
  3  页面超链接
  4  ajax异步请求

其中ajax异步请求的编码方式可由javascript控制,此处不再讨论。

对于其他的三种行为,不同的浏览器的编码处理方式并不一致,以下以IE和Firefox进行比较分析:

浏览器:IE8.0 和 Firefox6.0

web服务器:tomcat 6.0.18(本文的服务器都采用tomcat来描述,适用的版本是5.x、6.x)

测试方式:分别以地址栏输入、页面超链接、表单的get/post几种不同的请求行为去访问web服务器,通过web服务器的access_log来查看中文数据的编码方式。

测试的中文请求数据:http://localhost:8083/struts/飞?word=飞(uri部分为/struts/飞、参数部分为word=飞)

html页面:分别有GBK编码和UTF8编码的页面两个(除了页面编码外,其他内容一致)

 

 

 1 <html>
 2 <head>
 3 <meta http-equiv="Content-Type" content="text/html; charset=gbk">  <!-- 指定页面编码 -->
 4 </head>
 5 <body>
 6 <hr/>
 7 <center>
 8   <form action="http://localhost:8083/struts/飞"  method="get">     <!-- 表单get方式发起请求 -->
 9   get表单:
10   <input name="word" type="text" value="飞"/>
11   <input type="submit" value="submit"/>
12   </form>
13 <hr/>
14    <a href="http://localhost:8083/struts/飞?word=飞">页面超链接</a>   <!-- 超链接方式发起请求-->
15 <hr/>
16  <form action="http://localhost:8083/struts/飞"  method="post">       <!-- 表单post方式发起请求 -->
17   post表单:
18   <input name="input" type="text" value="飞"/>
19   <input type="submit" value="submit"/>
20   </form>
21 </center>
22 </body>
23 </html>
View Code

IE测试结果:

IE浏览器有一个高级选项:是否以UTF8发送URL。该选项对于请求数据的编码有一些影响。

请求方式        access_log(开启以UTF8发送URL的高级选项)                      access_log(不开启...)                                          
地址栏输入 "GET /struts/%E9%A3%9E?word=·É HTTP/1.1" 200 "GET /struts/%B7%C9?word=·É HTTP/1.1"
GBK页面超链接        ”GET /struts/%E9%A3%9E?word=·É HTTP/1.1" 200 "GET /struts/%B7%C9?word=·É HTTP/1.1" 200
GBK页面表单GET方式          "GET /struts/%E9%A3%9E?word=%B7%C9 HTTP/1.1" 500   "GET /struts/%B7%C9?word=%B7%C9 HTTP/1.1" 500
GBK页面表单POST方式 "POST /struts/%E9%A3%9E HTTP/1.1" 500 "POST /struts/%B7%C9 HTTP/1.1" 500
UTF8页面超链接 "GET /struts/%E9%A3%9E?word=·É HTTP/1.1" 200 "GET /struts/%B7%C9?word=·É HTTP/1.1" 200
UTF8页面表单GET方式 "GET /struts/%E9%A3%9E?word=%E9%A3%9E HTTP/1.1" 500 "GET /struts/%B7%C9?word=%E9%A3%9E HTTP/1.1" 500
UTF8页面表单POST方式 "POST /struts/%E9%A3%9E HTTP/1.1" 500 "POST /struts/%B7%C9 HTTP/1.1" 500







 

Firefox测试结果:

请求方式 access_log
地址栏输入 "GET /struts/%E9%A3%9E?word=%B7%C9 HTTP/1.1" 200       
GBK页面超链接 "GET /struts/%E9%A3%9E?word=%B7%C9 HTTP/1.1"
GBK页面表单GET方式 "GET /struts/%E9%A3%9E?word=%B7%C9 HTTP/1.1" 500
GBK页面表单POST方式        "POST /struts/%E9%A3%9E HTTP/1.1" 500
UTF8页面超链接 "GET /struts/%E9%A3%9E?word=%E9%A3%9E HTTP/1.1" 200
UTF8页面表单GET方式 "GET /struts/%E9%A3%9E?word=%E9%A3%9E HTTP/1.1" 500
UTF8页面表单POST方式 "POST /struts/%E9%A3%9E HTTP/1.1" 500


 

 

 

 

 

 

注:由表单POST方式发起的请求中参数数据被包含在请求的body体中,因此在access_log的uri中看不到参数部分的数据。但可以肯定表单POST行为的编码方式是以页面编码转Base64的方式。

access_log的编码说明

”%B7%C9“为"飞“的GBK转Base64形式;

%E9%A3%9E”为"飞"的UTF-8转Base64形式;

·É”为“飞"的GBK编码形式(使用Latin1字符集去识别GBK编码所得的字符串)


结果分析:

1 IE 对于uri部分的编码与“是否开启UTF8发送URL”的高级选项相关,如果开启,则一律使用UTF8转Base64的编码;否则使用GBK转Base64的编码。

        对于参数部分的编码:

        A. 地址栏输入与页面超链接的处理一致,都直接使用GBK编码直接发送;

        B. 页面表单Get和Post,使用页面编码转Base64编码。

2 Firefox 对于uri部分的编码一律采用UTF8转Base64编码的方式;

                对于参数部分的编码:

        A. 地址栏输入使用GBK转Base64编码;

        B. 页面表单Get和Post,以及超链接都使用页面编码转Base64编码的方式。


三、web服务器端的编码处理:

对于URI部分的编码设置,tomcat服务器在Server.xml里面做如下配置:

URIEncoding="UTF-8"  <!-- 该设置负责将URI部分进行反转义,相当于调用URIDecoder.decode(uri,"utf-8") -->

 

 

对于表单POST提交(附在请求Body体中)的的参数,需要对HttpServletRequest对象进行编码设置:

request.setCharacterEncoding("utf-8");   //负责将参数进行反转义,相当于调用URIDecoder.decode(uri,"utf-8")

而对于超链接、表单Get、地址栏访问形式提交请求的参数(附在URI中),则一般由上述的URIEncoding来确定编码转义;也可以使其与POST参数的处理一致,这需要在Server.xml做如下配置:

useBodyEncodingForURI="true"

 

以上所述的编码设置都是针对某种编码(如UTF-8)转Base64的请求编码的,对于直接用某种编码发送请求参数的情况却无能为力(如上面案例中IE直接用GBK编码直接发送参数)。为了能处理这样的数据,需要在程序中手工转换:

String word = request.getParameter("word");
word = new String(word.getBytes("iso-8859-1"),"gbk");   
//传输的GBK编码被tomcat服务器以latin1字符集进行识别,成为latin1字符串,在URI转义过程中未被改变(不符合%xxx的转义形式),于是从request对象取得的是latin1字符串,因此可以做如此转换。

 

 

四、采用统一、可靠的编码方案:

        经过上面的一系列分析,得一些总结的方案:

        1   URI部分不要含有中文字符,因为IE和Firefox的转义编码可能是不一致的。

        2   超链接参数部分不要含有中文,因为IE会直接发送GBK编码的参数,在后台需要另外处理,而Firefox则以页面编码做Base64转义...

        3   统一页面编码,推荐使用UTF-8(因其更加国际化);

        4   表单Get和Post允许含有中文参数,web服务器将Get和Post参数的编码处理设置为一致:useBodyEncodingForURI=“true"

             此外使用过滤器(或其他统一的方式)对HttpServletRequest对象进行编码设置如:request.setCharacterEncoding("utf-8");

        5   以Ajax进行交互的情况下,中文参数也使用页面统一的编码进行Base64转义发送。

 

原文地址:http://blog.csdn.net/littleatp2008/article/details/6767062

© 著作权归作者所有

共有 人打赏支持
littleatp
粉丝 1
博文 5
码字总数 8891
作品 0
广州
程序员
使用request.getParameter(“参数名”)取网页中输入值的中文乱码解决方法

在Java 开发中,如果框架搭建的不完善或者初学者在学习过程中,出现中文乱码是经常的事儿(哈。谁让发明Java语言的不是中国人呢) 今天跟大家分享几个解决java Web开发中,request.getParame...

zwtestsky
2016/11/25
0
0
IntelliJ IDEA 控制台中文乱码

2.2. 系统语言:中文 先说明一下如果系统语言设置为中文是没有乱码问题的,所以网上大量的重复文章的办法是把"File Encoding"设置为GBK或者GB2312,但是很多系统的编码不可能因为一个IDE而更...

xjt2016
2016/09/13
17
0
java web中中文乱码问题汇总

[关于使用java 进行的javaweb开发时候的中文乱码的解决方法][1] [1]: http://blog.sina.com.cn/s/blog_6cadcce70101ep77.html 如下是其中的内容: 1,jsp页面中文乱码解决办法:文件头部定义...

小老傅
2014/03/07
0
0
在开发WEB应用中,资源文件的转码问题

我们一般开发WEB应用的时候,使用的编码都是UTF8的 而为了国际化(虽然大部分时间都用不到),我们的中文都是存放到资源文件中 但不能进接存放,需要将中文转成Unicode编码后才可以 而英文却...

puras
2010/10/29
179
7
让Tomcat支持中文路径名和中文文件名

让Tomcat支持中文路径名和中文文件名关键字: Tomcat 中文 中文文件名 下载 列出目录 Tomcat是Java开发者使用得较多的一个Web服务器,因为它占用资源小,运行速度快等特点,深受Java Web程序员...

enzozhong
2013/07/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

函数调用约定 (cdecl stdcall)

函数调用约定 (cdecl stdcall) 在 C 语言里,我们通过阅读函数声明,就知道怎么携带参数去调用函数,也能在函数体定义内使用这些参数。但是 CPU 并不直接完成函数调用的传参操作,这需要人为...

傅易
5分钟前
0
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a=b...

代码打碟手
7分钟前
0
0
mysql5.7 修改datadir

mysql 的默认存储路径为 /var/lib/mysql ,修改后为 /data/mysql 关闭服务 service mysql stop 复制mysql 数据文件到新的目录 cp -rp /var/lib/mysql /data 查看原目录的权限,如果新目...

hotsmile
24分钟前
0
0
证书安装指引之Tomcat 证书部署

Tomcat 证书部署 0 申请证书 1 获取证书 如果申请证书时有填写私钥密码,下载可获得Tomcat文件夹,其中有密钥库 www.domain.com.jks; 如果没有填写私钥密码,证书下载包的Tomcat文件夹中包括...

吴伟祥
28分钟前
0
0
ConcurrentHashMap1.7和1.8的底层不同实现

1.Hashmap和HashTable在线程安全方面的优劣? Hashmap多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。 Hash...

刘祖鹏
44分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部