1. 程式人生 > >Http協議引數傳遞中編碼問題(Get/Post 方式)

Http協議引數傳遞中編碼問題(Get/Post 方式)

以下內容是我轉載的,覺得挺好的。。。。

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


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/中國?name=�й�

(1) 對於中文IE,如果在高階選項中取消總以UTF-8傳送,則PathInfo和QueryString是URL encode按照GBK編碼。
實際上提交是:
GET /example/�й�?name=�й�

(3) 對於中文firefox,則pathInfo和queryString都是URL encode按照GBK編碼。
實際上提交是:
GET /example/�й�?name=�й�

很顯然,不同的瀏覽器以及同一瀏覽器的不同設定,會影響最終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/�й�?name=�й�

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

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/中國
並且我們建議URL中不要在PathInfo和QueryString同時使用非ASCII字元,比如
http://localhost:8080/example1/example/中國?name=中國
原因很簡單:不同瀏覽器對URL中PathInfo和QueryString編碼時採用的字符集不同,但應用伺服器對URL通常會採用相同的字符集來解碼。

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

相關推薦

Http協議引數傳遞編碼問題Get/Post 方式

以下內容是我轉載的,覺得挺好的。。。。 一、問題:     編碼問題是JAVA初學者在web開發過程中經常會遇到問題,網上也有大量相關的文章介紹,但其中很多文章並沒有對URL中使用了中文等非ASCII的字 符造成伺服器後臺程式解析出現亂碼的問題作出準確的解釋和說明。本文

JAVA——建立HTTP通訊GET/POST方式

建立HTTP通訊(GET/POST方式) 1.要求 此程式可以建立HTTP通訊,以GET方式和POST方式向WEB伺服器提交資訊,並接收WEB伺服器返回的響應。 2.GET和POST請求 GET請求: GET查詢字串(名稱/值對)是在 GET 請求的 U

a標籤跳頁傳參,以及擷取URL引數 js 編碼encode和解碼decode的三種方法

<a href="dd.index?aa=1&&bb=2"></a> //擷取URL引數 // console.log(window.location.search); function GetQueryString(name) { var reg = new Re

Http協議獲取圖片資料流GET方式

String filePath = "http://127.0.0.1/doc/pic.jpg"; byte[] byteArray; HttpURLConnection connection = n

HTTP協議的幾種請求方法get/post 差別17.2.15日更新

【問題的引入】 以前知道HTTP有GET和POST兩種請求方法,並且都見過,但印象裡兩者差不多,可以混著用。最近要進一步研究這個問題,才發現原來的想法不對。 不對有兩點:1,GET和POST區別很大; 2,HTTP有不止這兩種請求方法。 get和post這是http協議的兩種方法,另外還有head, 

Jmeter(二十八) - 從入門到精通 - Jmeter Http協議錄製指令碼工具-Badboy1詳解教程

1.簡介    在使用jmeter自動錄製指令碼時會產生很多無用的請求,所以推薦使用badboy錄製指令碼之後儲存為jmx檔案,在jmeter中開啟使用。因此巨集哥在這裡介紹一下Badboy這款工具,本來打算不做介紹了,原因是因為這款工具已經不在維護和更新了,但是考慮到有些童鞋們不能手擼測試指令碼,

Jmeter(二十九) - 從入門到精通 - Jmeter Http協議錄製指令碼工具-Badboy2詳解教程

1.簡介   上一篇文中已經對Badboy做了一個基本上詳細完整的介紹,這一篇巨集哥帶你們實戰一下,這一篇主要講解和分享:錄製和執行指令碼、引數化 首先讓我們使用N模式錄製一個指令碼,測試用例編號為:1.1.1 成功的釋出僅有文字主題。  2錄製指令碼 1. 建立名為1 Log in的Suite,

Jmeter(三十) - 從入門到精通 - Jmeter Http協議錄製指令碼工具-Badboy3詳解教程

