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

JSP/Servlet 中文編碼亂碼終極解決方案:原理、陷阱與最佳實踐

     編輯:關於JSP
為什麼會亂碼?核心原理深度剖析

亂碼的本質是 「編碼不一致導致的字節序列解碼錯誤」。在 Java Web 體系中,數據流經多個環節,每個環節若編碼設置不一致,即會產生亂碼。

關鍵編碼轉換鏈路

瀏覽器輸入/顯示 (瀏覽器編碼)
    ↓ HTTP 傳輸 (URL 編碼 / 請求主體編碼)
Web 伺服器/容器 (Tomcat URIEncoding / request.setCharacterEncoding)
    ↓ Java 內部處理 (Unicode UTF-16)
業務邏輯 / 數據庫驅動 (連接串 characterEncoding)
    ↓ 數據庫存儲 (表/列字符集: utf8mb4 / gbk)
數據庫讀取 → 反向流程 → 瀏覽器顯示 (response.setContentType charset)

核心鐵律:全鏈路統一編碼,推薦全站 UTF-8 (或 UTF-8MB4)。

中文字符集演進與 Java 支持

字符集說明Java 編碼名備註
GB2312-80國家標準,6763 漢字GB2312 / EUC_CN早期系統,字符集較小
GBKGB2312 擴展,兼容 GB2312,含 2萬+ 字符GBK / CP936Windows 中文默認,MySQL 早期常用
GB18030-2000國家標準,強制兼容 GBK,含少數民族字,變長編碼 (1/2/4 字節)GB18030現代國標要求,JDK 1.4+ 支持
Big5繁體中文常用編碼Big5 / Cp950台灣/香港地區歷史系統
Unicode (UTF-16)Java 內部字符表示 (char 2 字節,補充字符 4 字節)內部使用Java char 為 UTF-16 代碼單元
UTF-8Unicode 變長編碼 (1-4 字節),ASCII 兼容,**Web 國際化標準**UTF-8強烈推薦全棧統一使用

四大亂碼高發場景與精準修復

場景一:GET 請求參數中文亂碼 (Tomcat 8+ 默認已修復)

現象:URL `?name=張三` 到達後端變 `??` 或 `涓婂競`。

原因:Tomcat 7 默認用 ISO-8859-1 解碼 URL 查詢字符串;Tomcat 8+ 默認 UTF-8。

修復 (server.xml Connector):

<Connector port="8080" protocol="HTTP/1.1"
           URIEncoding="UTF-8"  <!-- 關鍵:指定 URL 解碼編碼 -->
           connectionTimeout="20000"
           redirectPort="8443" />

舊版 Tomcat 7 臨時方案:`new String(param.getBytes("ISO-8859-1"), "UTF-8")` (不推薦,升級容器)。

場景二:POST 請求表單中文亂碼

現象:`request.getParameter("name")` 獲取亂碼。

原因:容器默認用 ISO-8859-1 解碼請求主體。

修復:在讀取任何參數前 設置:

// Servlet / Filter / Controller 入口第一行
request.setCharacterEncoding("UTF-8");

最佳實踐:配置 **字符編碼過濾器** (web.xml 或 Spring `CharacterEncodingFilter`),全局攔截保證。
注意:`multipart/form-data` (文件上傳) 需上傳組件 (Commons FileUpload / Servlet 3.0 Part API) 支持編碼設置,通常在解析前同樣需 `request.setCharacterEncoding`。

場景三:響應輸出中文亂碼 (瀏覽器顯示亂碼)

現象:JSP 頁面輸出中文變 `???` 或亂碼。

修復雙管齊下:

  1. 設置響應頭 Content-Type 包含 charset (必須在獲取 out/writer 前):
    response.setContentType("text/html; charset=UTF-8");
    // 或
    response.setCharacterEncoding("UTF-8"); // 等效於設置 Content-Type charset 部分
    
  2. JSP 頁面指令聲明編碼 (告訴容器源文件編碼 & 響應編碼):
    <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
    

原理:`pageEncoding` 指導容器以何種編碼讀取 .jsp 源文件 (生成 Servlet 時字符串常量正確);`contentType` 指導響應頭,瀏覽器據此解碼顯示。

場景四:數據庫中文存取亂碼

MySQL 典型配置:

  • 建庫/建表:`CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci` (支援 Emoji/補充字符)。
  • 連接串:`jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai`。
  • 驅動版本:MySQL Connector/J 5.1+ (5.1.47 穩定) 或 8.0+。

Oracle/SQL Server/PostgreSQL:同理確保數據庫/表/列字符集、JDBC 連接屬性、Java 端編碼三方一致。

調試亂碼的「黃金三步法」

  1. 確認源頭:瀏覽器發送的原始字節是什麼?(F12 Network -> Payload/Query String -> view source -> 檢查 %XX 編碼)。
  2. 斷點驗證:在 `request.getParameter()` 後斷點,檢查 Java String 內部 char[] 值 (IDEA 懸停查看),是否已為正確 Unicode 碼點。
  3. 追蹤流向:String -> 業務邏輯 -> 數據庫 -> 讀取 -> 響應輸出 -> 瀏覽器渲染,每一環檢查編碼設置。

現代框架 (Spring Boot / Spring MVC) 自動化配置

Spring Boot 2.x/3.x 默認已全鏈路 UTF-8:

  • Tomcat/Undertow/Jetty 容器自動配置 `URIEncoding=UTF-8`。
  • `CharacterEncodingFilter` 默認註冊,`forceEncoding=true` 強制請求/響應 UTF-8。
  • JSP 模板引擎需手動加 `pageEncoding`;Thymeleaf/Freemarker 默認 UTF-8。
  • 數據源連接串建議顯式加 `characterEncoding=utf8`。

總結:零亂碼檢查清單

層級關鍵配置項推薦值
瀏覽器/前端HTML Meta / AJAX Content-Type<meta charset="UTF-8"> / application/json; charset=UTF-8
Web 容器Connector URIEncodingUTF-8
請求處理request.setCharacterEncoding / FilterUTF-8 (最早執行)
JSP 頁面pageEncoding / contentTypeUTF-8 / UTF-8
響應輸出response.setContentType / setCharacterEncodingtext/html; charset=UTF-8
數據庫Schema/Table/Column Charset + JDBC URLutf8mb4 / useUnicode=true&characterEncoding=utf8
文件/日誌IDE/Editor/File Encoding / Logback encodingUTF-8

堅持 「全棧 UTF-8 (utf8mb4)」,配置 字符編碼過濾器 為最早攔截點,升級容器至 Tomcat 9+/Jetty 9+,即可徹底告別中文亂碼噩夢。

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