国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

深入淺出URL編碼

2019-11-17 03:55:03
字體:
來源:轉載
供稿:網友
雖然是一個老鳥了,在論壇里看到這個關于編碼的帖子時,還是會學習到很多知識,俗語云:溫故而知新,所以轉貼過來以饗讀者。

出處: http://blog.csdn.net/yzhz   楊爭

一、問題:
        編碼問題是java初學者在web開發過程中經常會遇到問題,網上也有大量相關的文章介紹,但其中很多文章并沒有對URL中使用了中文等非ASCII的字符造成服務器后臺程序解析出現亂碼的問題作出準確的解釋和說明。本文將詳細介紹由于在URL中使用了中文等非ASCII的字符造成亂碼的問題。

1、在URL中中文字符通常出現在以下兩個地方:
(1)、Query String中的參數值,比如http://search.china.alibaba.com/search/offer_search.htm?keyWords =中國
(2)、servlet path,比如:http://search.china.alibaba.com/selloffer/ 中國.html


2、出現亂碼問題的原因主要是以下幾方面:
(1)、瀏覽器:我們的客戶端(瀏覽器)本身并沒有遵循URI編碼的規范(http://www.w3.org/International/O-URL-code.html )。
(2)、Servlet服務器:Servlet服務器的沒有正確配置。
(3)、開發人員并不了解Servlet的規范和API的含義。

二、基礎知識:
1、一個http請求經過的幾個環節:
瀏覽器(ie Firefox)【get/post】------------>Servlet服務器------------------------------->瀏覽器顯示
                               編碼                 解碼成unicode,然后將顯示的內容編碼        解碼
(1) 瀏覽器把URL(以及post提交的內容)經過編碼后發送給服務器。
(2) 這里的Servlet服務器實際上指的是由Servlet服務器提供的servlet實現ServletRequestWrapper,不同應用服務器的 servlet實現不同,這些servlet的實現把這些內容解碼轉換為unicode,處理完畢后,然后再把結果(即網頁)編碼返回給瀏覽器。
(3) 瀏覽器按照指定的編碼顯示該網頁。

        當對字符串進行編碼和解碼的時候都涉及到字符集,通常使用的字符集為ISO8859-1、GBK、UTF-8、UNICODE。


2、URL的組成:
域名:端口/contextPath/servletPath/pathInfo?queryString
說明:

1、ContextPath是在Servlet服務器的配置文件中指定的。
對于weblogic:
contextPath是在應用的weblogic.xml中配置。
<context-root>/</context-root>

對于tomcat:
contextPath是在server.xml中配置。
<Context path="/" docBase="D:/server/blog.war" debug="5" reloadable="true" crossContext="true"/>

對于jboos:
contextPath是在應用的jboss-web.xml中配置。
<jboss-web>
    <context-root>/</context-root>
</jboss-web>

2、ServletPath是在應用的web.xml中配置。
<servlet-mapping>
    <servlet-name>Example</servlet-name>
    <url-pattern>/example/*</url-pattern>
</servlet-mapping>

2、Servlet API
我們使用以下servlet API獲得URL的值及參數。
request.getParameter("name");         // 獲得queryString的參數值(來自于get和post),其值經過Servlet服務器URL Decode過的
request.getPathInfo();                // 注意:pathinfo返回的字符串是經過Servlet服務器URL Decode過的。
requestURI = request.getRequestURI(); // 內容為:contextPath/servletPath/pathinfo 瀏覽器提交過來的原始數據,未被Servlet服務器URL Decode過。


3、開發人員必須清楚的servlet規范:
(1) HttpServletRequest.setCharacterEncoding()方法 僅僅只適用于設置post提交的request body的編碼而不是設置get方法提交的queryString的編碼。該方法告訴應用服務器應該采用什么編碼解析post傳過來的內容。很多文章并沒有說明這一點。
(2) HttpServletRequest.getPathInfo()返回的結果是由Servlet服務器解碼(decode)過的。
(3) HttpServletRequest.getRequestURI()返回的字符串沒有被Servlet服務器decoded過。
(4) POST提交的數據是作為request body的一部分。
(5) 網頁的Http頭中ContentType("text/html; charset=GBK")的作用:
   (a) 告訴瀏覽器網頁中數據是什么編碼;
   (b) 表單提交時,通常瀏覽器會根據ContentType指定的charset對表單中的數據編碼,然后發送給服務器的。
   這里需要注意的是:這里所說的ContentType是指http頭的ContentType,而不是在網頁中meta中的ContentType。


三、下面我們分別從瀏覽器和應用服務器來舉例說明:
URL:http://localhost:8080/example/ 中國?name=中國
漢字   編碼      二進制表示
中國   UTF-8     0xe4 0xb8 0xad 0xe5 0x9b 0xbd[-28, -72, -83, -27, -101, -67]
中國   GBK       0xd6 0xd0 0xb9 0xfa[-42, -48, -71, -6]
中國   ISO8859-1 0x3f,0x3f[63, 63]信息失去


(一)、瀏覽器
1、GET方式提交,瀏覽器會對URL進行URL encode,然后發送給服務器。
(1) 對于中文IE,如果在高級選項中選中總以UTF-8發送(默認方式),則PathInfo是URL Encode是按照UTF-8編碼,QueryString是按照GBK編碼。
http://localhost:8080/example/ 中國?name=中國
實際上提交是:
GET /example/%E4%B8%AD%E5%9B%BD?name=%D6%D0%B9%FA

(1) 對于中文IE,如果在高級選項中取消總以UTF-8發送,則PathInfo和QueryString是URL encode按照GBK編碼。
實際上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

(3) 對于中文firefox,則pathInfo和queryString都是URL encode按照GBK編碼。
實際上提交是:
GET /example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

很顯然,不同的瀏覽器以及同一瀏覽器的不同設置,會影響最終URL中PathInfo的編碼。對于中文的IE和FIREFOX都是采用GBK編碼QueryString。

小結:解決方案:
1、URL中如果含有中文等非ASCII字符,則瀏覽器會對它們進行URLEncode。為了避免瀏覽器采用了我們不希望的編碼,所以最好不要在URL中直接使用非ASCII字符,而采用URL Encode編碼過的字符串%.
比如:
URL:http://localhost:8080/example/ 中國?name=中國
建議:
URL:http://localhost:8080/example/%D6%D0%B9%FA?name=%D6%D0%B9%FA

2、我們建議URL中PathInfo和QueryString采用相同的編碼,這樣對服務器端處理的時候會更加簡單。

2、還有一個問題,我發現很多程序員并不明白URL Encode是需要指定字符集的。不明白的人可以看看這篇文檔:http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/net/URLEncoder.html

2、 POST提交
        對于POST方式,表單中的參數值對是通過request body發送給服務器,此時瀏覽器會根據網頁的ContentType("text/html; charset=GBK")中指定的編碼進行對表單中的數據進行編碼,然后發給服務器。
在服務器端的程序中我們可以通過Request.setCharacterEncoding() 設置編碼,然后通過request.getParameter獲得正確的數據。

解決方案:
1、從最簡單,所需代價最小來看,我們對URL以及網頁中的編碼使用統一的編碼對我們來說是比較合適的。
如果不使用統一編碼的話,我們就需要在程序中做一些編碼轉換的事情。這也是我們為什么看到有網絡上大量的資料介紹如何對亂碼進行處理,其中很多解決方案都只是一時的權宜之計,沒有從根本上解決問題。


(二)、Servlet服務器
        Servlet服務器實現的Servlet遇到URL和POST提交的數據中含有%的字符串,它會按照指定的字符集解碼。下面兩個Servlet方法返回的結果都是經過解碼的:
request.getParameter("name");
request.getPathInfo();

這里所說的"指定的字符集"是在應用服務器的配置文件中配置。

(1) tomcat服務器
對于tomcat服務器,該文件是server.xml
<Connector port="8080" PRotocol="HTTP/1.1"
               maxThreads="150" connectionTimeout="20000"
               redirectPort="8443" URIEncoding="GBK"/>
URIEncoding告訴服務器servlet解碼URL時采用的編碼。

<Connector port="8080" ... useBodyEncodingForURI="true" />
useBodyEncodingForURI告訴服務器解碼URL時候需要采用request body指定的編碼。

(2) weblogic服務器
對于weblogic服務器,該文件是weblogic.xml
<input-charset>
  <java-charset-name>GBK</java-charset-name>
</input-charset>

(三)瀏覽器顯示
        瀏覽器根據http頭中的ContentType("text/html; charset=GBK"),指定的字符集來解碼服務器發送過來的字節流。我們可以調用 HttpServletResponse.setContentType()設置http頭的ContentType。

總結:
1、URL中的PathInfo和QueryString字符串的編碼和解碼是由瀏覽器和應用服務器的配置決定的,我們的程序不能設置,不要期望用request.setCharacterEncoding()方法能設置URL中參數值解碼時的字符集。
所以我們建議URL中不要使用中文等非ASCII字符,如果含有非ASCII字符的話要使用URLEncode編碼一下,比如:
http://localhost:8080/example1/example/ 中國
正確的寫法:
http://localhost:8080/example1/example/%E4%B8%AD%E5%9B%BD
并且我們建議URL中不要在PathInfo和QueryString同時使用非ASCII字符,比如
http://localhost:8080/example1/example/ 中國?name=中國
原因很簡單:不同瀏覽器對URL中PathInfo和QueryString編碼時采用的字符集不同,但應用服務器對URL通常會采用相同的字符集來解碼。

2、我們建議URL中的URL Encode編碼的字符集和網頁的contentType的字符集采用相同的字符集,這樣程序的實現就很簡單,不用做復雜的編碼轉換。



本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/yq76034150/archive/2009/12/29/5101882.aspx
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 庐江县| 集安市| 敖汉旗| 肇庆市| 大渡口区| 衡水市| 罗平县| 周宁县| 武功县| 阜平县| 安阳市| 衢州市| 厦门市| 安吉县| 阜城县| 泗水县| 尉犁县| 临沂市| 河源市| 磴口县| 都江堰市| 闵行区| 西充县| 海安县| 黄骅市| 晋江市| 新干县| 衡山县| 盐池县| 林口县| 任丘市| 鹰潭市| 武义县| 连州市| 峨山| 利川市| 达孜县| 乌鲁木齐县| 临邑县| 洪江市| 临邑县|