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

SpringMVC + MyBatis + MySQL 中文亂碼終極解決方案

     編輯:Java 相關知識

前言

中文亂碼本質是編碼不一致導致的字節解碼錯誤。全鏈路涉及:瀏覽器 → Tomcat → SpringMVC → MyBatis → JDBC → MySQL。任一環節編碼不匹配即產生亂碼。本文提供系統性排查與修復方案。

一、全鏈路編碼統一原則

層級配置點標準值驗證方式
瀏覽器HTTP Header / Meta 標簽UTF-8F12 Network → Response Headers
Tomcatserver.xml ConnectorURIEncoding="UTF-8"GET 參數中文正常
SpringMVCCharacterEncodingFilterUTF-8 + forceEncoding=truePOST 表單中文正常
JSP/ThymeleafpageEncoding / charsetUTF-8頁面顯示正常
MyBatisresultType / TypeHandler匹配數據庫字段類型Blob/Clob 正確讀取
JDBC URLconnection parameterscharacterEncoding=utf8mb4寫入讀取無亂碼
MySQL表/庫/連接編碼utf8mb4 / utf8mb4_general_ciSHOW VARIABLES LIKE 'char%'

二、核心配置清單

2.1 web.xml:CharacterEncodingFilter(必須第一個 Filter)

<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>

2.2 Tomcat server.xml:GET 參數編碼

<Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443"
    URIEncoding="UTF-8"
    useBodyEncodingForURI="true" />

2.3 SpringMVC Controller:響應編碼

// 方案一:@ResponseBody 返回 String 時指定編碼
@GetMapping(value = "/api/text", produces = "text/plain;charset=UTF-8")
@ResponseBody
public String getText() { return "中文內容"; }

// 方案二:返回對象,配置 HttpMessageConverter
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        converters.add(0, stringConverter); // 優先級最高
    }
}

// 方案三:全局響應攔截器
@Component
public class EncodingResponseInterceptor implements HandlerInterceptor {
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        response.setCharacterEncoding("UTF-8");
    }
}

2.4 MyBatis Blob/Clob 處理

<!-- Mapper XML:Blob 字段映射為 byte[] -->
<select id="selectContent" resultType="java.util.HashMap">
    SELECT id, content FROM article WHERE id = #{id}
</select>

<!-- Service 處理 -->
public String getContent(Long id) {
    Map<String, Object> row = mapper.selectContent(id);
    byte[] blobData = (byte[]) row.get("content"); // 或 getBytes("content")
    return new String(blobData, StandardCharsets.UTF_8);
}

2.5 JDBC URL 關鍵參數

jdbc:mysql://localhost:3306/mydb?
    useUnicode=true&
    characterEncoding=utf8mb4&
    useSSL=false&
    serverTimezone=UTC&
    allowPublicKeyRetrieval=true

2.6 MySQL 編碼徹底修正

-- 1. 檢查當前編碼
SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';

-- 2. 修改配置文件 my.cnf / my.ini
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init_connect='SET NAMES utf8mb4'

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

-- 3. 重啟 MySQL 後,修改現有庫表
ALTER DATABASE mydb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;
ALTER TABLE article CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 或單獨修改字段
ALTER TABLE article MODIFY content LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

三、典型亂碼場景排查樹


亂碼現象
├── 頁面顯示 ? / 鏡像字符
│   ├── 檢查 JSP pageEncoding="UTF-8"
│   ├── 檢查 SpringMVC produces="...charset=UTF-8"
│   └── 檢查 Tomcat URIEncoding="UTF-8"
├── 數據庫存入 ?? / 亂碼
│   ├── 檢查 JDBC URL characterEncoding=utf8mb4
│   ├── 檢查 MySQL 表/庫編碼 utf8mb4
│   └── 檢查 MyBatis resultType 是否匹配 (Blob→byte[])
├── GET 請求參數亂碼
│   └── Tomcat server.xml URIEncoding="UTF-8"
├── POST 請求參數亂碼
│   └── CharacterEncodingFilter forceEncoding=true
└── 文件下載中文文件名亂碼
    └── URLEncoder.encode(fileName, "UTF-8") + 瀏覽器兼容處理

四、調試技巧

  1. 字節級驗證:`new String(bytes, "ISO-8859-1").getBytes("UTF-8")` 逆向還原
  2. 日誌輸出字節:`log.info("bytes: {}", Arrays.toString(str.getBytes(StandardCharsets.UTF_8)))`
  3. 數據庫直連驗證:`SELECT HEX(content), CHAR_LENGTH(content), CHARACTER_LENGTH(content) FROM article`
  4. 網絡抓包:Wireshark / F12 Network 查看實際傳輸字節

五、總結

中文亂碼解決核心三步:全鏈路 UTF-8 統一 → Blob/Clob 正確類型映射 → MySQL utf8mb4 徹底配置。建立「編碼檢查清單」納入代碼評審,新增接口必驗中文場景,從源頭杜絕亂碼。

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