Spring Boot从MySQL获取越南语字符乱码问题排查
越南语字符在Spring Boot API返回时乱码的排查与解决
问题背景
我基于Spring Boot开发了一个简单API,从Docker部署的MySQL数据库中读取数据。直接在数据库执行SELECT * FROM pair;查询时,越南语字符显示正常,但API返回的越南语内容出现乱码。
数据库初始化脚本
CREATE DATABASE IF NOT EXISTS word_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GO USE word_app; GO CREATE TABLE user ( id INT NOT NULL AUTO_INCREMENT, display_name VARCHAR(50), username VARCHAR(100), password VARCHAR(100), PRIMARY KEY (id) ); GO CREATE TABLE category ( id INT NOT NULL AUTO_INCREMENT, title VARCHAR(50), user_id INT NOT NULL, PRIMARY KEY (id), FOREIGN KEY (user_id) REFERENCES user(id) ); GO CREATE TABLE pair ( id INT NOT NULL AUTO_INCREMENT, en VARCHAR(255), vi VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, category_id INT NOT NULL, PRIMARY KEY (id), FOREIGN KEY (category_id) REFERENCES category(id) ); GO INSERT INTO pair (en, vi, category_id) VALUES ("mediterranean", "Địa Trung Hải(adj, n)", 5);
API返回乱码示例
"data": [ { "id": 42, "en": "mediterranean", "vi": "Äịa Trung Hải(adj, n)", "categoryId": 5 }, { "id": 43, "en": "stronghold", "vi": "pháo đà i", "categoryId": 5 }]
当前application.properties配置
spring.datasource.url=jdbc:mysql://localhost:3306/word_app?useUnicode=true&characterEncoding=UTF-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.show-sql=true server.servlet.encoding.charset=UTF-8 server.servlet.encoding.enabled=true server.servlet.encoding.force=true spring.mvc.locale-resolver=fixed spring.mvc.locale=vi_VN
排查与解决步骤
1. 修正JDBC URL的字符编码参数
properties文件中无需使用HTML转义字符&,直接用&拼接参数。同时针对MySQL 8.0+,补充characterSetResults=utf8mb4确保读取数据时的编码一致,修改后的URL:
spring.datasource.url=jdbc:mysql://localhost:3306/word_app?useUnicode=true&characterEncoding=utf8mb4&characterSetResults=utf8mb4&useSSL=false
2. 验证数据库连接编码
添加代码打印数据库连接的字符编码属性,确认配置是否生效:
import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.sql.Connection; import java.sql.SQLException; @Component public class DbEncodingChecker { @Autowired private DataSource dataSource; public void checkEncoding() throws SQLException { try (Connection conn = dataSource.getConnection()) { String encoding = conn.getMetaData().getCharacterSet(); System.out.println("数据库连接字符集: " + encoding); } } }
3. 配置JPA/Hibernate编码参数
避免Hibernate覆盖连接编码设置,在application.properties中添加:
spring.jpa.properties.hibernate.connection.characterEncoding=utf8mb4 spring.jpa.properties.hibernate.connection.useUnicode=true
4. 修正Docker容器中MySQL的编码配置
Docker部署的MySQL可能默认编码不是utf8mb4,启动容器时需指定编码参数:
- 用docker run命令启动:
docker run -e MYSQL_ROOT_PASSWORD=yourpassword -e MYSQL_CHARACTER_SET=utf8mb4 -e MYSQL_COLLATION=utf8mb4_unicode_ci mysql:8.0
- 用docker-compose.yml配置:
services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: yourpassword MYSQL_DATABASE: word_app MYSQL_CHARACTER_SET: utf8mb4 MYSQL_COLLATION: utf8mb4_unicode_ci
5. 显式指定API响应编码
在Controller方法上明确指定响应的Content-Type编码,确保输出编码正确:
import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class PairController { @GetMapping(value = "/pairs", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public List<Pair> getPairs() { // 业务逻辑实现 } }
6. 重新插入测试数据
如果之前的数据是在编码配置错误时插入的,可能已存储为乱码。需删除现有数据,在正确配置完成后重新插入,确保数据本身以utf8mb4编码存储。
内容的提问来源于stack exchange,提问作者Peter Present
相关产品推荐
相关产品推荐

