公司的一个项目,一开始没有考虑到内容字段支持表情,有一个接入方的内容含有表情要支持下

项目是基于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的默认时区

保存表情成功:

01-12 21:52