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

Java Web 中文亂碼終極解決方案:全鏈路編碼一致性指南(Servlet、Filter、Tomcat、DB、前端)

     編輯:Java 程式設計入門

亂碼產生的三大入口

  1. 請求參數解碼:GET/POST 參數從字節 → 字符串
  2. 業務處理/存儲:字符串 → 數據庫/文件/外部 API
  3. 響應輸出編碼:字符串 → 字節流 → 瀏覽器

第一階段:請求參數統一解碼(核心難點)

1. POST 請求:Filter 方案(推薦)

@WebFilter("/*")
public class EncodingFilter implements Filter {
    private static final String ENCODING = "UTF-8";

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) 
            throws IOException, ServletException {
        req.setCharacterEncoding(ENCODING);   // 必須在 getParameter() 前調用
        resp.setCharacterEncoding(ENCODING);
        resp.setContentType("text/html;charset=" + ENCODING);
        chain.doFilter(req, resp);
    }
}
  • request.setCharacterEncoding() 僅對 Body 參數(POST)生效。
  • 必須在 getParameter()、getReader() 之前調用,否則無效。

2. GET 請求:Tomcat URIEncoding(唯一生效)

<!-- Tomcat server.xml -->
<Connector port="8080" protocol="HTTP/1.1"
           URIEncoding="UTF-8" 
           ... />
  • GET 參數在 URL 路徑/查詢串,屬於 URI 解碼階段,Filter 無法攔截。
  • Tomcat 8+ 默認即為 UTF-8,但建議顯式配置。

3. Spring Boot 統一配置

@Bean
public FilterRegistrationBean encodingFilter() {
    CharacterEncodingFilter filter = new CharacterEncodingFilter();
    filter.setEncoding("UTF-8");
    filter.setForceEncoding(true); // 強制覆蓋 request/response 編碼
    FilterRegistrationBean bean = new FilterRegistrationBean<>(filter);
    bean.addUrlPatterns("/*");
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return bean;
}

第二階段:業務層字符串處理最佳實踐

第三階段:響應輸出編碼

// Servlet 原生
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter(); // 獲取 Writer 會鎖定編碼,之後不可改
out.write("中文正常");

// Spring MVC @RestController 默認 application/json;charset=UTF-8
// JSP 頁面頂部
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>

全鏈路檢查清單(部署前必驗)

  1. ☐ 所有 .java/.jsp/.xml/.properties 文件保存為 UTF-8 無 BOM
  2. ☐ IDE 編譯編碼設置為 UTF-8(IntelliJ: Settings → File Encodings → Global/Project/Properties = UTF-8)
  3. ☐ Tomcat server.xml URIEncoding="UTF-8"
  4. ☐ web.xml 或 Spring Boot 配置 CharacterEncodingFilter(forceEncoding=true)
  5. ☐ 數據庫連接串含 characterEncoding=utf8&useUnicode=true
  6. ☐ 表/庫字符集 utf8mb4(支持 Emoji)
  7. ☐ 前端頁面 <meta charset="UTF-8">、AJAX contentType: "application/json;charset=UTF-8"
  8. ☐ 日誌框架 log4j2.xml / logback.xml 設置 charset="UTF-8"

經典誤區還原

誤區 1:request.setCharacterEncoding("GBK") 就能解決所有亂碼

只對 POST Body 生效;GET 參數、響應輸出、數據庫存儲完全不受影響。

誤區 2:new String(bytes, "UTF-8") 就是萬能轉碼

若 bytes 本身已是錯誤解碼產生的(如 ISO-8859-1 讀取 UTF-8 字節),再轉 UTF-8 只會將錯誤固化。必須在最早入口正確解碼。

誤區 3:Tomcat 8 默認 UTF-8 就不用配了

默認值可能因版本、發行版、Docker 基礎鏡像而異。顯式配置零成本,隱式依賴高風險。

總結

中文亂碼本質是編碼/解碼不一致。解決之道只有一條:全鏈路統一 UTF-8(推薦 utf8mb4),在最早入口正確解碼,在最後出口正確編碼,中間業務層純 Unicode 操作,絕不手動轉碼。配置一次,永久安寧。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景錯誤做法正確做法
手動轉碼new String(str.getBytes("ISO-8859-1"), "GBK")全鏈路 UTF-8,禁止手動轉碼
JDBC 連接無參數jdbc:mysql://host:3306/db?characterEncoding=utf8&useUnicode=true&serverTimezone=Asia/Shanghai
數據庫表默認 latin1CREATE TABLE t (...) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
文件讀寫new FileReader(file)Files.readString(path, StandardCharsets.UTF_8) / new InputStreamReader(is, StandardCharsets.UTF_8)
JSON 序列化默認可能轉義Jackson: mapper.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII)