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

JBoss 中文亂碼徹底解決:從 Jetty 源碼層修復 ISO-8859-1 默認編碼缺陷

     編輯:Java 相關知識

從 WebLogic 遷移到 JBoss 3.0.8 (Jetty 版) 時,中文參數存入數據庫/XML 出現亂碼,根因是 Jetty 默認使用 ISO-8859-1 解析請求參數。本文提供源碼級修復方案:修改 `org.mortbay.jetty.jar` 中 `HttpRequest.java` 和 `StringUtil.java`,將默認編碼強制為 GBK,並修復中文 URL 路徑解碼問題,經 Windows 2000 和 RedHat Linux 雙平台驗證有效。

問題根因分析

JBoss 3.0.8 內嵌 Jetty 4.2.20RC0 作為 Servlet 容器。Jetty 在 `HttpRequest.extractParameters()` 中解析查詢字符串時:


// 原始缺陷邏輯
String encoding = getCharacterEncoding(); // 通常為 null
if (encoding == null) {
    encoding = StringUtil.__ISO_8859_1; // ❌ 硬編碼默認值
    _uri.putParametersTo(_parameters);
}

導致中文參數 `%D6%D0%CE%C4` (GBK 編碼的"中文") 被錯誤按 ISO-8859-1 解析為亂碼字符。

修復步驟詳解

準備工作:獲取 Jetty 源碼

  1. 下載:Jetty 4.2.20RC0-all 源碼包
  2. 解壓定位:`org.mortbay.http.HttpRequest`、`org.mortbay.util.StringUtil`、`org.mortbay.util.URI`

修復一:HttpRequest.java - 參數解析默認編碼

文件:`org/mortbay/http/HttpRequest.java`,`extractParameters()` 方法


private void extractParameters() {
    if (_paramsExtracted) return;
    _paramsExtracted = true;
    if (_parameters == null) _parameters = new MultiMap(16);

    String encoding = getCharacterEncoding();
    if (encoding == null) {
        // === 核心修復:默認編碼改為 GBK ===
        // encoding = StringUtil.__ISO_8859_1;  // 原代碼註釋
        encoding = StringUtil.__GBK;           // 新增常量
        _uri.putParametersTo(_parameters);
    } else {
        String query = _uri.getQuery();
        if (query != null) {
            try {
                // === 核心修復:查詢字符串按 GBK 解碼 ===
                // byte[] qbytes = query.getBytes(StringUtil.__ISO_8859_1);
                byte[] qbytes = query.getBytes(StringUtil.__GBK);
                UrlEncoded.decodeTo(qbytes, 0, qbytes.length, _parameters, encoding);
            } catch (Exception e) {
                _uri.putParametersTo(_parameters);
            }
        }
    }
    // ... POST 表單處理邏輯同理修改
}

修復二:StringUtil.java - 定義 __GBK 常量

文件:`org/mortbay/util/StringUtil.java`,靜態初始化塊後添加


// === 新增 GBK 編碼常量支持 ===
public static String __GBK;
static {
    String gbk = System.getProperty("GBK");
    if (gbk != null) {
        __GBK = gbk;
    } else {
        try {
            // 驗證 JVM 是否支持 GBK
            new String(new byte[]{(byte)20}, "GBK");
            __GBK = "GBK";
        } catch (UnsupportedEncodingException e) {
            __GBK = "GBK"; // 即使異常也設置,讓上層拋出明確錯誤
        }
    }
}

修復三:URI.java - 中文 URL 路徑解碼

文件:`org/mortbay/util/URI.java`,`setURI()` 方法 case 3 分支


case 3:
    _dirty = (mark == maxi);
    _encodedPath = uri.substring(mark);
    // === 核心修復:路徑解碼使用 UTF-8 (標準規範) ===
    // _path = decodePath(_encodedPath);  // 原代碼註釋
    _path = java.net.URLDecoder.decode(_encodedPath, "UTF-8"); // 標準 URL 解碼
    break;

關鍵說明:URL 路徑部分按 RFC 3986 應使用 UTF-8 編碼,查詢字符串部分按表單提交編碼(通常 GBK)。此修復解決中文 URL 如 `/servlet/中文路徑` 的 404 問題。

編譯打包部署


# 進入 Jetty 源碼根目錄
ant clean dist  # 或 ant build-jar

# 產出:build/lib/org.mortbay.jetty.jar
# 替換 JBoss 中對應文件
cp build/lib/org.mortbay.jetty.jar $JBOSS_HOME/server/default/deploy/jbossweb.sar/
# 重啟 JBoss 生效

Linux 環境額外配置

RedHat Linux 必須設置系統 Locale 為 GBK,否則 JVM 可能不支持 GBK 編碼:


# 臨時設置
export LANG=zh_CN.GBK
export LC_ALL=zh_CN.GBK

# 永久設置 (/etc/sysconfig/i18n)
LANG="zh_CN.GBK"
SUPPORTED="zh_CN.GBK:zh_CN:zh"
SYSFONT="latarcyrheb-sun16"

驗證測試矩陣

測試場景修復前修復後驗證方法
GET 參數中文亂碼正確`/test.jsp?name=中文`
POST 表單中文亂碼正確提交包含中文的表單
中文 URL 路徑404 Not Found正確路由`/servlet/中文路徑`
英文/數字參數正常正常回歸測試
混合編碼環境部分亂碼需客戶端協調建議全鏈路 UTF-8

架構層面的最佳實踐建議

💡 源碼修補是權宜之計,架構升級才是正道

  1. 全鏈路 UTF-8:JSP 頁面 `<%@ page contentType="text/html;charset=UTF-8" %>`、數據庫連接 `useUnicode=true&characterEncoding=UTF-8`、Tomcat/Jetty `URIEncoding="UTF-8"`
  2. 升級容器版本:JBoss 4.x+/WildFly、Tomcat 7+ 內建完善編碼配置,無需修改源碼
  3. Filter 統一處理:部署 `CharacterEncodingFilter` 強制設置 `request.setCharacterEncoding("UTF-8")`
  4. 前端規範:AJAX 請求設置 `contentType: "application/x-www-form-urlencoded; charset=UTF-8"`,表單 `
    `

遷移升級路線圖


JBoss 3.0.8 (Jetty) 
    │ 源碼修補 GBK (本文方案)
    ▼
JBoss 4.x / Tomcat 5.5+ 
    │ server.xml: URIEncoding="UTF-8" + CharacterEncodingFilter
    ▼
JBoss 7 / WildFly / Tomcat 8+ 
    │ undertow/server.xml: 默認 UTF-8 + 標準 Filter
    ▼
Spring Boot 內嵌容器
    │ application.yml: server.tomcat.uri-encoding=UTF-8
    ▼
Cloud Native (K8s + Istio)
    │ Sidecar 統一編碼轉碼 + 服務網格治理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved