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

Ajax 中文亂碼終極解決方案:JavaScript escape/unescape 與 Java 完美互通

     編輯:J2EE

問題根源:編碼標準不一致

Ajax 使用 XMLHttpRequest (或 ActiveXObject) POST 中文時,瀏覽器默認按頁面編碼 (如 UTF-8/GBK) 發送字節流。但早期 Java URLEncoder.encode 輸出 %XX%XX (雙字節拆分),而 JavaScript escape() 輸出 %uXXXX (Unicode 4位十六進制)。兩者解碼邏輯完全不同,導致服務端解碼亂碼。

解決方案:統一採用 escape/unescape 協議

客戶端:JavaScript escape 編碼

var params = "chineseData=" + escape(document.getElementById("input").value);
xmlHttp.open("POST", "/test/zhongwen.jsp", false);
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send(params);

服務端:Java 實現 unescape 解碼

提供 Escape 工具類,精確實現 JavaScript unescape 算法:

public class Escape {
    private static final String[] HEX = {"00","01",...,"FF"}; // 256 條
    private static final byte[] VAL = {0x3F, 0x3F, ..., 0x0F}; // 反查表
    
    public static String unescape(String s) {
        StringBuffer sbuf = new StringBuffer();
        int i = 0, len = s.length();
        while (i < len) {
            char ch = s.charAt(i);
            if (ch == '+') { sbuf.append(' '); }
            else if (isUnreserved(ch)) { sbuf.append(ch); } // A-Z a-z 0-9 - _ . ! ~ * ' ( )
            else if (ch == '%') {
                if (i+1 < len && s.charAt(i+1) == 'u') { // %uXXXX Unicode
                    int code = (VAL[s.charAt(i+2)] << 12) | (VAL[s.charAt(i+3)] << 8) 
                             | (VAL[s.charAt(i+4)] << 4) | VAL[s.charAt(i+5)];
                    sbuf.append((char) code);
                    i += 5;
                } else { // %XX ASCII
                    int code = (VAL[s.charAt(i+1)] << 4) | VAL[s.charAt(i+2)];
                    sbuf.append((char) code);
                    i += 2;
                }
            }
            i++;
        }
        return sbuf.toString();
    }
    
    // 配套 escape 方法(供 Java 客戶端調用 JS 服務時使用)
    public static String escape(String s) { ... }
}

JSP 中調用

<%
    String decoded = Escape.unescape(request.getParameter("chineseData"));
    // 正常業務處理
%>

為什麼不推薦 URLEncoder/URLDecoder?

  • URLEncoder 輸出 %E4%B8%AD%EF%BF%BD (UTF-8 字節流編碼)
  • escape() 輸出 %u4E2D%u6587 (Unicode 代碼點編碼)
  • 現代瀏覽器內部字符串均為 UTF-16,escape 直接取碼點,無歧義
  • 關鍵:Java 標準庫無內置 %uXXXX 解碼器,必須自行實現

現代最佳實踐:標準化 UTF-8 全鏈路

若項目可控制前後端,強烈建議棄用 escape 方案,改用標準化方案:

  1. 頁面聲明 <meta charset="UTF-8">
  2. JS 使用 encodeURIComponent() (輸出 UTF-8 %XX%XX)
  3. Java 使用 URLDecoder.decode(param, "UTF-8")
  4. Tomcat server.xml 配置 URIEncoding="UTF-8"
  5. Filter 強制 request.setCharacterEncoding("UTF-8")

此方案符合 RFC 3986,無需自定義工具類,支援所有語言字符,為現代 Web 應用首選。

總結

歷史項目維護期,Escape 類完美解決 escape/unescape 互通問題;新項目請直接採用 UTF-8 + encodeURIComponent 全鏈路標準化方案,從源頭消除編碼地獄。

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