從 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 解析為亂碼字符。
文件:`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 表單處理邏輯同理修改
}
文件:`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"; // 即使異常也設置,讓上層拋出明確錯誤
}
}
}
文件:`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 生效
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 |
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 統一編碼轉碼 + 服務網格治理