首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

URL 傳遞中文參數亂碼終極解決方案:編碼協議、Tomcat 配置與 Java 代碼三層防線

     編輯:Java 相關知識

問題根源

URL 中文亂碼本質是「瀏覽器編碼 → 服務端解碼」不一致導致的字節序列錯誤解讀。涉及三個關鍵環節:

  1. 瀏覽器發送:GET 請求 URL 編碼方式取決於頁面編碼 (HTML meta charset) 與瀏覽器實現。
  2. 服務端接收:Tomcat 默認用 ISO-8859-1 解碼 URL 路徑與查詢字符串。
  3. 應用代碼讀取:request.getParameter() 直接使用容器解碼結果。

三層防線徹底解決

第一層:Tomcat 容器配置 (server.xml)

強制指定 URI 解碼字符集,一勞永逸。

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"
           useBodyEncodingForURI="true" />
  • URIEncoding="UTF-8":告訴 Tomcat 用 UTF-8 解碼 URL (含查詢字符串)。
  • useBodyEncodingForURI="true":若請求體有編碼 (POST),則用該編碼解碼 URI (兼容舊應用)。

第二層:Filter 統一編碼 (推薦 Spring 框架內置)

@WebFilter("/*")
public class EncodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        chain.doFilter(req, resp);
    }
}

作用:覆蓋 POST 請求體編碼,確保 request.getParameter() 正確讀取 Body 參數。

第三層:Java 代碼手動轉碼 (補救/特殊場景)

若無法修改容器配置 (如虛擬主機),可在代碼中手動修正:

// GET 參數修正
String raw = request.getParameter("name"); // 已被 ISO-8859-1 錯誤解碼
String correct = new String(raw.getBytes("ISO-8859-1"), "UTF-8");

// 通用工具方法
public static String decodeParam(String param, HttpServletRequest request) {
    if (param == null) return null;
    String enc = request.getCharacterEncoding();
    if (enc == null) enc = "ISO-8859-1";
    try {
        return new String(param.getBytes(enc), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return param; // 兜底
    }
}

前端協同:JS 編碼最佳實踐

// 錯誤:直接拼接中文
location.href = "/search?q=關鍵詞"; // 瀏覽器可能用 GBK 編碼

// 正確:encodeURIComponent 強制 UTF-8 編碼
location.href = "/search?q=" + encodeURIComponent("關鍵詞");
// 產生: /search?q=%E9%97%9C%E9%8D%B5%E8%A9%9E

// 表單提交
<form action="/search" method="get" accept-charset="UTF-8">
    <input name="q" />
</form>

POST 請求特殊說明

  • POST 請求體編碼由 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 決定。
  • 只要 Filter 設置 request.setCharacterEncoding("UTF-8") 在讀取參數前執行,POST 中文通常無亂碼。
  • Multipart 文件上傳需解析器 (Commons FileUpload / Servlet 3.0 request.getPart()) 支援編碼設置。

RESTful API 路徑參數 (@PathVariable)

Spring MVC 中 @PathVariable 同樣受 URIEncoding 影響。若 Tomcat 未配置,需在 web.xml 添加 CharacterEncodingFilter 並設置 forceEncoding=true。

調試排查清單

  1. 確認 HTML 頁面 <meta charset="UTF-8">。
  2. 瀏覽器 Network 面板查看 Request URL 實際發送的字節序列 (%E4%B8%AD%E6%96%87 為 UTF-8)。
  3. 檢查 Tomcat server.xml Connector 是否有 URIEncoding="UTF-8"。
  4. 確認 Filter 順序:EncodingFilter 必須在其他讀取參數的 Filter 之前。
  5. 排除反向代理 (Nginx/Apache) 轉發時的編碼轉換問題 (proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 一般不影響編碼)。

總結

「容器配置 URIEncoding + 過濾器統一編碼 + 前端 encodeURIComponent」三位一體,徹底根治 URL 中文亂碼。原則:全鏈路 UTF-8,任何環節不允許出現 GBK/ISO-8859-1。新項目啟動即配置,老項目補全 Filter 與 server.xml,亂碼問題將不再困擾。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved