表單提交中文亂碼是 Web 開發經典坑。本文從 **瀏覽器編碼行為、Tomcat 解析源碼邏輯、Filter 統一處理方案** 三個層面,徹底講透 GET/POST 編碼差異根因,給出生產級解決方案。
| 場景 | 編碼方式 | 說明 |
|---|---|---|
| GET 請求 | URLEncode(頁面編碼) | 參數拼在 URL,編碼取決於頁面 Content-Type charset |
| POST 請求 | URLEncode(頁面編碼) | 參數在 Body,同樣按頁面編碼 |
| AJAX (jQuery) | 強制 UTF-8 | 無論頁面編碼,jQuery 固定用 UTF-8 發送 |
| 地址欄直接輸入 | 瀏覽器自定 | Chrome 用 UTF-8,IE 用 GBK,極不穩定 |
server.xml 配置 <Connector URIEncoding="UTF-8"/>,則用 UTF-8 解碼;String val = request.getParameter("name");
byte[] bytes = val.getBytes("ISO-8859-1");
String real = new String(bytes, "UTF-8");
getParameter() 等方法時才觸發解析;setCharacterEncoding(),默認用 **ISO-8859-1**;request.setCharacterEncoding("UTF-8") **必須在第一次 getParameter 之前調用**,否則無效!@WebServlet("/post")
public class TestPost extends HttpServlet {
protected void service(HttpServletRequest req, HttpServletResponse resp) {
String cmd = req.getParameter("cmd"); // ❌ 先調用 getParameter 觸發解析
list(req, resp);
}
void list(HttpServletRequest req, HttpServletResponse resp) {
req.setCharacterEncoding("utf-8"); // ❌ 已經晚了,解析已完成
String name = req.getParameter("name"); // 亂碼
}
}
@WebFilter("/*")
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);
}
}
getParameter 之前;String name = req.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
response.setCharacterEncoding("UTF-8"); // 自動設置 Content-Type: text/html;charset=UTF-8
response.setContentType("application/json;charset=UTF-8"); // API 場景
亂碼本質是 **編碼/解碼不一致**。POST 請求因 Tomcat 延遲解析特性,**第一次 getParameter 前 setCharacterEncoding** 是鐵律。生產環境**務必用 Filter 全局攔截**,從源頭消除編碼問題,而非靠開發者自覺在每個 Controller 寫第一行代碼。