亂碼根源:跨平台特性與編碼不一致
Java 內部統一使用 Unicode(UTF-16)運算,但輸入/輸出(I/O)邊界卻依賴作業系統預設編碼。J2EE 系統涉及瀏覽器請求、資料庫讀寫、JSP 編譯、檔案讀取等多重 I/O 路徑,若任由各環節按預設編碼處理,亂碼在所難免。
三種統一編碼策略比較
策略一:ISO-8859-1(西歐語系)
- 優勢:Linux、MySQL 等開源軟體預設即此編碼,相容性好
- 劣勢:不支援中文,需將中文轉為雙字節逃逸序列,開發維護極其痛苦
- 適用:純英文系統或 Legacy 系統維護
策略二:GBK(中文擴展)
- 優勢:中文 Windows 原生支援,開發直觀
- 劣勢:破壞跨平台性,Linux 需額外配置 locale,部署遷移極其麻煩
- 適用:僅部署於中文 Windows 環境的內部系統
策略三:UTF-8(推薦,唯一通用解)
UTF-8 相容 ASCII、涵蓋所有語言、無平台限制。核心在於鎖定所有 I/O 邊界:
UTF-8 全鏈路落地清單
- 開發編譯階段:IDE(Eclipse/IDEA)專案編碼設為 UTF-8,`javac -encoding UTF-8`
- Web 請求過濾器:配置 `CharacterEncodingFilter`,核心一行:
request.setCharacterEncoding("UTF-8");
在 `web.xml` 中註冊並映射到 `/*`
- JSP 頁面聲明(雙重保險):
<%@ page contentType="text/html;charset=UTF-8" %>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- 資料庫連線:JDBC URL 附帶參數
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8
(Tomcat `context.xml` 中 `&` 需轉義為 `&`)
- 其他 I/O:檔案讀寫、XML 解析、序列化等均顯式指定 `StandardCharsets.UTF_8`
驗證與避坑指南
- 瀏覽器 Network 面板檢查 `Content-Type` 標頭是否含 `charset=UTF-8`
- 資料庫客戶端執行 `SHOW VARIABLES LIKE 'character_set%';` 確認連線編碼
- 避免使用 `new String(bytes)` 無參建構子,務必指定編碼
- Tomcat 8+ 預設 URI 編碼為 ISO-8859-1,需在 `server.xml` `` 加 `URIEncoding="UTF-8"`
此方案經 Struts、Spring、Hibernate、JSF 等多代框架驗證,真正實現「寫一次,到處跑」的中文無憂體驗。