数据库存值报错
### Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x81\xF0\x9F...' for column 'msg' at row 1
; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: '\xF0\x9F\x98\x81\xF0\x9F...' for column 'msg' at row 1; nested exception is java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x81\xF0\x9F...' for column 'msg' at row 1
org.springframework.jdb
解决方式:
前端传值来时,emoj表情 转换为 别名字符 ;-- 实现方式:注解校验更改
后端向前端返回值时,转换为 表情; -- 实现方式:普通代码
- 后端向前端返回值时:
// 别名 转换成 表情
value = EmojiParser.parseToUnicode(value);
- 前端传值来的注解方式:
1、 controller利用@Valid注解拦截
@Slf4j
@Controller
@ResponseBody
@RequestMapping("/api/chat")
public class Testtroller extends TemplateController {
@Autowired
private Service Service;
/**
* test
*/
@RequestMapping("/create")
@Log("new message")
public CreateMsgResult create(@RequestBody @Valid CreateRequest createRequest){
return Service.create(createRequest);
}
}
2、对POJO类中的要更改的属性加注解
@Getter
@Setter
public class CreateRequest extends ToString {
/**
* 当前消息内容
*/
@EmojToAliases
private String msg;
}
3、自定义注解 @EmojToAliases
import com.alipay.antcs.annotation.resolve.AnnotationResolve;
import org.springframework.stereotype.Component;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
// 注解包含于Javadoc中
@Documented
// 注解的作用目标
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER})
// 注解可以被继承
@Inherited
// 注解的保留策略
@Retention(RetentionPolicy.RUNTIME)
@Component
@Constraint(validatedBy = AnnotationResolve.class)
public @interface EmojToAliases {
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
4、注解解析器
import com.alipay.antcs.annotation.EmojToAliases;
import com.alipay.antcs.model.base.ToString;
import com.alipay.antcs.model.exception.AntcsException;
import com.vdurmont.emoji.EmojiParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@Slf4j
public class AnnotationResolve extends ToString implements ConstraintValidator<EmojToAliases, Object> {
@Override
public void initialize(EmojToAliases constraintAnnotation) {
log.info("[emoj-to-aliases-info]-start");
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if(null == value || value == ""){
return true;
}
String msg = (String) value;
String newValue = msg;
boolean hasEmoj = containsEmoji(msg);
if (hasEmoj) {
newValue = emojToAliases(msg);
}
mergeObject(newValue, msg);
return true;
}
/**
* 判断字符串中是否含有emoj表情
*
* @param source
* @return boolean
*/
public static boolean containsEmoji(String source) {
int len = source.length();
boolean isEmoji = false;
for (int i = 0; i < len; i++) {
char hs = source.charAt(i);
if (0xd800 <= hs && hs <= 0xdbff) {
if (source.length() > 1) {
char ls = source.charAt(i + 1);
int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
if (0x1d000 <= uc && uc <= 0x1f77f) {
return true;
}
}
} else {
// non surrogate
if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
return true;
} else if (0x2B05 <= hs && hs <= 0x2b07) {
return true;
} else if (0x2934 <= hs && hs <= 0x2935) {
return true;
} else if (0x3297 <= hs && hs <= 0x3299) {
return true;
} else if (hs == 0xa9 || hs == 0xae || hs == 0x303d
|| hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c
|| hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) {
return true;
}
if (!isEmoji && source.length() > 1 && i < source.length() - 1) {
char ls = source.charAt(i + 1);
if (ls == 0x20e3) {
return true;
}
}
}
}
return isEmoji;
}
/**
* 将字符串中的emoj标签替换成别名字符
*
* @param msg
* @return String
* @throws Exception
*/
private String emojToAliases(String msg) {
if (StringUtils.isNotBlank(msg)) {
try {
// 将字符串中的emoj标签替换成别名字符
return EmojiParser.parseToAliases(msg);
} catch (Exception e) {
log.error("[emoj-to-aliases-error]", e);
}
}
return msg;
}
/**
* 将origin对象中的非空属性循环赋值给destination对象,要求两个参数类型一样
*
* @param origin
* @param destination
* @param <T>
*/
public static <T> void mergeObject(T origin, T destination) {
if (origin == null || destination == null) {
return;
}
if (!origin.getClass().equals(destination.getClass())) {
return;
}
Field[] fields = origin.getClass().getDeclaredFields();
if (fields.length == 0) {
// 得到父类,然后赋给自己
fields = origin.getClass().getSuperclass().getDeclaredFields();
}
for (int i = 0; i < fields.length; i++) {
try {
fields[i].setAccessible(true);
// 静态属性跳过
if (Modifier.isStatic(fields[i].getModifiers()) || fields[i].isSynthetic()) {
continue;
}
Object value = fields[i].get(origin);
if (null != value) {
if (StringUtils.equals(fields[i].getName(), "serialVersionUID")) {
continue;
}
fields[i].set(destination, value);
}
fields[i].setAccessible(false);
} catch (Throwable e) {
throw new AntcsException("对象转换异常", e);
}
}
}
}
5、引入三方库jar
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>4.0.0</version>
</dependency>
网友评论