公司的一个项目,一开始没有考虑到内容字段支持表情,有一个接入方的内容含有表情要支持下
项目是基于Springboot的。
方案1先尝试直接配置数据库连接
shardingsphere: datasource: names: master # 数据源 master: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://rm-xx.mysql.rds.aliyuncs.com/db?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8mb4 username: user password: ps
启动项目报错
2019-11-20 16:33:39.200 [ERROR] com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2469) - create connection SQLException, url: jdbc:mysql://rm-xxx.mysql.rds.aliyuncs.com/db?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8mb4, errorCode 0, state 0S100
java.sql.SQLException: Unsupported character encoding 'utf8mb4'.
查看数据库字符集
SHOW VARIABLES LIKE 'character_set%';
看到客户端连接数据库返回集都支持了utf8mb4
方案2更改服务器配置
这里网上有好多解决方案,直接配置数据库服务器的启动参数支持utf8mb4,做个demo还可以,测试环境多个部门共用一个mysql实例,更改配置的话所有的字符集都会更改;线上环境也不可行:阿里云的字符集是在新建实例的时候配置的,只能重建然后迁移数据
方案3让MySQL自动转换
还有一个现象是,使用datagrip是可以直接插入表情的,也就是可以在不更改服务器配置的情况下从客户端设置,或者直接发送表情让mysql自己识别
连接直接设置utf8,
shardingsphere: datasource: names: master # 数据源 master: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://rm-xxx.mysql.rds.aliyuncs.com/db?zeroDateTimeBehavior=convertToNull&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: u password: p
然后用接口直接把utf8传表情过去
报错:
chUpdateException: Incorrect string value: '\xF0\x9F\x98\x82\xF0\x9F...' for column 'msg_content' at row 1 at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:89) ~[spring-jdbc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
然后网上搜到这个https://blog.csdn.net/FHGFHFYUUGY/article/details/90292139
参考 connector-j-reference-charset 可以看到如果程序要插入 utf8mb4 字符, 需要满足以下条件: Connector/J 5.1.47 及以上版本: 1. 指定 characterEncoding 参数为 UTF8/UTF-8 即可, 新版本直接映射到 utf8mb4 编码; 2. 如果 connectionCollation 指定的排序规则不是 utf8mb4 相关的, 则 characterEncoding 参数会重写为排序规则对应的编码; Connector/J 5.1.47 以下版本: 1. 设置 MySQL 参数变量 character_set_server=utf8mb4; 2. 指定 characterEncoding 参数为 UTF8/UTF-8, jdbc 程序会进行探测是否使用 utf8mb4;
和mysql连接器版本有关,从上面保存日志看到现在使用的是5.0.4,而我们的character_set_server=utf8,所以把连接器升级到5.1.47就可以 了
<!-- Use MySQL Connector-J --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency>
注意更改5.1.47的默认时区
保存表情成功: