大家在使用 Java Servlet 開發(fā)網(wǎng)站的時(shí)候經(jīng)常會(huì)遇到中文亂碼問題,不管是請(qǐng)求(request)還是響應(yīng)(response)的過程,本節(jié)我們分別給出對(duì)應(yīng)的解決方案。
在填寫表單數(shù)據(jù)時(shí),難免需要輸入中文,如用戶名和公司名稱等。如果將 servletDemo02 項(xiàng)目中表單頁面的的用戶名輸入為“黑馬程序員”,則提交后控制臺(tái)的顯示將如圖 1 所示。
圖 1 運(yùn)行結(jié)果
從圖 3 中可以看出,當(dāng)輸入的用戶名為中文時(shí),出現(xiàn)了“é??é??...”的亂碼。本節(jié)將介紹如何處理請(qǐng)求參數(shù)中的中文亂碼。
在 HttpServletRequest 接口中提供了一個(gè) setCharacterEncoding() 方法,該方法用于設(shè)置 request 對(duì)象的解碼方式。接下來對(duì) RequestParamsServlet 進(jìn)行修改,在第 7~8 行代碼之間添加如下代碼:
request.setCharacterEncoding("utf-8"); //設(shè)置request對(duì)象的解碼方式
重啟 Tomcat 服務(wù)器,再次輸入中文“黑馬程序員”并提交表單信息后,控制臺(tái)顯示的信息如圖 2 所示。
圖 2 運(yùn)行結(jié)果
需要注意的是,這種解決亂碼的方式只對(duì) POST 方式有效,而對(duì) GET 方式無效。如果將 form.html 文件中 method 屬性的值改為 GET,重新訪問 form.html 頁面并填寫中文信息,則控制臺(tái)依然會(huì)出現(xiàn)如圖 1 所示的亂碼問題。
為了解決 GET 方式提交表單時(shí)出現(xiàn)的中文亂碼問題,可以先使用錯(cuò)誤碼表 ISO-8859-1 將用戶名重新編碼,然后使用碼表 UTF-8 進(jìn)行解碼。再次對(duì) RequestParamsServlet 進(jìn)行修改,在第 9~10 行代碼之間增加一行代碼,如下所示:
name = new String(name.getBytes("iso8859-1"),"utf-8");
重啟 Tomcat 服務(wù)器,再次訪問 form.html 網(wǎng)頁,輸入中文用戶名“黑馬程序員”,這時(shí),控制臺(tái)顯示的信息將不會(huì)出現(xiàn)亂碼。
由于計(jì)算機(jī)中的數(shù)據(jù)都是以二進(jìn)制形式存儲(chǔ)的,因此,當(dāng)傳輸文本數(shù)據(jù)時(shí),會(huì)發(fā)生字符和字節(jié)之間的轉(zhuǎn)換。字符與字節(jié)之間的轉(zhuǎn)換是通過查碼表完成的,將字符轉(zhuǎn)換成字節(jié)的過程稱為編碼,將字節(jié)轉(zhuǎn)換成字符的過程稱為解碼,如果編碼和解碼使用的碼表不一致,則會(huì)導(dǎo)致亂碼問題。下面通過案例演示亂碼問題的產(chǎn)生原因以及解決方式。
在 servletDemo02 項(xiàng)目中新建一個(gè)名稱為 com.mengma.response 的包,在該包中新建一個(gè)名為 ChineseServlet 的類,在類中定義一個(gè)中文字符串,然后使用字符輸出流輸出,如下所示。
package com.mengma.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ChineseServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
String data = "中國";
PrintWriter out = response.getWriter();
out.println(data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
doGet(request, response);
}
}
啟動(dòng) Tomcat 服務(wù)器,在瀏覽器的地址欄中輸入地址 http://localhost:8080/servletDemo02/ChineseServlet 訪問 ChineseServlet,瀏覽器的顯示結(jié)果如圖 3 所示。
圖 3 運(yùn)行結(jié)果
從圖 1 中可以看出,瀏覽器顯示的內(nèi)容是“??”,說明發(fā)生了亂碼。實(shí)際上此處產(chǎn)生亂碼的原因是 response 對(duì)象的字符輸出流在編碼時(shí)采用的字符碼表是 ISO-8859-1,該碼表不兼容中文,會(huì)將“中國”編碼為 63 63(在 ISO-8859-1 的碼表中查不到的字符就會(huì)顯示 63)。當(dāng)瀏覽器對(duì)接收到的數(shù)據(jù)進(jìn)行解碼時(shí),會(huì)采用默認(rèn)的碼表 GB2312,將 63 解碼為?,因此,瀏覽器將“中國”兩個(gè)字符顯示為“??”,具體分析如圖 4 所示。
圖 4 編碼錯(cuò)誤分析
為了解決上述編碼錯(cuò)誤,HttpServletResponse 對(duì)象提供了兩種解決亂碼的方式,具體如下。
第一種方式:
response.setCharacterEncoding("utf-8"); //設(shè)置 HttpServletResponse使用utf-8編碼
response.setHeader("Content-Type", "text/html;charset=utf-8"); //通知瀏覽器使用utf-8解碼
第二種方式:
response.setContentType("text/html;charset=utf-8"); //包含第一種方式的兩個(gè)功能
在通常情況下,為了使代碼更加簡潔,一般會(huì)采用第二種方式。接下來對(duì) ChineseServlet 進(jìn)行修改,在第 7~8 行代碼之間加入第二種方式的代碼,重新啟動(dòng) Tomcat 服務(wù)器并使用瀏覽器訪問 ChineseServlet,瀏覽器顯示出了正確的中文字符,如圖 5 所示。
圖 5 運(yùn)行結(jié)果