Tomcat 處理 GET/POST 請求編碼的機制不同,導致 POST 可通過 Filter 解決,而 GET 需修改 Connector 配置。本文系統梳理亂碼產生原因、分層解決方案與生產環境最佳實踐。
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 編碼請求體ISO-8859-1 解碼 → 亂碼request.getParameter() 前設置 request.setCharacterEncoding("UTF-8")/search?q=中文%E4%B8%AD%E6%96%87ISO-8859-1 解碼查詢字符串 → 亂碼<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value> <!-- 強制覆蓋 request/response 編碼 -->
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Spring Boot 自動配置:spring.mvc.servlet.encoding.enabled=true (默認)、spring.mvc.servlet.encoding.charset=UTF-8、spring.mvc.servlet.encoding.force=true
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
useBodyEncodingForURI="true" />
差異:URIEncoding 直接指定 URL 解碼編碼;useBodyEncodingForURI 使用請求體編碼 (由 Filter 設置) 解碼 URL。推薦 URIEncoding,更顯式、不依賴 Filter 順序。
server:
tomcat:
uri-encoding: UTF-8
# 或 Spring Boot 2.6+ 標準屬性
servlet:
encoding:
charset: UTF-8
force: true
enabled: true
{
connector.setURIEncoding("UTF-8");
// connector.setUseBodyEncodingForURI(true);
});
return factory;
}
修改 server.xml 後重啟項目,配置被重置為默認值。
IDE 使用工作空間元數據管理 Tomcat 配置,而非安裝目錄下的 server.xml。
conf/server.xmlconf/server.xmlapplication.yml 配置,無需碰 server.xml// 前端 jQuery
$.get("/api/search", {q: "中文"}, function(data) {...});
// 即使設置了 URIEncoding="UTF-8",若前端未正確編碼仍會亂碼
// 確保前端:
// 1. 頁面
// 2. $.ajax 默認 UTF-8,無需額外設置
// 3. 若手動拼接 URL:encodeURIComponent("中文") → "%E4%B8%AD%E6%96%87"
# 1. Spring Boot 應用層
spring:
mvc:
servlet:
encoding:
charset: UTF-8
force: true
enabled: true
# 2. 內嵌 Tomcat 連接器
server:
tomcat:
uri-encoding: UTF-8
max-http-header-size: 8192 # 防止長 URL 截斷
# 3. 反向代理 (Nginx) - 關鍵!
# Nginx 必須透傳原始 URL 編碼
location / {
proxy_pass https://backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
# 關鍵:不解碼、不重新編碼
proxy_pass_request_headers on;
}
# 4. 數據庫連接
spring:
datasource:
url: jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
# 5. 頁面/響應
# Spring Boot 默認 response.setContentType("text/html;charset=UTF-8")
# JSP: <%@ page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8" %>
# Thymeleaf: spring.thymeleaf.encoding=UTF-8
/search?q=中文 → 後端正確接收Tomcat GET 亂碼本質是 URL 解析階段編碼不匹配。解決路徑:Spring Filter 處理 POST → Tomcat Connector URIEncoding 處理 GET → Spring Boot application.yml 統一配置 → Nginx 透傳原始編碼。開發環境切記 IDE 管理 Tomcat 配置的特殊性,生產環境建議全鏈路 UTF-8 統一,徹底告別亂碼。