Servlet 亂碼本質是瀏覽器、伺服器、應用程式三方編碼不一致導致。理解 HTTP 請求結構是解決問題的關鍵:
在 service()、doGet() 或 doPost() 方法最開頭設置:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 設置請求編碼(解決請求體亂碼)
req.setCharacterEncoding("UTF-8");
// 2. 設置響應編碼(解決響應體亂碼)
resp.setCharacterEncoding("UTF-8");
// 3. 設置響應 Content-Type 告知瀏覽器編碼(關鍵!)
resp.setContentType("text/html;charset=UTF-8");
// 後續業務邏輯...
String param = req.getParameter("name"); // 正確獲取中文參數
}
GET 參數在 URL 中,Tomcat 預設用 ISO-8859-1 解碼,需雙重處理:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
URIEncoding="UTF-8" 讓 Tomcat 直接用 UTF-8 解碼 URL,最徹底。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
useBodyEncodingForURI="true" />
讓 URL 編碼跟隨請求體編碼(由 req.setCharacterEncoding() 決定)。
// 獲取原始參數(ISO-8859-1 解碼後的錯誤字串)
String wrong = req.getParameter("name");
// 手動轉回 bytes 再用正確編碼解碼
String correct = new String(wrong.getBytes("ISO-8859-1"), "UTF-8");
function submitForm() {
// 關鍵:encodeURIComponent 進行 UTF-8 編碼
var name = encodeURIComponent("大家好");
window.location.href = "UserServlet?uname=zhangsan&realname=" + name;
}
對應後端 req.getParameter("realname") 即可正確獲取。
| 層級 | 配置項 | 建議值 |
|---|---|---|
| IDE/編輯器 | 檔案編碼 | UTF-8 |
| Java 源碼 | 編譯編碼 | javac -encoding UTF-8 |
| 資料庫 | 字符集/排序規則 | utf8mb4 / utf8mb4_unicode_ci |
| 連線池 | 連線 URL 參數 | characterEncoding=utf8&useUnicode=true |
| Tomcat | URIEncoding | UTF-8 |
| JSP | pageEncoding | UTF-8 |
| HTML | meta charset | UTF-8 |
| JS | 發送前編碼 | encodeURIComponent() |
return; 防止後續代碼繼續執行導致重複跳轉或異常