javaweb請求編碼 url編碼 響應編碼 亂碼問題 post編碼 get請求編碼 中文亂碼問題 GET POST參數亂碼問題 url亂碼問題 get post請求亂碼 字符編碼

  亂碼是一個常常出現的問題
請求中,參數傳遞的過程當中也是常常出現亂碼的問題
本文主要整理了請求亂碼中的問題以及解決思路
 
先要理解一個概念前提:
編碼就是把圖形變成數值碼因此說:
圖形的字符  ---->  字節數組  是編碼
字節數組-------->圖形的字符 是解碼
 

爲何會亂碼?

計算機數據只能是二進制的
數值類型的數據轉換成二進制很簡單,
但字符類型如何轉換成二進制呢?這就須要使用字符編碼!
在編碼表中,每一個字符都有對應的編碼,編碼是整數,最終在計算機中存儲的是字符的編碼
而不是字符自己(由於計算機數據都是二進制數值,因此字符自己是沒法存儲的)。
 
假如說兩種編碼
紅框1    橘色框 2 ,不用較真數值是多少,符號是什麼,只爲表達概念
每種編碼方式內部,字符和數值是一 一對應的
可是若是使用A------>65進行編碼 
而後使用      65------>$ 另一種解碼方式解讀,顯然A就變成了$,這不就是亂碼了麼
不一樣的編碼方式不一樣,同一個字符的二進制也基本是不一樣的,若是沒有正確的進行解讀,那麼就會出現亂碼問題
發起請求時,不論是什麼字符,計算機都不認識,必須編碼轉換爲數值.
接收到請求的地方想要使用,就必須在編碼成爲字符
亂碼的根本在於 編碼和解碼方式的先後不一致
 

 
如何解決亂碼問題,也就是正確編碼的問題
請求響應的編碼問題

1.直接在地址欄中給出中文

請求數據是由客戶端瀏覽器發送服務器的,請求數據的編碼是由瀏覽器決定的。
例如在瀏覽器地址欄中給出:http://localhost:8080/servlet/AServlet?name=張三,那麼其中「張三」是什麼編碼的呢?
不一樣瀏覽器使用不一樣的編碼,因此這是不肯定的!
Chrome:使用UTF-8;
IE:使用GB2312;
FireFox:使用GB2312;
 
(這幾個說的不必定對,反正重點是要知道,不一樣的瀏覽器,直接地址欄輸入的參數的字符編碼是不固定的,也說不定將來或許會統一)

2. 響應編碼

當使用response.getWriter()來向客戶端發送字符數據時,若是在以前沒有設置編碼,那麼默認使用iso,由於iso不支持中文,必定亂碼
response.getWriter().println("ServletA");

response.getWriter().println("你好");

 

在使用response.getWriter()以前
可使用response.setCharacterEncoding()來設置字符流的編碼爲gbk或utf-8
固然咱們一般會選擇utf-8
response.setCharacterEncoding("utf-8");
這樣使用response.getWriter()發送的字符就是使用utf-8編碼的。但仍是會出現亂碼!
由於瀏覽器並不知道服務器發送過來的是什麼編碼的數據!這時瀏覽器通常會使用gbk來解碼,因此亂碼!
因此須要設置響應的編碼,以及通知瀏覽器應該使用何種編碼方式去解讀
 
在使用response.getWriter()以前
可使用
response.setHeader("Content-type","text/html;charset=utf-8")
來設置響應頭,通知瀏覽器服務器這邊使用的是utf-8編碼
並且在調用setHeader()後
還會自動執行setCharacterEncding()方法。
這樣瀏覽器會使用utf-8解碼,因此就不會亂碼了!
response.setHeader("Content-type","text/html;charset=utf-8");

response.getWriter().println("ServletA");

response.getWriter().println("你好");

 

 
setHeader("Content-Type", "text/html;charset=utf-8")的快捷方法是:
response.setContentType("text/html;charset=utf-8);
總結:輸出響應,想要不亂碼
只須要在使用getWriter()方法前:
response.setContentType("text/html;charset=utf-8);

 
若是是靜態頁面中,使用<meta>來設置content-type響應頭,例如:
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

 


補充說明: 
UTF-8 中  三個字節表示一箇中文
E4BDA0=你  E5A5BD=好  
發送的時候是UTF-8 也就是發送的  E4BDA0E5A5BD
GBK中兩個字節表示一箇中文
也就是
E4BD   A0E5    A5BD
查表可得:

 
 

3.在頁面中發出請求

一般向服務器發送請求數據都須要先請求一個頁面,而後用戶在頁面中輸入數據。
頁面中有超連接和表單,經過超連接和表單就能夠向服務器發送數據了。
用戶在頁面中輸入的數據是由頁面自己的編碼決定的
又由於頁面是服務器發送到客戶端瀏覽器的,因此這個頁面自己的編碼又由服務器響應決定

 

 

 

 
服務器返回當前頁面的響應時,設置響應頭content-type,指定當前頁面的編碼爲utf-8
若是設置了那麼能夠經過瀏覽器查看響應信息看到
若是是
Content-Type:text/html;  而沒有後面的charset=utf-8
能夠看下輸出的響應頁面上是否有這一句,也是同樣的
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
歸根結底是看響應中是否有 Content-type utf-8 的相關信息   有了charset的信息,就按照他來

4.GET請求解讀編碼

 

當客戶端經過GET請求發送數據給服務器時
使用request.getParameter()獲取的數據是被服務器誤認爲ISO-8859-1編碼的
也就是說客戶端發送過來的數據不管是UTF-8仍是GBK,服務器都認爲是ISO-8859-1  
tomcat8之後默認編碼格式是utf-8;7以前的都是iso8859-1
 

是否須要在使用request.getParameter()獲取數據後,再轉發成正確的編碼
要看你實際使用的tomcat 版本
例如客戶端以UTF-8發送的數據,使用tomcat7 以及以前的版本
須要使用以下轉碼方式:html

String name = request.getParameter(「name」);

name = new String(name.getBytes(「iso-8859-1」), 「utf-8」);
重點是要理解邏輯:
 tomcat 默認的使用某種編碼對傳遞過來的數據進行了解碼
 若是說正好是咱們傳遞過來的,那麼不須要作處理
 若是不是,就須要按照他解碼的方式,從新編碼成字符數組,在使用字節數組 按照編碼規則從新解碼爲字符串
 (字符到字節數組是編碼   字節數組到字符是解碼)
 
示例:
在utf8頁面上 get請求  http://127.0.0.1:8080/servlet/ServletA?name=張三
Servlet中
String name = request.getParameter("name");
System.out.println("request.getParameter(\"name\"): "+name);

name = new String(name.getBytes("iso-8859-1"), "utf-8");
System.out.println("new String(name.getBytes(\"iso-8859-1\"), \"utf-8\"): "+name);
頁面是utf8 天然請求是utf8編碼規則
tomcat8  默認utf8  解碼
 
tomcat7 默認iso
固然也是能夠修改Server.xml中設置URIEncoding的值爲UTF-8
可是不建議這麼作,代碼不能依賴tomcat的設置,嚴重破壞可移植性
 
 

5.POST請求解讀編碼

當客戶端經過POST請求發送數據給服務器時,能夠在使用request.getParameter()獲取請求參數以前
先經過request.setCharacterEncoding()來指定編碼,而後再使用reuqest.getParameter()方法來獲取請求參數
那麼就是用指定的編碼來讀取了。
也就是說,若是是POST請求,服務器能夠指定編碼!
但若是沒有指定編碼,那麼仍舊也仍是使用默認的來解讀
request.setCharacterEncoding(「utf-8」);
String name = request.getParameter(「name」);

6. URL編碼

POST表單提交的類型:
Content-Type: application/x-www-form-urlencoded
  • 首先,Content-Type 被指定爲 application/x-www-form-urlencoded;
  • 其次,提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。
  • 大部分服務端語言都對這種方式有很好的支持。
其實就是把中文轉換成%後面跟隨兩位的16進制。
在客戶端和服務器之間傳遞中文時須要把它轉換成網絡適合的方式
不是字符編碼,客戶端與服務器之間傳遞參數用的一種方式
URL編碼須要先指定一種字符編碼,把字符串解碼後,獲得byte[],而後把小於0的字節+256,再轉換成16進制。前面再添加一個%。
* POST請求默認就使用URL編碼!tomcat會自動使用URL解碼!
* URL編碼:String username = URLEncoder.encode(username, "utf-8");
* URL解碼:String username = URLDecoder.decode(username, "utf-8");
 
這種場景下,編碼和解碼都是自動的,不須要手動干預
瀏覽器中顯示的"張三"
新建一個測試類 main方法中執行打印結果同樣
public static void main(String[] args) throws UnsupportedEncodingException {
String s= "張三";
System.out.println(URLEncoder.encode(s,"UTF-8"));
}
相關文章
相關標籤/搜索