表單亂碼是 Java Web 開發高頻痛點,本質是「編碼不一致」。按請求類型、傳輸環節、響應環節劃分六大場景,逐一給出根因與標準修正代碼。
根因:Tomcat 默認用 ISO-8859-1 解碼 URL 中的查詢字符串。
修正:
// 方案 A:Tomcat server.xml 全局生效(推薦)
<Connector port="8080" URIEncoding="UTF-8" />
-- 方案 B:代碼手動轉碼(不推薦,易漏)
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");
根因:容器默認 ISO-8859-1 解碼 Body。
修正(必須在獲取參數前調用):
request.setCharacterEncoding("UTF-8"); // 僅對 POST 有效
String name = request.getParameter("name"); // 正確
本質:超鏈接發起 GET 請求,同場景一。
修正:
URIEncoding=UTF-8(現代瀏覽器自動 URL Encode)。URLEncoder.encode(name, "UTF-8") 拼接鏈接,服務端 URLDecoder.decode。sendRedirect 攜帶中文參數亂碼本質:重定向是 302 + Location Header,瀏覽器發起新 GET 請求,同場景一/三。
修正:
String url = request.getContextPath() + "/target.jsp?name=" + URLEncoder.encode(name, "UTF-8");
response.sendRedirect(url);
現象:中文參數長度為奇數時截斷/亂碼,因雙字節字符編碼邊界處理缺陷。
修正:
根因:response.getWriter() 默認 ISO-8859-1,不支持中文。
修正(在獲取 Writer/Stream 前):
// 方式一:雙重設置(推薦)
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
// 方式二:單行合併(優先級更高)
response.setContentType("text/html;charset=UTF-8"); // 隱含設置 charset
// JSP 頁面指令(編譯時生效)
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
| 層級 | 配置位置 | 關鍵設置 |
|---|---|---|
| 1. 瀏覽器頁面 | HTML <meta> / HTTP Header | charset=UTF-8 |
| 2. JSP 編譯 | page 指令 | pageEncoding=UTF-8, contentType=UTF-8 |
| 3. 請求解碼 | Filter (第一順位) | request.setCharacterEncoding(UTF-8) |
| 4. GET 參數 | Tomcat server.xml | URIEncoding=UTF-8 |
| 5. 響應編碼 | Filter / JSP / Servlet | response.setContentType(text/html;charset=UTF-8) |
| 6. JDBC 連接 | 連接串 / DataSource | characterEncoding=UTF-8 & useUnicode=true |
| 7. 數據庫存儲 | 建庫/建表 | CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
@WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD})
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
req.setCharacterEncoding("UTF-8");
res.setCharacterEncoding("UTF-8");
res.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, res);
}
}
亂碼治理核心:**統一 UTF-8、Filter 前置、Tomcat 容器級修正 GET、數據庫 utf8mb4**。按清單逐項落地,徹底告別亂碼。