1.簡介   Badboy為方便自動化資料靈活性,以及指令碼的重用,減少工作量;為此提供了指令碼引數化的功能,這一篇文章巨集哥以度娘搜尋的關鍵字“北京-巨集哥”進行引數化為例,巨集哥帶領你們實戰一下如何使用Badboy的引數化功能。 2.指令碼錄製   經過上一篇文章的學習想必大家對B

Jmeter(三十三) - 從入門到精通 - Jmeter Http協議錄製指令碼工具-Badboy6詳解教程

1.簡介   今天分享的就是在上一篇文章的基礎上來進行講解和分享:Badboy使用資料來源Excel進行指令碼引數化。然後在使用讀取的引數進行對比斷言。 2.具體場景   Badboy錄製一個搜尋的指令碼,並對搜尋內容進行斷言,然後將搜尋內容和斷言內容分別引數化,引數不設定具體值,具體的值要從Excel中讀取

flex 通過htmlservices鏈接moss的restrest 的get post方式

obj 顯示調用 路徑更改 tps private url manage param type 一:flex debug(調試)——trace() ——moss導入 flex學習:1、flex出現不能使用trace調試語句的問題,控制臺無信息輸出。這個問題不須要改動

Filter解決全域性亂碼get提交方式

package cn.hsm.web.filter; import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.servlet.Filter; import javax.

動態代理方式來解決全域性亂碼get/post提交

final HttpServletRequest req = (HttpServletRequest) request; // 使用動態代理完成全域性編碼 HttpServletRequest enhanceRequest = (HttpServletRequest) Proxy.new

Webservice06---SOAP訊息的傳遞和處理基於Message方式

使用Message方式傳遞和處理SOAP訊息。 1.1、建立服務 private String wsdlUrlStr = "http://localhost:9999/ns?wsdl"; private String targetNameSpace

VB呼叫WebService直接Post方式並解析返回的XML

Function TodoTaskBySOAP(postURL As String,host As String, n As Integer,FilterItem() As String,OwnerSSICID() As String ,AppID() As String

Http協議及ServletGETPOST提交方式

 Http協議及Servlet中的GET、POST提交方式 本文知識點(目錄): 本文知識點(目錄):     1、什麼是http協議     2、檢視http協議的工具   &

HTTP】請求協議GET/POST和響應協議內容分析

1.請求協議 請求協議的格式如下: 請求首行 請求頭資訊 空行 請求體 最常用的請求就是GET/POST  還有其他 **OPTIONS: 返回伺服器針對特定資源所支援的HTTP請求方法,也可以利用向web伺服器傳送‘*’的

java基礎77 Http協議及ServletGETPOST提交方式

本文知識點(目錄): 1、什麼是http協議     http協議:是對瀏覽器(客戶端)和服務端之間的資料傳輸的格式規範 2、檢視http協議的工具     1)使用火狐--->右擊選擇”檢視元素”/”檢查”--->網路--->點選裡面你的訪問頁面即可顯示(如下圖中的index.jsp)

C/C++函式引數傳遞詳解從記憶體的分析

   昨天看了記憶體管理的有關內容,有一點了解,但不是很深入,發現之前寫程式碼時有很多細節問題沒有注意到,只知道這樣做可以實現功能,卻不知道為什麼可以這樣,對於採用自己的方法造成的隱患也未知,更不曉得還有其他方法可以實現,我們知道C++強大的一個原因是因為對於一個問題的答案多種解答方法或思路,我想著也許就是

HTTP協議狀態碼詳解HTTP Status Code

找不到 work for 條件 暫時 ocs 有效 網絡設備 不同 使用ASP.NET/PHP/JSP 或者javascript都會用到http的不同狀態,一些常見的狀態碼為: 200 – 服務器成功返回網頁 404 – 請求的網頁不存在 503 – 服務不可用 1x

轉載 http協議無狀態的 "狀態" 到底指的是什麽?

logs 登錄 後處理 丟失 分配 使用 而是 這一 訪問者 轉載:http://www.cnblogs.com/bellkosmos/p/5237146.html 引子: 最近在好好了解http,發現對介紹http的第一句話【http協議是無狀態的,無連接的】就無法理解了