Java → JDBC → Network → MySQL Server → Storage,任一環節不一致即亂碼。
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init_connect='SET NAMES utf8mb4'
建表顯式指定:
CREATE TABLE Company (
Cname VARCHAR(10) NOT NULL,
Caddr VARCHAR(100),
Ctel VARCHAR(16)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
String url = "jdbc:mysql://localhost:3306/test?" +
"user=root&password=1" +
"&useUnicode=true" +
"&characterEncoding=utf-8" +
"&serverTimezone=Asia/Shanghai" +
"&useSSL=false";
Connection conn = DriverManager.getConnection(url);
關鍵參數:
useUnicode=true:啟用 Unicode 支持characterEncoding=utf-8:指定連接編碼(驅動 5.1+ 支持 utf8mb4)serverTimezone:8.0+ 必填,避免時區警告useSSL=false:本地開發關閉 SSL<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
或 Web.xml 過濾器統一設置:
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
// 請求參數
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
// 結果集
String name = new String(rs.getString("name").getBytes("ISO-8859-1"), "UTF-8");
原理:Tomcat 默認 ISO-8859-1 解碼 URL/Body,強制重新編碼。副作用:雙重編碼導致新亂碼、性能損耗、掩蓋根因。
SET NAMES utf8mb4
SET CHARACTER SET utf8mb4
SET SESSION collation_connection = 'utf8mb4_general_ci'
SHOW CREATE TABLE 確認 CHARSET=utf8mb4SHOW VARIABLES LIKE 'character_set%'; 全鏈路 utf8mb4INSERT ... VALUES ('測試😀') 包含 EmojicharacterEncoding=utf8mb4