Bean Validator扩展

1、需求

​ 在使用validator时,有个需求就是公用错误提示信息,什么意思?

举个例子:

​ @NotEmpty非空判断,在资源文件中我不想每个非空判断都写”不能为空“,只需要写”###“,然后提示信息自动会变成”###不能为空“

代码:

public class User{//资源文件中user.name.empty=用户名@NotEmpty(key={user.name.empty})private String name;'''
}

//加入name为空,则最终的错误提示为“用户名不能为空”(会自动加上“不能为空”信息)

2、实现方式

有两种实现方式

方式一:手动调用验证方法
注解
@Target({FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@ReportAsSingleViolation
@Constraint(validatedBy = {})
@NotNull
@Size(min = 1)
public @interface NotEmpty {String message() default "{key}{com.chyjr.hyb.validator.constraints.empty.message}";
​Class<?>[] groups() default { };
​Class<? extends Payload>[] payload() default { };String key() default "";
}

验证器
//验证器
public class MyValidator {private static final Logger log = LoggerFactory.getLogger(HybValidator.class);private static Validator validator = null;private static MessageInterpolator msgInterpolator = null;static {if (validator == null) {LocalValidatorFactoryBean factory = (LocalValidatorFactoryBean) ApplicationContextUtil.getBean("validator");validator = factory.getValidator();msgInterpolator = factory.getMessageInterpolator();}}
​public static HybValidatorResult validate(Object object, Class<?>... groups) {HybValidatorResult result = new HybValidatorResult();Set<ConstraintViolation<Object>> violations = validator.validate(object, groups);Map<String, String> map = new HashMap<>();if (CollectionUtils.isEmpty(violations)) {result.setErrors(false);} else {result.setErrors(true);for (ConstraintViolation<Object> violation : violations) {String path = violation.getPropertyPath().toString();String message = violation.getMessage();if (StringUtils.isBlank(path) || StringUtils.isBlank(message) || map.containsKey(path))continue;message = resolveMessage(message);map.put(path, message);}result.setItems(map);}return result;}private static final Pattern elpattern = Pattern.compile("\\{[^{}]+\\}");private static String resolveMessage(String message) {Matcher matcher = elpattern.matcher(message);try {while (matcher.find()) {String el = matcher.group();//用资源文件信息替换message = {key}{my.empty.message}//注解这里的key会替换成注解NotEmpty定义的key,即//message = {user.name.empty}{my.empty.message}String val = msgInterpolator.interpolate(el, null);if (StringUtils.isBlank(val))continue;message = message.replace(el, val);}} catch (Exception e) {log.error("验证引擎进行数据校验时出现异常, message:{}", message, e);}return message;}
}

使用
//调用验证方法获得验证结果
 HybValidatorResult bvr = HybValidator.validate(emp, CreateValidator.class);//表示有错误if (bvr.isErrors()) {}
//资源文件内容
//my.empty.message=不能为空
//user.name.empty=用户名

方式二:用spring自带的@Validated,无需调用验证方法

这里有个问题:@Validated注解不认注解@NotEmpty中的key,如何解决呢?

最终的实现方案:自定义验证器

代码:

注解
@Documented
@Target({FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@ReportAsSingleViolation
//指定验证器
@Constraint(validatedBy = NotEmptyValidator.class)
public @interface NotEmpty {String message() default "{my.empty.message}";
​Class<?>[] groups() default { };
​Class<? extends Payload>[] payload() default { };String key() default "";
}

验证器:自定义
public class NotEmptyValidator extends AbstractValidator<NotEmpty,Object>{
​@Overridepublic void initialize(NotEmpty notEmpty) {
​}
​@Overridepublic boolean doIsValid(Object value, ConstraintValidatorContext cc) {return value != null;}
}
​
/**
* 这里采用模板的设计模式
* @param constraintAnnotation
*/
public abstract class AbstractValidator<A extends Annotation,T> implements ConstraintValidator<A,T>{
​/*** 初始化由具体类实现* @param constraintAnnotation*/@Overridepublic abstract void initialize(A constraintAnnotation);
​/*** 初始化具体由实现类实现* @param value* @param context* @return*/@Overridepublic boolean isValid(T value, ConstraintValidatorContext context){//获取验证结果,采用模板方法boolean result = doIsValid(value,context);//当验证错误时修改默认信息if(!result){//改变默认提示信息if(ConstraintValidatorContextImpl.class.isAssignableFrom(context.getClass())){ConstraintValidatorContextImpl constraintValidatorContext = (ConstraintValidatorContextImpl)context;//获取默认提示信息String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();Object key = constraintValidatorContext.getConstraintDescriptor().getAttributes().get("key");//禁用默认提示信息
                context.disableDefaultConstraintViolation();//设置提示语(在message前面加上key)context.buildConstraintViolationWithTemplate(key +                                          defaultConstraintMessageTemplate).addConstraintViolation();}}
​return result;}/*** 真正验证方法* @param value* @param context* @return*/public abstract boolean doIsValid(T value, ConstraintValidatorContext context);
}

使用:

调用的时候只要在JavaBean前加上@Validated注解即可

总结:上述就是在工作中遇到的问题,并扩展了Validator

转载于:https://www.cnblogs.com/liruiloveparents/p/9378264.html

Springboot集成BeanValidation扩展一:错误提示信息加公共模板相关推荐

  1. Springboot集成BeanValidation扩展二:加载jar中的资源文件

    一.需求 今天在搭建Springboot框架的时候,又遇到一个需求:在多模块系统中,有些模块想自己管理BeanValidation的资源文件(默认是启动项目claspath下的 ValidationM ...

  2. springboot集成mybatis源码分析-启动加载mybatis过程(二)

    springboot集成mybatis源码分析-启动加载mybatis过程(二) 1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplicati ...

  3. py程序可以运行,但打包出的exe运行提示错误:加载“cv2”二进制扩展时检测到递归。请检查OpenCV安装。

    py程序里包含有 from pdf2docx import Converter 没有封装之前可以正常运行,但是封装成exe后,运行时闪退.我快速复制下报错的内容. raise ImportError( ...

  4. springboot集成 security 更改中英文提示信息

    如图显示,输入错误密码,提示为英文 springsecurity包下有自带的语言资源包 我们通过自定义messageSource,返回中文的配置文件 //security中文提示信息配置类 @Conf ...

  5. springboot项目启动时提示错误: 找不到或无法加载主类

    问题: springboot项目启动时提示错误: 找不到或无法加载主类 解决方法:

  6. SpringBoot集成Elasticsearch7.4 实战(一)

    在网上已经有好多关于Elasticsearch的介绍,就不在翻来覆去讲一些基本概念,大家感兴趣的可以自己去找一些资料巩固下.这次只为了顾及众多首次接触Elasticsearch,案例都讲的很浅显,还有 ...

  7. kafka(组件分析 整合springboot集成 实战)

    kafka 组件 搭建 springboot集成 实战 kafka 组件 搭建 springboot集成 实战 1.应用场景 1.1 kafka场景 1.2 kafka特性 1.3 消息对比 1.4 ...

  8. ES入门学习:ElasticSearch、Kibana、ik分词器的安装、简单使用及SpringBoot集成

    前言 es是采用Java语言开发,因此,想要安装运行es需要提前准备好jdk环境,关于linux配置jdk在前文linux配置jdk 本文主要介绍es的安装.kibana的安装和简单使用及ik分词器的 ...

  9. Springboot集成Flyway(适用于多数据源)

    1. Flyway 可以将初始化sql在项目启动时候执行,取代单独的DBN更新包 2. 依赖 <dependency><groupId>org.flywaydb</gro ...

最新文章

  1. 几分钟让小孩的人物涂鸦「动起来」,Meta AI创建了一个奇妙的火柴人世界
  2. java args例子_Spring AOP中使用args表达式的方法示例
  3. matlab vector用法,C++ vector 用法汇总
  4. python定义字符串1hdhdjdjd_python基础总结(字符串)
  5. 查看用户账户过期信息
  6. selenium 鼠标悬浮_处理Selenium3+python3定位鼠标悬停才显示的元素
  7. arm for asterisk1.8
  8. C++字符串的个人理解
  9. 十三、JSP9大隐视对象中四个作用域的大小与作用范围
  10. Leetcode-区域和检索-数组不可变
  11. Python 爬虫 —— 网页内容解析(lxml)
  12. python充分理解def语句
  13. tp5使用RabbitMQ的使用记录
  14. 【每日一题】打卡 14
  15. Linux tail命令的使用方法详解
  16. 【嵌入式软件开发岗位 ---- 面试总结01】
  17. 音频之WAV格式编码解析
  18. 谈谈 微软 鲍尔默退休,他错在哪里?该怎么做!
  19. Springboot 小巧简便的限流器使用 RateLimiter
  20. 视频大数据存储平台解决方案(ppt)

热门文章

  1. 老男孩mysql参数配置_MySQL启动相关参数解析
  2. pymssql mysql_Python利用pymssql访问mysql数据库
  3. 远程管理口怎么看地址_红烧羊肉怎么样做才能滋味浓郁,咸甜适口,且回味有奶香?看这里...
  4. android让一个控件跟上面控件对其,学个明白--Android控件架构
  5. 逆水寒服务器维护7.5,逆水寒7.26日维护到什么时候 逆水寒7.26日游戏改动汇总介绍...
  6. Linux 命令行上执行多个命令(分隔符简介使用)
  7. 力扣35. 搜索插入位置
  8. c# 无法将类型隐式转换_C#中的隐式类型数组
  9. python程序执行时间_用于在Python中查找程序执行时间的程序
  10. Java Thread类的静态布尔型interrupted()方法(带示例)