JSP 頁面傳遞中文參數到 Servlet,接收到的全是亂碼(如 ????? 或 )。試遍網上方法仍無效,最終發現只需在 Tomcat 配置中加入一行即可解決。
Tomcat 預設使用 ISO-8859-1 解碼 URL 參數。瀏覽器以 UTF-8 編碼發送請求,Tomcat 用 ISO-8859-1 解碼,導致位元組序列錯誤解讀為亂碼。
conf 資料夾server.xml<Connector 標籤(通常在 port="8080" 附近)URIEncoding="UTF-8"
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
URIEncoding 指定 Tomcat 解碼 URL 參數(GET 請求查詢字串、路徑參數)時使用的字元集request.getParameter()、request.getQueryString()、request.getRequestURI() 等雖然 URIEncoding="UTF-8" 解決 GET 請求,但完整專案還需處理 POST、JSP 頁面、資料庫、檔案等編碼:
<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>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Spring 專案直接使用 CharacterEncodingFilter;非 Spring 專案可自寫簡單 Filter:
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) {
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<meta charset="UTF-8">
<!-- 或舊版 -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
// GET 參數手動修正(若無法修改 server.xml)
String param = request.getParameter("name");
if (param != null) {
param = new String(param.getBytes("ISO-8859-1"), "UTF-8");
}
// 表單提交指定編碼
//
// MySQL JDBC URL
jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Taipei
// PostgreSQL
jdbc:postgresql://localhost:5432/mydb?charSet=UTF-8
// 讀取
Files.readAllLines(Paths.get("file.txt"), StandardCharsets.UTF_8);
// 寫入
Files.write(Paths.get("file.txt"), content.getBytes(StandardCharsets.UTF_8));
| 版本 | 預設 URIEncoding | 備註 |
|---|---|---|
| Tomcat 7.0.x | ISO-8859-1 | 需手動加入 URIEncoding="UTF-8" |
| Tomcat 8.0.x | ISO-8859-1 | 同上 |
| Tomcat 8.5+ | UTF-8 | 預設已為 UTF-8,但建議顯式指定 |
| Tomcat 9/10 | UTF-8 | 預設已為 UTF-8 |
// 測試 Servlet
@WebServlet("/test")
public class EncodingTestServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
String name = req.getParameter("name");
resp.setContentType("text/plain;charset=UTF-8");
resp.getWriter().write("接收到參數: " + name);
}
}
瀏覽器訪問:https://localhost:8080/test?name=中文測試
正確顯示:接收到參數: 中文測試
| 誤區 | 正確觀念 |
|---|---|
| 只在 JSP 加 pageEncoding 就夠了 | 只影響 JSP 編譯與輸出,不影響 request 參數解碼 |
| request.setCharacterEncoding("UTF-8") 能修正 GET 亂碼 | 只對 POST 請求體有效,GET 參數在 Filter 執行前已由 Tomcat 解碼 |
| 修改 server.xml 後不用重啟 | 必須重啟 Tomcat 才生效 |
| URIEncoding 影響 POST 請求體 | 不影響,POST 請求體由 request.setCharacterEncoding 或 Filter 控制 |
JSP/Servlet 中文亂碼的核心在於統一編碼鏈路:瀏覽器 → Tomcat (URIEncoding) → Filter (request/response encoding) → JSP (pageEncoding) → HTML (meta charset) → 資料庫 → 檔案。其中 Tomcat 的 URIEncoding="UTF-8" 是解決 GET 請求中文亂碼的關鍵一招,配合全鏈路 UTF-8 設定,徹底杜絕亂碼問題。