前言

通常我们在开发的过程中,需要对前端传入的数据进行校验,尽管这一步已经在前端进行了一次校验,虽然现在已经有了很多校验的注解,@NotNull、@NotBlank、@URL等一系列注解帮助我们进行校验,但是在实际的业务开发过程中,这些可能不足以满足我们的需求,这时候我们就需要自己来定义注解了。

可能需要用到的依赖按需导入:

     <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.4.1.Final</version></dependency><dependency><groupId>org.jboss.logging</groupId><artifactId>jboss-logging</artifactId><version>3.3.0.Final</version></dependency><dependency><groupId>com.fasterxml</groupId><artifactId>classmate</artifactId><version>1.3.3</version></dependency>

@Constraint

这个注解的主要作用就是帮助我们来处理验证逻辑的,根据根据自己的业务需求来完成这一块验证的逻辑。下面我们就来简单测试一下。

**场景 **:假设我们一个实体类的属性如下解释,我们需要对前端传入的数字是不是0或1。

/*** 显示状态[0-不显示;1-显示]*/private Integer showStatus;

定义注解

@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {String message() default "{com.atguigu.common.valid.ListValue.message}";Class<?>[] groups() default {};int[] vals() default {};Class<? extends Payload>[] payload() default {};}

message():错误信息,如果我们没有在注解中定义错误信息的话,他会默认去寻找com.atguigu.common.valid.ListValue.message为key的错误信息
groups():这个主要是来进行分组验证的。
** vals() ** :自行定义的值

我们可以看到@Constraint中
@Constraint(validatedBy = {ListValueConstraintValidator.class})
这段意思是我们将此注解的验证逻辑交给ListValueConstraintValidator来处理,这里是一个数组,我们可以传入多个处理逻辑。

ConstraintValidator接口,它有两个泛型,第一个是自定义的注解类,第二个就是要验证的数据的类型,这两个类里面都有两个方法,initialize和isValid,第一个是初始化方法,第二个是验证的逻辑方法,返回true,则验证通过,否则则不通过。

ListValueConstraintValidator自定义验证逻辑

public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {private Set<Integer> set = new HashSet<>();/*** 初始化 加载注解的信息。也就是带有此注解Bean上的vals值* @param constraintAnnotation*/@Overridepublic void initialize(ListValue constraintAnnotation) {int[] vals = constraintAnnotation.vals();for (int val : vals) {set.add(val);}}/*** 判断是否校验成功* @param value 需要校验的值 实际传入的值* @param context 上下文信息* @return*/@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return set.contains(value);}
}

** ValidationMessages.properties **

规范(JSR303)说,我必须将ValidationMessages.properties放到我的类路径根目录中,我希望它应该是MyDeploymentUnit.war / WEB-INF / classes / ValidationMessages.properties,这就是我的应用程序的构建和部署方式。出于调试原因,我将此代码添加到了自定义验证器中,以确保文件存在并正确设置。


key就是我们在注解定义的默认 message的值。

测试

在Controller中需要进行校验的Bean加上 ** @Validated ** 注解

需要验证的 属性

这里的如果校验不通过的话,他会抛出一个异常,我们只需要捕获到这个错误信息即可。

如果我们去掉属性声明的message信息 他会去寻找默认的ValidationMessages.properties下的信息。

分组校验

可能大家会注意到我在Controller中使用 @Validated 注解时会带有一个value值,他的作用是对操作进行分组。比如请看如下

 @NotNull(message = "修改商品时请传入商品id",groups = {UpdateGroup.class})@Null(groups = {AddGroup.class},message = "不能指定id")@TableIdprivate Long brandId;

商品的数据表的对应的ID,我们可能在进行新增操作时无需我们来指定对应的ID,因为我们一般设置都会默认自增的。而我们在查询或者更新的时候可能会根据ID来查出这一条记录。总的来说的就是在进行更新时需要ID,新增不需要。每一个注解都会带有groups这个属性来声明自己的组。

如何使用呢?
很简单:

定义对应的接口或者类。

public interface AddGroup {}
// ------------------------------
public interface UpdateGroup {}
//---------------------------------
public interface UpdateStatusGroup {}

我们只需要定义三个接口来声明组,无需任何操作。

在Controller中的@Validated 注解中声明对那个组进行验证。

@RequestMapping("/save")public R save(@Validated(value = {AddGroup.class}) @RequestBody BrandEntity brand) {brandService.save(brand);return R.ok();}

实体类进行分组逻辑

 @NotNull(message = "修改商品时请传入商品id",groups = {UpdateGroup.class})@Null(groups = {AddGroup.class},message = "不能指定id")@TableIdprivate Long brandId;

