servlet篇(附)【response、request 的 “亂碼”】

編碼問題總是爲難我小小程序員

1 response 輸出亂碼問題

response 有兩個輸出方法,即 getOutputStream()getWriter()

1.1 調用getOutputStream()方法向瀏覽器輸出數據

當調用 getOutputStream()方法向瀏覽器輸出數據時,該方法可以使用 print() (ServletOutputStream的方法,輸出字符串)或 write()(OutputStream的方法,輸出 byte[]) 執行輸出,下面分別看看它們的使用方法和區別(也可以查看源碼看看兩種方法的實現):

1)print()

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "IO Stream";
		//獲取response的OutputStream流
		ServletOutputStream out = response.getOutputStream();
		//輸出結果顯示到瀏覽器
		out.print(s1);
	}

瀏覽器輸出結果:
在這裏插入圖片描述
成功輸出,貌似沒什麼問題!但試着輸出中文:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "字節輸出流";
		ServletOutputStream out = response.getOutputStream();
		out.print(s1);
	}

結果卻是報了異常:
在這裏插入圖片描述
報異常的原因:OutputStream 輸出二進制數據,print() 方法接收了一箇中文字符串,且 print() 要將中文字符串改爲二進制數據輸出,而 Tomcat 使用 ISO 8859-1編碼使其進行轉換,ISO 8859-1 自身是不能顯示中文的。

2)write()

英文字符是都能正常輸出的,下面就直接試試中文字符:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s1 = "字節輸出流";
		ServletOutputStream out = response.getOutputStream();
		out.write(s1.getBytes());
	}

瀏覽器輸出結果:
在這裏插入圖片描述
正確輸出了。這是因爲 s1.getBytes() 將字符串轉化爲 byte[] 數組後默認的編碼方式是 GB 2312 ;而 GB 2312 支持簡體中文的輸出(print 輸出內容只能是字符串,不能轉化爲 byte[])。

但是,程序要實現通用性,就需要使用 UTF-8 編碼,若是在字節數組中指定使用 UTF-8 編碼,則會出現亂碼:

out.write(s1.getBytes("utf-8"));

在這裏插入圖片描述
亂碼的原因是因爲服務器指定使用 UTF-8 編碼,但瀏覽器顯示往往不是採用 UTF-8 編碼(如 GBK,GB2312等等),這樣就導致亂碼!

解決:http 響應消息有對瀏覽器說明響應數據是什麼類型的響應頭字段,即爲 Content-Type,通過設置 Content-Type 的值即可解決。

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//設置瀏覽器使用 utf-8 編碼顯示數據
		response.setHeader("Content-Type", "text/html;charset=UTF-8");
		//等效
		//response.setContentType("text/html;charset=UTF-8");
		
		String s1 = "字節輸出流";
		ServletOutputStream out = response.getOutputStream();
		out.write(s1.getBytes("utf-8"));
	}

在這裏插入圖片描述

1.2 調用getWriter()方法向瀏覽器輸出數據

PrintWriter 是 Writer 的子類,只能向瀏覽器輸出字符數據,而不能輸出二進制數據。getWriter() 是response 獲取 PrintWriter 對象的方法,同樣,它也可以通過 print()write() 輸出數據到瀏覽器顯示。

PrintWriter 中的 print() 和 write()【多看看源碼】
PrintWriter 中的 print() 方法的實現都是調用 write() 方法,但是 print() 提供了更多的參數類型,write() 輸出字符串,如:

//諸如此類
public void print(Object obj) {
    write(String.valueOf(obj));
}

public void print(String s) {
	if (s == null) {
		s = "null";
	}
    write(s);
}

那麼,就說說 write() 輸出時的編碼問題:

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String s2 = "字符輸出流";
		PrintWriter out = response.getWriter();
		out.write(s2);
	}

在這裏插入圖片描述
又是亂碼!!!!

