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