验证: 新增时:传入ID会失败

更新时:不传ID 会失败

使用@Constraint配合自定义注解开发相关推荐

  1. Java自定义注解开发

    目录 一.JAVA注解 1.java注解的定义 2.java注解的分类 2.1 JDK基本注解 2.2 JDK元注解 2.3 自定义注解 3.注解分类 3.1标记Annotation: 3.2 元数据 ...

  2. springboot 自定义注解开发

    适用场景: 同一个实体类(User)在多个地方用到,但是属性password只能设置为符合指定规则的字符,此时我们有pc和app端两处入口可以维护user的这个attribute,假设两处入口走不同的 ...

  3. 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句

    使用Java反射(Reflect).自定义注解(Customer Annotation)生成简单SQL语句 这次给大家介绍一下在Java开发过程中 使用自定义注解开发: 主要知识点:          ...

  4. @requirespermissions注解是什么意思_如何基于spring开发自定义注解实现对接口访问频次限制?...

    做JavaWeb的开发的同学们都应该遇到过,客户要求某个接口进行频次的限制,如每秒并发10个,或者短信验证码发送场景,60秒内只允许发送一次. 通常开发的小伙伴们肯定是拿到以上需求在接口逻辑里进行实现 ...

  5. MyBatis-学习笔记04【04.自定义Mybatis框架基于注解开发】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

  6. 接口访问次数_如何基于spring开发自定义注解实现对接口访问频次限制?

    做JavaWeb的开发的同学们都应该遇到过,客户要求某个接口进行频次的限制,如每秒并发10个,或者短信验证码发送场景,60秒内只允许发送一次. 通常开发的小伙伴们肯定是拿到以上需求在接口逻辑里进行实现 ...

  7. 【开发随机】JAVA+POI+自定义注解+反射构建自定义工具类实现快捷简便的Excel模板化导出(附demo代码)

    220907更新 项目UAT期间,用户反映了一个问题,数据量稍大的情况下,会出现"从某一行开始,往下所有行设置的字体和字体大小不生效"的BUG. 经过排查,发现原因是:POI的XS ...

  8. pytest框架二次开发之自定义注解

    目录 一.背景: 二.闭包与装饰器(可以跳过这一章) 2.1 .什么是闭包 2.2 闭包的用途 2.3 .装饰器(decorator) 三.pytest自定义注解@author 3.1 自定义注解@a ...

  9. Spring自定义注解驱动开发使用及源码分析

    目录 前言 注解驱动开发使用 需求 代码实现 测试效果 源码分析 BeanDefinitionRegistryPostProcessor接口 解析BeanDefinition 处理Bean上配置的注解 ...

最新文章

  1. mysql windows乱码_小白楠--windows系统下mysql乱码
  2. Python项目中 封装日志模块logging 及快速调用方法
  3. VC 位图按钮CBitmapButton的使用
  4. docker mysql 阿里云_阿里云docker部署mysql
  5. 2016.7.15 NOIP2014模拟试题解题报告(又名:方克顺和他的正余弦朋友们(
  6. CodeSnippet.info 开源说明 和 环境搭建 (第一版)
  7. 学成在线案例(完整代码)
  8. 深度解读:2021 中国低代码平台发展现状
  9. 每日一问 --信源编码的过程?
  10. go语言调用c 的头文件 so,golang 学习(10): 使用go语言调用c语言的so动态库-Go语言中文社区...
  11. 不同超声诊断仪器的原理和FPGA在超声中应用
  12. 怎么清理手机空间不足?苹果手机全面清理内存教程
  13. C++ 开源库,很完整介绍【转】
  14. 网易云歌单信息爬取及数据分析(1)爬虫部分
  15. 有钱人的心肠更硬吗?
  16. 2003版excel 删除某列数据相同的行只保留一行的方法
  17. 透视HTTP协议-03|HTTP协议进阶(一)
  18. 史上最全的软件测试面试题
  19. 多重比较校正中的一些概念
  20. GIS空间分析实验教程期末重点1718

热门文章

  1. Android 每次插入U盘自动创建了不需要的文件夹
  2. RPC,你知道多少呢?
  3. 复盘:推荐系统—— 负采样策略
  4. spring与mybatis整合,数据库连接异常
  5. 利用av号爬取Bilibili视频弹幕
  6. 今日探讨:“片式裹包机”结构组成
  7. 我是怎么避免“信息茧房”的?
  8. list集合对象去除重复,值相加求和
  9. 公司固定资产(车辆)处置的流程以及分录
  10. 运动耳机买什么样的好、值得推荐的运动耳机