项目排坑小计:mysql数据库插入字符串附带emoji表情发生报错的一般情况及解决方法

首先先喊一句:武汉加油!

疫情应该也快结束了,我们公司也迎来了复工,在家办公的这几天里,突然负责的中心传来线上的噩耗:

线上生产某接口出问题了!

经过排查,原来是某接口的保存接口在接收微信传来的微信昵称往我们中心数据库插数据的时候由于附带emoji,报错了!

我说奇怪,这种问题不应该啊,总所周知,目前mysql数据库的支持算是比较完备的,只要数据库的字符集设置成utf8mb4

果不其然, 查了线上的数据库字符集,果然不是utf8mb4而是utf8!

1.原因:

UTF-8编码有可能是两个、三个、四个字节。Emoji表情是4个字节,而Mysql的utf8编码最多3个字节,所以数据插不进去。

对应的解决方案1:

非常简单,只要一开始设置数据库的字符集或者数据表字段的字符集为utf8mb4 即可。 将Mysql的编码从utf8转换成utf8mb4。详细说明如下:

首先停止MySQL Server服务,修改mysql配置文件 my.cnf(其他系统)或者mysql.ini(windows系统)

[client]

default-character-set = utf8mb4

[mysql]

default-character-set = utf8mb4

[mysqld]

character-set-client-handshake = FALSE

character-set-server = utf8mb4

collation-server = utf8mb4_unicode_ci

init_connect='SET NAMES utf8mb4'

注意: 1.需要 >= MySQL 5.5.3版本、(经检测5.5.29的也可以)低版本不支持这个字符集、复制报错

2.如果只是某个字段需要 只需要修改那个字段的字符集就可以了

重点来了

但是非常可惜,这是我们线上环境使用的数据库,字符集一旦已经使用,修改字符集容易对目前存量的数据显示造成问题。

所以我们只能在不对数据库字符集进行更改的情况下,来弥补现有的缺陷。。

解决方法2

想到的方法就是:对获取的emoji表情进行转码了,使其能在utf8字符集下转码为字符串进行保存。

附带一个前辈开发的比较好用的工具包:

Emoji转换工具,便于各种规格客户端生成的Emoji字符串转换成另外一种格式

    <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>java-emoji-converter</artifactId>
            <version>0.1.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>xstream</artifactId>
                    <groupId>com.thoughtworks.xstream</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
            </exclusions>
        </dependency>
复制代码

写出一个工具方法:

public class EmojiUtils {

    /**
     * emoji字符alias转unicode
     * @param alias
     * @return
     */
    public static String toUnicode(String alias){
        if(StringUtil.isNotBlank(alias)){
            EmojiConverter emojiConverter = EmojiConverter.getInstance();
            return emojiConverter.toUnicode(alias);
        }
        return alias;
    }

    /**
     * emoji字符unicode转alias
     * @param alias
     * @return
     */
    public static String toAlias(String alias){
        if(StringUtil.isNotBlank(alias)){
            EmojiConverter emojiConverter = EmojiConverter.getInstance();
            return emojiConverter.toAlias(alias);
        }
        return alias;
    }
}
复制代码

在数据入库前进行toUnicode转码进行保存,

在查询接口要使用的字段上进行toAlias进行展示。

小坑大功告成

总结

这种坑最好就要防患于未然, 在建库建表时候最好就将字段设置成utf8mb4,杜绝这种坑的出现才是最好的(o´ω`o)ノ

猜你喜欢

转载自juejin.im/post/5e53980af265da57584da2b8