四大編碼設定點位與優先級
| 設定方式 | 作用範圍 | 優先級 | 核心功能 |
pageEncoding="UTF-8" | JSP 編譯階段 | 1 (基準) | JSP 檔案讀取編碼;若無 contentType/response 設定,兼作回應編碼 |
contentType="text/html;charset=UTF-8" | HTTP 回應 Header | 2 | 設定 Content-Type Header,瀏覽器據此解碼回應內容 |
response.setCharacterEncoding("UTF-8") | HTTP 回應 Header | 3 (最高) | 程式化設定回應編碼,覆蓋 contentType/pageEncoding |
request.setCharacterEncoding("UTF-8") | HTTP 請求解碼 | - | 設定請求參數解碼編碼(僅 POST 有效,GET 需容器配置) |
編碼鏈路全景圖
【瀏覽器發送請求】
│
├─ URL/GET 參數 → URL Encoding (瀏覽器編碼)
├─ POST 表單 → Request Body Encoding (瀏覽器編碼)
│
▼
【Tomcat 接收】
│
├─ POST → request.setCharacterEncoding() 解碼 (默認 ISO-8859-1)
├─ GET/URL → URIEncoding / useBodyEncodingForURI 解碼
│
▼
【JSP/Servlet 處理】
│
├─ 內部字串 → pageEncoding 讀取 JSP 原始碼
│
▼
【伺服器發送回應】
│
├─ response.setCharacterEncoding() → Content-Type Header
├─ 內容按指定編碼編碼
│
▼
【瀏覽器接收回應】
│
├─ 讀取 Content-Type Header 中 charset
├─ 按該編碼解碼顯示
│
▼
【用戶提交下一請求】 → 循環
瀏覽器編碼行為深度解析
- 接收回應:依據
Content-Type: text/html;charset=UTF-8 中的 charset 解碼。IE 選單「檢視→編碼」顯示即為此值。
- 發送請求:
- URL/GET 參數:瀏覽器按「當前頁面編碼」進行 URL Encoding(%XX 格式)。
- POST 表單:同樣按「當前頁面編碼」編碼 Request Body。
- 實驗證明:
- 百度 (GBK) 搜尋「漢字」 →
%BA%BA%D7%D6
- Google (UTF-8) 搜尋「漢字」 →
%E6%BC%A2%E5%AD%97
- 修改 IE 強制編碼為 GBK 訪問 Google,輸入「漢字」提交 → 發送
%BA%BA%D7%D6,證明瀏覽器編碼決定提交編碼。
Tomcat 5.0 請求解碼具體行為
| 請求類型 | 默認解碼 | 可配置項 | 推薦配置 |
| POST 表單 | ISO-8859-1 | request.setCharacterEncoding() | 在 Filter 中統一設定 UTF-8 |
| GET / URL 參數 | ISO-8859-1 | Connector: URIEncoding、useBodyEncodingForURI | URIEncoding="UTF-8" 或 useBodyEncodingForURI="true"+request 編碼 |
關鍵差異: URIEncoding 強制所有 GET 統一編碼;useBodyEncodingForURI 依賴各頁面 request.setCharacterEncoding(),彈性較大但需確保一致性。
Tomcat server.xml Connector 配置範例
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
useBodyEncodingForURI="true" />
亂碼終極解決方案:統一 UTF-8 全鏈路
- JSP 頁面頭:
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" %>
- 所有 Servlet/JSP:
response.setCharacterEncoding("UTF-8")(或依賴 contentType)。
- 請求解碼 Filter(全局攔截):
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
chain.doFilter(req, resp);
}
}
在 web.xml 映射 /*。
- Tomcat Connector:
URIEncoding="UTF-8" useBodyEncodingForURI="true"。
- 資料庫連線**:JDBC URL 加
?characterEncoding=UTF-8&useUnicode=true(MySQL)。
- 前端頁面**:
<meta charset="UTF-8">(HTML5)或 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">。
- JS/ CSS 檔案**:儲存為 UTF-8 無 BOM。
常見亂碼場景診斷表
| 現象 | 可能原因 | 排查方向 |
| JSP 靜態中文亂碼 | pageEncoding 與檔案實際編碼不符 | 確認編輯器儲存編碼 = pageEncoding |
| POST 表單中文亂碼 | 未設定 request.setCharacterEncoding | 加 Filter 統一設定 |
| GET 參數中文亂碼 | Tomcat 默認 ISO-8859-1 解碼 | 設定 URIEncoding 或 useBodyEncodingForURI |
| 資料庫讀出亂碼 | JDBC 連線未指定 characterEncoding | 檢查連線 URL 參數 |
| 頁面顯示 / | 瀏覽器編碼與回應 Header charset 不符 | 檢查 Content-Type Header、meta 標籤 |
總結
字元編碼問題本質是「編碼與解碼不配對」。建立「UTF-8 全鏈路」標準:檔案儲存 → pageEncoding → contentType → request/response Filter → Tomcat Connector → JDBC URL → 資料庫 → 前端 meta 環環相扣。採用 Filter 統一請求/回應編碼,配置 Tomcat URIEncoding,是徹底根治亂碼的工程化方案。