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

Java 中文亂碼全景解析:JSP 請求響應、JDBC 數據庫、系統編碼三大戰場制勝指南

     編輯:Java 相關知識

亂碼本質:編碼鏈路不一致

Java 內部 UTF-16,I/O 邊界發生編碼轉換。亂碼 = 讀取編碼 ≠ 寫入編碼,或 聲明編碼 ≠ 實際編碼。三大高發戰場:JSP/Servlet、JDBC、系統層面。

戰場一:JSP/Servlet 請求-響應鏈路

請求參數解碼

  • Tomcat 8+ 默認 UTF-8,需在 server.xml <Connector URIEncoding="UTF-8"/> 確認。
  • GET 參數在 URL 中,經瀏覽器 URL 編碼(通常 UTF-8)→ Tomcat 解碼。POST 參數在 Body,按 Content-Type charset 解碼。
  • 強制統一:request.setCharacterEncoding("UTF-8") 必須在首次讀取參數前調用(Filter 中攔截最佳)。

響應輸出編碼

// 方式一:page 指令(JSP 頂部)
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

// 方式二:Servlet 代碼
response.setContentType("text/html; charset=UTF-8");
response.setCharacterEncoding("UTF-8"); // 等同於上一行

// 方式三:HTML meta(瀏覽器兜底識別)
<meta charset="UTF-8">

鐵律:pageEncoding(源文件編碼)= charset(輸出編碼)= request.setCharacterEncoding(輸入編碼)= 數據庫連接編碼 = 文件/日誌編碼 = 全鏈路 UTF-8。

戰場二:JDBC 數據庫中文存取

驅動與連接 URL 參數

// MySQL 8.0+ (Con/J 8.0+)
jdbc:mysql://host:3306/db?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai

// Oracle
jdbc:oracle:thin:@host:1521:sid
// 驅動默認按 NLS_LANG 環境變量或 JVM file.encoding,建議顯式設置
System.setProperty("oracle.jdbc.defaultNChar", "true");

讀寫代碼模式

// 寫入:PreparedStatement 自動按連接編碼轉換
ps.setString(1, "中文"); // 推薦
// 或顯式字節
ps.setBytes(1, "中文".getBytes(StandardCharsets.UTF_8));

// 讀取:getString 自動解碼
String val = rs.getString("col"); // 推薦
// 歷史驅動可能需手動轉碼(極少見)
// String val = new String(rs.getBytes("col"), "ISO-8859-1"); // 反模式

驅動差異大:i-net UNA 免轉碼、舊版 jTDS 需手動、PostgreSQL 默認 UTF-8。**上線前必測該驅動中文存取**。

戰場三:系統層面編碼陷阱

文件讀寫

// 顯式指定編碼,禁用平台默認
Files.readString(path, StandardCharsets.UTF_8);
Files.writeString(path, content, StandardCharsets.UTF_8);
// 歷史代碼
new String(bytes, "GBK"); // 明確源編碼
new OutputStreamWriter(new FileOutputStream(file), "UTF-8");

JVM 启動參數(慎用)

-Dfile.encoding=UTF-8
// 影響:Charset.defaultCharset()、InputStreamReader/OutputStreamWriter 無參構造器
// 風險:第三方庫可能依賴平台默認編碼,全局修改可能引發新亂碼
// 建議:代碼中顯式指定編碼,不依賴 file.encoding

日誌框架編碼

<!-- Logback -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <encoder>
        <charset>UTF-8</charset>
    </encoder>
</appender>

遺留項目 GBK/ISO-8859-1 遷移策略

  1. 新模塊全鏈路 UTF-8,舊模塊維持原樣,邊界處轉碼(new String(bytes, "GBK"))。
  2. 數據庫表字符集轉換:ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4(MySQL)。
  3. 前端頁面 <meta charset="UTF-8">,AJAX 請求 contentType: "application/json; charset=UTF-8"。
  4. 分批灰度發布,監控亂碼異常日誌,驗證無誤後全量切換。

終極檢查清單

  • [ ] 源文件編碼 = 項目規範(UTF-8),IDE/編譯器一致。
  • [ ] JSP pageEncoding = charset = UTF-8。
  • [ ] Filter 首行 request.setCharacterEncoding("UTF-8")。
  • [ ] Servlet/Controller response.setCharacterEncoding("UTF-8")。
  • [ ] JDBC URL 含 characterEncoding=utf8(或對應參數)。
  • [ ] 文件/網絡/日誌 I/O 顯式指定 StandardCharsets.UTF_8。
  • [ ] 前端 HTML <meta charset="UTF-8">,AJAX/表單提交編碼一致。
  • [ ] 測試用例覆蓋:中文、繁體、Emoji、特殊符號、SQL 注入字符。
亂碼治理無捷徑,只有「全鏈路顯式、統一 UTF-8、自動化驗證」。把編碼當作接口契約的一部分,寫進代碼規範、CI 檢查、架構決策記錄(ADR)裡。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved