开发避坑指南(29):微信昵称特殊字符存储异常修复方案

异常信息

java 复制代码
Cause: java.sql.SQLException: 
Incorrect string value: '\xF0\x9F\x8D\x8B\xE5\xBB...' for column 'nick_name' at row 1

异常背景

抽奖大转盘,抽奖后需要保存用户抽奖记录,用户再次进入游戏时根据抽奖记录判断剩余抽奖机会。保存抽奖记录时需要保存用户open_id,昵称,抽奖时间等信息,保存昵称时异常,没有成功记录抽奖导致剩余机会不减,用户可多次抽奖。

保存接口请求参数:

异常分析

昵称包含特殊字符,数据库定义的数据类型、字符集不支持,所以保存失败了。

解决办法

MySQL在5.5.3版本之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。低版本的MySQL

支持的utf8编码,最大字符长度为 3 字节,如果遇到 4 字节的字符就会出现错误了,其中Emoji表情是四个字节,导致插不进去。

解决这个办法可以从数据库层面上解决,即修改数据库的字段定义,如下方案1;或者从应用层面解决,如下方案2。

方案1:修改数据库字段字符集

mysql数据库中,将nick_name字段字符集由utf8修改为utf8mb4,数据库链接中将字符集由utf8改为utf8mb4。如下:

properties 复制代码
url: "jdbc:mysql://localhost:3306/big-turntable?useUnicode=true&characterEncoding=utf8mb4&useSSL=false"

查看日志和数据库,插入不再异常。

方案2:使用 Base64 编码与解码昵称

java 复制代码
//Base64编码保存昵称
String nickname = record.getNickName();
if(stringutil.isNotEmpty(nickname)){
    nickname = Base64.getEncoder().encodeTostring(nickname.getBytes( charsetName: "utf-8"));
    record.setNickName(nickname);
}   

//Base64解码昵称
if(stringutil.isNotEmpty(record.getNickName())){
    String nickName =record.getNickName();
    String nickName = new String(Base64.getDecoder().decode(nickName), 	 charsetName: "UTF-8");
    nickNameMap.put(record.getPriceId(),nickName);
}
相关推荐
上学的小垃圾7 小时前
基于docker安装MySQL(openEuler系统)
linux·mysql·docker·容器
论迹复利8 小时前
FreeRTOS 在 RISC-V 上是如何“点火“的 —— 从 main() 到第一个任务的完整链路
java·开发语言·risc-v
张宇Joaquin8 小时前
鲲鹏统一并行加速库KUPL--众核并行能力介绍
java·开发语言·网络
宸津-代码粉碎机9 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
2601_9637491010 小时前
越华环保集团数字化污水治理:端边云采集架构与平台对接实现
java·大数据·架构
xcLeigh10 小时前
Go入门:整数类型的溢出与安全边界
java·安全·golang
爱吃火鸡面呀10 小时前
MySQL DQL 子查询详解:从标量、列、行到表子查询的完整实战
大数据·数据库·mysql
源码宝10 小时前
SpringBoot+Vue2 诊所门诊管理系统,完整前后端源码,可直接部署上线
java·源码·his系统·门诊系统·程序代码·诊所系统·门诊his
yychen_java11 小时前
九:Text-to-SQL 智能数据查询与 Human-in-the-Loop 人机协作
java·人工智能·架构
lhldsg12 小时前
智慧场馆解决方案小程序开发实战:从架构设计到部署指南
java·小程序·uni-app