You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+MySQL特定表韩文存储突发乱码,排查字符集仍未解决

韩文编码错误排查分析

开发Spring Boot+MySQL项目时,某特定表突然出现韩文文本编码错误,此前韩文存储正常。已确认MySQL字符集配置无误,甚至重建表后问题仍存在。

乱码数据示例

1,ãããããã,ãã,1729758442950_스크린샷 2024-08-27 211441.png,1

2,ãããããã,ãã,1729759803302_스크린샷 2024-08-27 211441.png,1

MySQL字符集配置

+--------------------------+---------------------------------------------------------+
| Variable_name            | Value                                                   |
+--------------------------+---------------------------------------------------------+
| character_set_client     | utf8mb4                                                 |
| character_set_connection | utf8mb4                                                 |
| character_set_database   | utf8mb4                                                 |
| character_set_filesystem | binary                                                  |
| character_set_results    | utf8mb4                                                 |
| character_set_server     | utf8mb4                                                 |
| character_set_system     | utf8mb3                                                 |
| character_sets_dir       | C:\Program Files\MySQL\MySQL Server 8.0\share\charsets\ |
+--------------------------+---------------------------------------------------------+
8 rows in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'collation%';
+----------------------+--------------------+
| Variable_name        | Value              |
+----------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database   | utf8mb4_unicode_ci |
| collation_server     | utf8mb4_unicode_ci |
+----------------------+--------------------+

表结构

self_intro | CREATE TABLE `self_intro` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `content` varchar(1500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `image_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `user_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FKc409uoed65kpyxaq026593lp4` (`user_id`),
  CONSTRAINT `FKc409uoed65kpyxaq026593lp4` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |

HEX查询结果

+------------------------------+--------------------------+
| title_hex                    | content_hex              |
+------------------------------+--------------------------+
| C3ACC2A0C29CC3ABC2B0C29C2F2F | C3A3C285C287C3A3C285C287 |
+------------------------------+--------------------------+
1 row in set (0.01 sec)

服务端代码

public void createSelfIntroduction(SelfIntroDto selfIntroDto, String userEmail, MultipartFile file) throws IOException {
        User user = userRepository.findByEmail(userEmail) // email
                .orElseThrow(() -> new RuntimeException("User not found with email: " + userEmail));

        String imageUrl = saveFile(file); // file

        SelfIntro selfIntroduction = new SelfIntro();
        selfIntroduction.setTitle(selfIntroDto.getTitle());
        selfIntroduction.setContent(selfIntroDto.getContent());
        selfIntroduction.setImageUrl(imageUrl); // save url
        selfIntroduction.setUser(user);
        System.out.println(selfIntroDto.getTitle());

        selfIntroRepository.save(selfIntroduction);
    }

控制器代码

@PostMapping(consumes = "multipart/form-data")
@Secured("ROLE_STUDENT")
public ResponseEntity<String> createSelfIntroduction(
        @RequestPart(value = "title") String title,
        @RequestPart(value = "content") String content,
        @RequestPart(value = "file", required = false) MultipartFile file,
        HttpServletRequest request) {
    try {
        String userEmail = extractUserEmailFromJwt(request);
        SelfIntroDto selfIntroDto = new SelfIntroDto();
        selfIntroDto.setTitle(title);
        selfIntroDto.setContent(content);

        User user = userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new RuntimeException("User not found with email: " + userEmail));
        selfIntroDto.setUserName(user.getName());
        selfIntroDto.setUserSchool(user.getSchool());

        selfIntroService.createSelfIntroduction(selfIntroDto, userEmail, file);
        return ResponseEntity.ok("Self Introduction created successfully");
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Failed to create self introduction: " + e.getMessage());
    }
}

可能的原因分析

1. Multipart请求参数编码解析错误

控制器通过@RequestPart接收title和content时,Spring Boot默认对multipart/form-data类型的字符串参数可能使用ISO-8859-1编码解析,而非UTF-8。当前端传递UTF-8编码的韩文时,被错误解码后再转存到数据库,就会生成类似ãããããã的乱码。

从HEX结果来看,存储的字节序列(如C3AC)符合“UTF-8字节被当作ISO-8859-1解码,再重新编码为UTF-8”的特征——原本的韩文UTF-8字节被错误解析为乱码字符,再以UTF-8存储就会导致二次编码错误。

2. Spring Boot编码配置缺失

若未在配置文件中强制指定全局字符编码,Spring Boot处理请求时可能依赖系统默认编码(非UTF-8),导致参数解析阶段出现编码偏差。需检查application.properties或application.yml中是否配置:

spring.http.encoding.charset=UTF-8
spring.http.encoding.force=true
spring.http.encoding.enabled=true
spring.servlet.multipart.enabled=true

3. JDBC连接URL编码参数遗漏

尽管MySQL全局字符集配置为utf8mb4,但JDBC连接URL若未明确指定编码参数,可能导致连接时的编码协商异常。需确保URL包含以下参数:

jdbc:mysql://localhost:3306/your_db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC

4. 控制台输出验证辅助判断

服务端代码中打印了selfIntroDto.getTitle(),可直接观察控制台输出:

  • 若控制台输出为乱码:说明参数在控制器接收阶段就已编码错误,重点排查请求解析的编码配置;
  • 若控制台输出正常:说明问题出在数据库存储环节,需再次确认JDBC连接参数或通过ALTER TABLE self_intro CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci强制转换表字符集。

内容的提问来源于stack exchange,提问作者kaidey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:12:09