web编程乱码问题总结

从业很多年了,乱码问题还是经常以不同面孔出现,今天花了一下午时间归纳整理和实验,希望大家少浪费时间在这个英语国家根本碰不到的问题上。

关键字:tomcat , 转码 ,乱码,ecsape,


测试工具:

get方法直接在浏览器地址栏敲入

post方法是用一个html页面,代码如下:

<html>
<head><meta content="text/html; charset=UTF-8" http-equiv="content-type"></head>
<form action="http://localhost:8080/teacher/deskapp/html/login.do?action=index" method="post">
    <input type="text" value="您好" name="userid">
    <input type="submit" value="submit">
</form>
</html>


情况1
tomcat  <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"  URIEncoding="UTF-8"/>
无任何过滤和转码机制
请求如下
http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=你好&pwd=a
http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=%E4%BD%A0%E5%A5%BD2&pwd=a (把你好用decodeURIComponent 转码utf-8)
得到的userid值:你好


情况2
tomcat  <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"  />
无任何过滤和转码机制
直接得到httpReq.getParameter("userid")值:乱码
使用new String(userid.getBytes("iso-8859-1"),"UTF-8");  得到:你好
因为(不指定URIEncoding默认为 ISO-8859-1  ),和UTF-8不兼容。

情况3
tomcat  <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"  />
使用utf-8过滤器
使用get方法传递userid,得到的还是乱码,除非用使用new String(userid.getBytes("iso-8859-1"),"UTF-8")转一下得到正常值
使用post方法传递userid,得到正常结果

情况4
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>
使用utf-8过滤器
使用get方法 传递userid=%E4%BD%A0%E5%A5%BD2
使用post方法传递userid=你好
直接得到httpReq.getParameter("userid")值:你好。


原因说明1--tomcat和服务端的最佳实践 :

在 tomcat4之前 get 与 post 的编码是一样的,所以只要在过滤器中通过 request.setCharacterEncoding 设定一次就可以解决 get 与 post 的问题
在 tomcat5 中,get 与 post 的处理是分开进行的,对 get 的处理通过Connector的 URIEncoding属性 进行处理,对 post 的内容依然通过 request.setCharacterEncoding 处理
在 tomcat5 中 将Connector的 useBodyEncodingForURI属性 设定为真后,就可以通过 request.setCharacterEncoding 一起直接解决 get 和 post 的编码
所以推荐使用情况4 useBodyEncodingForURI属性+统一过滤器。

resin服务器貌似不区分get和url统一使用使用一下配置来指定 

<web-app id='/'>         <character-encoding>UTF-8</character-encoding>...</web-app>



原因说明2--浏览器端的最佳实践:
在第4中情况下是用ie
地址栏中敲入http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=%E4%BD%A0%E5%A5%BD2&pwd=a 结果页面还是这个参数
服务端得到你好。
地址栏中敲入http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=你好&pwd=a结果页面还是这个参数
服务端接收到的是乱码

因为ie  URL后面的参数是不编码发送的,


但是chrome和firefox则
无论地址栏敲入http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=你好&pwd=a
还是http://localhost:8080/teacher/deskapp/html/login.do?action=index&userid=%E4%BD%A0%E5%A5%BD2&pwd=a
最终结果页面的地址栏都是显示为汉字你好。
服务端得到你好。
通过http监视工具看到这两个浏览器实际向服务器发送的是 userid=%E4%BD%A0%E5%A5%BD2

使用post方式传递无论ie,firefox都可以正常显示
网页中的表单使用POST方法提交时,数据内容的类型是 application/x-www-form-urlencoded,

所以,推荐使用post方式传递汉字字符串,这样ie和其他浏览器都不用特殊处理了。
如果使用js传递参数则都要使用encodeURI 或者 encodeURIComponent来处理。jquery的get方法中的参数都处理过才发往服务器。



说明3--转码的由来:
 web设计者面临的众多难题之一便是怎样处理不同操作系统间的差异性。这些差异性能引起URL方面的问题:例如,一些操作系统允许文件名中含有空格符,有些又不允许。大多数操作系统不会认为文件名中含有符号“#”会有什么特殊含义;但是在一个URL中,符号“#”表示该文件名已经结束,后面会紧跟一个fragment(部分)标识符。其他的特殊字符,非字母数字字符集,它们在URL或另一个操作系统上都有其特殊的含义,表述着相似的问题。为了解决这些问题,我们在URL中使用的字符就必须是一个ASCII字符集的固定字集中的元素,具体如下:
  1.大写字母A-Z
  2.小写字母a-z
  3.数字 0-9
  4.标点符 - _ . ! ~ * ' (和 ,)

ActionScirpt3或者javascript中的
trace(escape("你好"));
trace(encodeURI("你好#"))
trace(encodeURIComponent("你好#"));
结果如下
%u4F60%u597D
%E4%BD%A0%E5%A5%BD#
%E4%BD%A0%E5%A5%BD%23

escape                   使用操作系统默认编码形式,其中某些字符被替换一个“%”后面跟着两位16进制的数值。ECMAScript v3 反对使用该方法,应用使用 decodeURI() 和 decodeURIComponent() 替代它。
encodeURI(a)             使用UTF-8,对a中的特殊字符例如 # 和 /不会转化掉,适于处理整个uri
encodeURIComponent       使用UTF-8,对a中的特殊字符例如 # 和 / 会转化掉 ,适于处理uri中的一个参数的值

escape使用了平台的默认编码形式,得到%xx。这些编码形式典型的有:在 U.S. Unix 系统上的ISO-8859-1, 在U.S. Windows 系统上的Cp1252,在U.S. Macs上的MacRoman,和其他本地字符集等。因为编码解码过程都是与本地操作平台相关的,所以这些方法是令人不爽的,不能跨平台的。
不要使用escape


参考--以上除实验外都是从以下文章中获取的经验:
http://hi.baidu.com/hou_shaojun/item/b85d2e12cea9b407b98a1af6
http://blog.163.com/huangwei913@126/blog/static/232632222012013739238/
http://tech.sina.com.cn/s/2008-07-07/1053722241.shtml
 









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值