0
点赞
收藏
分享

微信扫一扫

Validation验证框架—动态的返回所有字段的异常信息

朱小落 2021-09-21 阅读 68

一般Validation注解,存在一个message属性,当校验异常时,会将message的信息抛出。

1. 需求背景

需求:一个实体类中多个字段使用@ValidationXXX注解来校验多个字段的合法性。到出现异常时:

  1. 动态的输出异常信息;
  2. 将多个字段信息合并输出(且需要按照文档描述输出)。

2. 实现方案

2.1 自定义校验注解

@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = ValidateWordValidator.class)
@Documented
public  @interface ValidateWord {


    String message() default "请求参数错误!";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

2.2 注解处理器—关闭默认消息,设置动态消息

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Set;

@Slf4j
public class ValidateWordValidator implements ConstraintValidator<ValidateWord, Object> {

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 校验是否存在敏感词
        Set<String> hitSensitiveWords = WordUtil.hit(JSON.toJSONString(value));

        if (CollectionUtils.isEmpty(hitSensitiveWords)) {
            return true;
        } else {
            //敏感词使用,分割
            String word = String.join(",", hitSensitiveWords);
            //禁止默认消息返回
            context.disableDefaultConstraintViolation();
            //输出设置的信息
            context.buildConstraintViolationWithTemplate(word).addBeanNode().addConstraintViolation();
            return false;
        }
    }
}

关键点:

  1. 禁止默认的message属性输出。
  2. buildConstraintViolationWithTemplate设置个性化消息。

2.3 全局异常处理器—解析异常类,汇总异常描述

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
   @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class})
    @ResponseBody
    public String validErrorHandler(MethodArgumentNotValidException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        List<String> results = new ArrayList<>();
        Set<String> sensitiveSets = new HashSet<>();
        //遍历
        if (!CollectionUtils.isEmpty(errors)) {
            for (ObjectError error : errors) {
                ConstraintViolationImpl constraintViolation = error.unwrap(ConstraintViolationImpl.class);
                ConstraintDescriptor constraintDescriptor = constraintViolation.getConstraintDescriptor();
                constraintDescriptor.getAnnotation().annotationType();
                //特定注解
                if (ValidateWord.class.isAssignableFrom(constraintDescriptor.getAnnotation().annotationType())) {
                    String[] split = Objects.requireNonNull(error.getDefaultMessage()).split(",");
                    sensitiveSets.addAll(Arrays.asList(split));
                } else {
                    //其他异常
                    results.add(error.getDefaultMessage());
                }
            }
            if (!CollectionUtils.isEmpty(sensitiveSets)) {
                results.add(0, String.format("您所输入的内容中包含敏感词,请重新输入,敏感词:%s", String.join(" ", sensitiveSets)));
            }
        }
        return results.get(0);
    }
}

详细代码实现:项目实战—@Valid+自定义校验注解+全局异常处理器实现敏感词过滤

相关文章:

JAVA基础篇(4)-Validation验证框架
SpringBoot2.x—方法参数/返回值的注解版校验
JAVA基础篇(15)—自定义“通用型枚举参数”校验注解
SpringBoot2.x—方法参数/返回值的注解版校验(解决方法内事务不生效)
SpringBoot项目启动时校验@ConfigurationProperties注解(对于内部类的支持)
Spring进阶篇(9)- MethodValidationPostProcessor 后置处理器的运用

举报

相关推荐

0 条评论