Linux 下 Web 應用亂碼的根本原因是應用層、數據庫層、文件存儲層編碼不一致。解決之道只有一條:全鏈路統一編碼(推薦 UTF-8)。
| 層級 | 配置項 | 推薦值 | 驗證命令 |
|---|---|---|---|
| 文件存儲 | 源碼文件編碼 | UTF-8 無 BOM | file -i *.jsp *.java *.xml |
| 頁面聲明 | <%@ page contentType="text/html;charset=UTF-8" %> | 檢查 JSP/HTML 頭部 | |
| 數據庫 | 庫級編碼 | CREATE DATABASE db CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci; | SHOW CREATE DATABASE db; |
| 表級編碼 | CREATE TABLE t (...) CHARSET=utf8mb4; | SHOW CREATE TABLE t; | |
| 連接編碼 | JDBC URL 參數 | 見下文 | |
| 應用服務器 | Tomcat URI 編碼 | <Connector URIEncoding="UTF-8" /> | server.xml |
| Filter 過濾器 | CharacterEncodingFilter (Spring) | web.xml / 配置類 |
-- 僅支持 BMP 字符(無 Emoji)
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 支持完整 Unicode(含 Emoji,推薦)
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意:MySQL 的 utf8 僅支持 3 字節字符,utf8mb4 才是真正的 UTF-8。
# MySQL 5.1.13+ (Connector/J 5.1+)
jdbc:mysql://host:3306/mydb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
# MySQL 8.0+ (Connector/J 8.0+)
jdbc:mysql://host:3306/mydb?characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai
驅動版本陷阱:舊版驅動(如 3.0.9)不支持 utf8mb4,需升級至 5.1.47+ 或 8.0.23+。
# Spring Boot application.yml
server:
servlet:
encoding:
charset: UTF-8
force: true
enabled: true
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai
hikari:
connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"
useBodyEncodingForURI="true" />
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
很多教程建議修改 /etc/sysconfig/i18n 或 /etc/my.cnf 的 default-character-set,實際上這些是服務端默認值,不影響已顯式指定編碼的連接。只要應用層在連接時顯式聲明 characterEncoding=utf8mb4,系統級配置即可忽略。
| 現象 | 可能原因 | 排查重點 |
|---|---|---|
| 中文存入 DB 變 ??? | 表/庫編碼非 utf8mb4 | SHOW CREATE TABLE 檢查 CHARSET |
| 讀出顯示亂碼(如 鏂伴矞) | 讀取編碼與寫入編碼不一致 | JDBC URL characterEncoding、JSP pageEncoding |
| GET 參數亂碼 | Tomcat URIEncoding 缺失 | server.xml Connector 配置 |
| POST 表單亂碼 | 無 CharacterEncodingFilter | Spring 配置 / Filter 順序 |
| Emoji 存入報錯 / 變 ? | 使用 utf8 而非 utf8mb4 | 庫/表/連接全鏈路 utf8mb4 |
#!/bin/bash
echo "=== 數據庫編碼 ==="
mysql -e "SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';"
echo -e "\n=== 當前連接編碼 ==="
mysql -e "SHOW VARIABLES LIKE 'character_set_connection';"
echo -e "\n=== 表編碼樣例 ==="
mysql -e "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA='your_db' LIMIT 5;"
echo -e "\n=== JDBC 驅動版本 ==="
find ~/.m2 -name "mysql-connector-java*.jar" 2>/dev/null | head -1 | xargs -I{} unzip -p {} META-INF/MANIFEST.MF | grep Implementation-Version
Linux Web 亂碼治理三部曲:
遵循此原則,無需動系統配置,亂碼問題可徹底根治。