`
yiminghe
  • 浏览: 1430204 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

web 编码问题

    博客分类:
  • java
阅读更多

关于编码解码问题的看法与解释

首先注意:

规范规定网络中传输都是二进制编码的,这里所说的编码只是将字符编码为二进制传输到服务器,具体解析仍要依靠服务器,可能不同的二进制流最终会解析出相同的字符 (经过字符解码与 url 解码).

form 讨论:

form post:

当使用 form post 时,浏览器负责将 form 元素按照页面的编码(中文或特殊字符)转换成 %xx%xx%xx 的形式,传给 server,jsp 按照自己服务器的设置(filter setcharacterencoding 或 ( 采用浏览器传过来的charset , ie不会传charset ) 进行解码。request.getParameter() -> 得到我们希望的数据 。

form get:

form get 浏览器负责将 form 元素按照页面的编码(中文或特殊字符) 转换成%xx%xx%xx 的形式,传给 server  jsp 按照自己服务器的设置(tomcat

< Connector   port = "8080"   protocol = "HTTP/1.1"   maxThreads = "150" connectionTimeout = "20000"   redirectPort = "8443"   URIEncoding = "xxxx" / > ) 解码,注意 setCharacterEncoding 对 get 不管用,并且设置 charset 也不管用,ajax get 验证的。

ajax 讨论:

ajax post:

     如果 js 对于非 ascii 字符没有 encodeURIComponent ,那么浏览器直接给服务器 utf8(key=字),utf8表示字符串的 utf-8 的编码,服务器不能正常解析。

     如果 js 对于非 ascii 字符进行了 encodeURIComponent , 则浏览器直接给服务器  key=%YY%YY%YY(YYYYYY 为一个中文字的utf-8编码),并且该web应用的编码filter的ignore配置参数设置为true(表示采用客户端传过来的编码),jsp  应用浏览器传过来的charset 进行解码。request.getParameter() -> 得到我们希望的数据。

    至于 "Content-Type","application/x-www-form-urlencoded;charset:xxx" 也会影响 web server 端 的参数解析,也要设置.

Content-Type

设置 content-type : application/x-www-form-urlencoded;charset=gbk.

chrome,safari 即使设了 charset 不为 utf-8 也不管用,还是在发送时被改为 UTF-8

firefox:

chrome:



ie 虽然不会自动改,但是仍然会以 utf-8 发送数据

ie,chrome,firefox 具体字节流例子

 

默认配置 post "q=我"

 

请求体字节流为  71 3d e6 88 91 ,其中 e6 88 91 为 `我` 的 utf-8 编码,不经过 urlencode 直接传给了服务器

 

ajax get :

charset 设不设一样,相当于 ajax post 没有设 charset,服务器不管charset 属性,直接按照按照自己服务器的设置(tomcat

< Connector   port = "8080"   protocol = "HTTP/1.1"   maxThreads = "150" connectionTimeout = "20000"   redirectPort = "8443"   URIEncoding = "xxxx" /> 

)解码。

 

 

如果 get 时参数不 js encodeURIComponent ,则浏览器按照系统编码就行url发送,如果设置了总是以 utf-8 发送,则会将参数按照其utf-8编码发送.

 

 

 

具体发送字节流和浏览器设置有关,例如

 

ie

默认配置 get "http://xx.com/?q=我"

 

字节流为  71 3d ce d2 ,其中 ce d2 为 `我` 的 gbk 编码,ie 不经过 urlencode 直接传给了服务器

 

 

chrome

 

默认配置 get "http://xx.com/?q=我"

 

字节流为 71 3d 25 43 45 25 44 32 ,代表字符为 q=%CE%D2 ,chrome 在发送字节流前对非 ascii 码字符进行了 gbk urlencode (直接 ?q=%CE%D2 则不会被编码)

 

firefox

默认配置 get "http://xx.com/?q=我"

 

字节流为 71 3d ..... ,代表字符为 q=%E6%88%91 ,firefox 在发送字节流前对非 ascii 码字符进行了 utf-8 urlencode (直接 ?q=%E6%88%91 则不会被编码) 

 

 

服务器解码

 

get

 

s1. 服务端首先根据设置的编码从网络字节流中解析出单个的字符的集合

 

s2. 然后再根据同一编码进行 urldecode 得出真正的值.

 

post

 

s1. 服务端首先根据固定的 utf-8 编码从网络字节流中解析出单个的字符的集合

 

s2. 然后再根据 filter 设置的编码(或者根据请求头 charset)进行 urldecode 得出真正的值.

 

直接地址栏输入中文区别

 

这里部分浏览器的 ajax get 又和直接往地址栏输中文不同:

 

ie

 

直接地址栏输入 q=我 和 ie ajax get 保持一致

 

chrome

 

字节流为 71 3d ..... ,代表字符为 q=%E6%88%91 ,chrome 在发送字节流前对非 ascii 码字符进行了 utf-8 urlencode (直接 ?q=%E6%88%91 则不会被编码) 

 

firefox

 

字节流为 71 3d 25 43 45 25 44 32 ,代表字符为 q=%CE%D2 ,firefox 在发送字节流前对非 ascii 码字符进行了 gbk urlencode (直接 ?q=%CE%D2 则不会被编码)

 

 

firefox ,chrome 与 ajax get 时恰好颠倒了!

 

ajax get post 区别总结

get 时:部分浏览器(chrome,firefox)会在发送前对非 ascii 字符自动进行urlencode,但是编码格式不定。

 

post 时:所有浏览器发送前都不会自动 urlencode,直接发送字符的 utf-8 字符编码作为二进制流给服务器

 

注意:

 

典型国内浏览器直接 www.xx.com/?1=我 和 www.xx.com/?1=%ce%d2 对于设置了 uriencoding="gbk" 的tomcat 来说都会得到正确的结果,但是处理浏览浏览不一样

 

c1. www.xx.com/?1=我: 查询串发送的字节流为 31 3d ce d2

 

c2. www.xx.com/?1=%ce%d2 : 查询串发送的字节流为 31 3d 25 63 65 25 64 32

 

对于 c1 ,服务器在s1 步已经处理完毕,s2 则是什么都不做

对于 c2 ,服务器则主要是在 s2 才得到真正的值.

 

总结:

只要将 web 应用的配置文件中编码filter的参数配置 ignore 设为 true,每次ajax请求设置charset = utf-8,则不会出现乱码问题了。

PS:客户端解码问题

客户端根据服务器端传送的 content-type 响应头的 charset 对服务器返回数据进行解码,当返回 json 时更简单的做法是服务器端直接对中文数据进行 unicode 转换,统一转换为 "\uxxxx" 的形式,客户端 js 由于内存中数据统一为 unicode 表示,则客户端拿到 json 对象就可以直接操作了。



实验代码 (tomcat 默认设置)

 

ps2:客户端的编码函数

javascript中存在几种对URL字符串进行编码的方法:escape(),encodeURI(),以及encodeURIComponent()。这几种编码所起的作用各不相同。

 

 

escape() deprecated

 

采用 ISO Latin 字符集对指定的字符串进行编码。所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。比如,空格符对应的编码是%20。
不会被此方法编码的字符: @ * / +


encodeURI() :

 

把 URI 字符串的指定字符采用 UTF-8 编码格式转化成 escape 格式的字符串。
不会被此方法编码的字符:! @ # $& * ( ) = : / ; ? + '


encodeURIComponent() :

 

把 URI 字符串中的指定字符采用 UTF-8 编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码,比如 / 等字符。所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。
不会被此方法编码的字符:! * ( ) '

因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面的charset是一致的时候),只需要使用 escape。如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用encodeURI或者encodeURIComponent。

另外,encodeURI/encodeURIComponent是在javascript1.5之后引进的,escape则在javascript1.0版本就有。

  • 大小: 12.6 KB
  • 大小: 9.8 KB
  • 大小: 6.8 KB
  • 大小: 18.2 KB
分享到:
评论
1 楼 xwqiang 2013-08-08  
a.jsp:
<%@  page language="Java" import="java.util.*"%>
<%@page contentType="text/html;charset=UTF-8"%>
<form action= "CodingServlet">
name:<input type='text' name='name' value="中文"/>
<input type='submit' value="提交">


CodingServlet:
String name = request.getParameter("name");
System.out.println(name);
name = new String(name.getBytes("ISO-8859-1"),"UTF-8");
System.out.println(name);
request.getRequestDispatcher("b.jsp").forward(request, response);

b.jsp:
<%@page language="Java" import="java.util.*" pageEncoding="UTF-8"%>
<%@page contentType="text/html;charset=UTF-8"%>
<%
String name = request.getParameter("name");
%>

<body>
name:<%=name%>
</body>

tomcat设置为默认,两个sysout第一个是乱码 ,第二个正常。问题:为什么页面b.jsp输出(name:中文)是乱码?

浏览器显示response的header为:Content-Type:text/html;charset=UTF-8

相关推荐

Global site tag (gtag.js) - Google Analytics