美文网首页
消息中有emoj表情的处理方式

消息中有emoj表情的处理方式

作者: 一只狗被牵着走 | 来源:发表于2020-02-27 19:58 被阅读0次

数据库存值报错

### 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表情 转换为 别名字符 ;-- 实现方式:注解校验更改
后端向前端返回值时,转换为 表情; -- 实现方式:普通代码

  1. 后端向前端返回值时:
    // 别名 转换成 表情
    value = EmojiParser.parseToUnicode(value);
  1. 前端传值来的注解方式:

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>

done

相关文章

网友评论

      本文标题:消息中有emoj表情的处理方式

      本文链接:https://www.haomeiwen.com/subject/annxhhtx.html