原因:Tomcat 對瀏覽器進行響應時默認採用 IOS 8859-1 編碼,而這個編碼方式不支持中文。response.setCharacterEncoding("UTF-8") 可以設置 Tomcat 的編碼爲 UTF-8(但需要注意瀏覽器的顯示編碼方式,往往瀏覽器顯示的編碼方式不是 UTF-8 又容易產生亂碼)。

那麼就需要進行設置編碼。設置編碼的方式有很多:設置 Content-Type 頭字段的值,或者輸出標籤模擬消息頭等等。最簡單的可以只通過一個方法 setContentType 就ok。

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//設置編碼(它不僅設置瀏覽器用UTF-8顯示數據,內部還把中文轉碼的碼錶設置成UTF-8了)
		response.setContentType("text/html;charset=UTF-8");
		String s2 = "字符輸出流";
		PrintWriter out = response.getWriter();
		out.write(s2);
	}

在這裏插入圖片描述

2 request 獲取數據亂碼問題

request 對於 POST 和 GET 兩種方式的請求處理中文亂碼的方式有所不同。

2.1 POST 中文亂碼解決

表單:

//前端顯示/提交數據編碼
<meta charset="UTF-8">
....
//post方法提交表單數據
<form action="Test01Servlet" method="post">
		姓名: <input type="text" name="name"><br>
		簡介:<input type="text" name="intro">
		<input type="submit" />
	</form>

提交數據:
在這裏插入圖片描述
後臺獲取數據:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		//設置服務端接收數據編碼(重點)
		request.setCharacterEncoding("utf-8");
		
		String name = request.getParameter("name");
		String intro = request.getParameter("intro");
		
		System.out.println(name);
		System.out.println(intro);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

獲取數據:
在這裏插入圖片描述
request.setCharacterEncoding("utf-8") 語句可解決 post 方式提交表單出現的中文亂碼。若沒有該語句,控制檯打印結果:
在這裏插入圖片描述
這是因爲 Tomcat 默認編碼爲 ISO-8859-1,瀏覽器頁面使用的 UTF-8(<meta charset="UTF-8">);這樣的話,Servlet 讀取數據時自然就得到亂碼,在 post 提交方式下,簡單通過 request.setCharacterEncoding("utf-8") 設置編碼即可解決。

2.1 GET 中文亂碼解決

不僅表單指定的 GET 方式,超鏈接默認也是 GET 提交方式。

先看看 GET 提交數據的方式與 POST 有何不同!

POST提交數據:點擊提交時,數據封裝進了 From Data 中,然後 http 請求將消息主體發送給服務端,此時 request 對象封裝有 http 請求,自然就可以解析 http 中的 From Data 數據,這時只要把request 編碼設置爲 UTF-8 即可
在這裏插入圖片描述
GET提交數據:GET 的數據時通過消息行帶給服務端的,而沒有封裝到 request 對象中,此時,即使設置 request 編碼也不起作用
在這裏插入圖片描述
那麼,GET 方式出現的中文亂碼又怎麼解決???

方法一:將 GET 的數據反向查 ISO 8859-1 編碼(既然它是因爲 ISO 8859-1 而亂碼,就先找到它的未經編碼的原始數據)

//獲取數據(經ISO 8859-1編碼後的字符串,亂碼)
String name = request.getParameter("name");
String intro = request.getParameter("intro");

//亂碼通過反向查ISO 8859-1得到原始的數據	 
byte[] bytename = name.getBytes("ISO8859-1");
byte[] byteintro = intro.getBytes("ISO8859-1");

//對原始的數據,設置編碼,構建字符串	
String name_1 = new String(bytename,"UTF-8");
String intro_1 = new String(byteintro,"UTF-8");

System.out.println(name_1 );
System.out.println(intro_1 );

方法二:除了上面的手工轉換,還可以通過修改 Tomcat 服務器的配置解決服務器在解析數據時造成的中文亂碼

<!-- URIEncoding="utf-8"的增加使得get方法編碼問題得到糾正   -->
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8888" protocol="HTTP/1.1" redirectPort="8443"/>  

這種改法是固定使用 UTF-8 編碼的(過於依賴服務器)

一般來說,能使用 POST 方式提交數據的就用 POST。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章