Cause: java.sql.SQLException: Incorrect string value: '\\xF0\\x9F\\x9F\\xA6\\xE6\\x98...'
咋一眼看到这个错,反应过来是入库的内容包含了emoji表情, 或者特殊符号。
因为数据库中的字符集设置的未utf8,而mysql中的utf8是有缺陷的,那就是编码最大是3个字节,而我们在开发中的UTF-8编码最大是四个字节,像emoji表情就是4个字节,这里可以验证这个猜想。
取前四个字节找个在线转换网站便可,转换如下:
这明显是个特殊符号,所以导致入库失败。
解决办法:
1. mysql有对这个缺陷修复,即utf8mb4,这是utf8超集,兼容utf8,并且编码最大字节是4个字节,特殊字符和emoji表情存入,毫无问题(这也是最好的办法,只是对mysql版本有要求, 一般5.6+)
2. 如果功能已经上线,有大量线上数据,以及mysql版本不支持,不能轻易去修改字符集,那也可以通过encode编码入库,出库时在用decode解码,但是这种方式也很麻烦,因为如果涉及改造地方太多,那将花费大量时间
3. 过滤emoji表情,使用工具EmojiParser,示例如下:
if (!name.equals(EmojiParser.parseToAliases(name))) {
try {
String encode = URLEncoder.encode(name, "UTF-8");
String decode = URLDecoder.decode(encode, "UTF-8");
log.info("部门名称包含emoji表情: {}, encode编码后: {}, decode解码后: {}", name, encode, decode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
这种方式对用户不是很友好,并且像上面那个字符还不属于emoji表情,是无法用这个过滤的。
总结:如果是在功能开发前,想到这个问题,避免出现这种问题是最好的,出于业务考虑,一般和微信等有关联的情况下,条件反射想到这个问题,当然这都是后话,只能做到以后避免。