Validation验证框架实现自定义注解时,我们想动态的返回异常信息,那么如何实现?
一般Validation注解,存在一个message属性,当校验异常时,会将message的信息抛出。
1. 需求背景
需求:一个实体类中多个字段使用@ValidationXXX注解来校验多个字段的合法性。到出现异常时:
- 动态的输出异常信息;
- 将多个字段信息合并输出(且需要按照文档描述输出)。
2. 实现方案
采用的是SpringMVC框架下的@Valid+自定义注解+全局异常处理器实现。
2.1 自定义校验注解
存在message属性,当字段出现异常时,会抛出message配置的信息。
@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;
}
}
}
关键点:
- 禁止默认的
message
属性输出。 -
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 后置处理器的运用
网友评论