使用@Constraint配合自定义注解开发
前言
通常我们在开发的过程中,需要对前端传入的数据进行校验,尽管这一步已经在前端进行了一次校验,虽然现在已经有了很多校验的注解,@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配合自定义注解开发相关推荐
- Java自定义注解开发
目录 一.JAVA注解 1.java注解的定义 2.java注解的分类 2.1 JDK基本注解 2.2 JDK元注解 2.3 自定义注解 3.注解分类 3.1标记Annotation: 3.2 元数据 ...
- springboot 自定义注解开发
适用场景: 同一个实体类(User)在多个地方用到,但是属性password只能设置为符合指定规则的字符,此时我们有pc和app端两处入口可以维护user的这个attribute,假设两处入口走不同的 ...
- 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句
使用Java反射(Reflect).自定义注解(Customer Annotation)生成简单SQL语句 这次给大家介绍一下在Java开发过程中 使用自定义注解开发: 主要知识点: ...
- @requirespermissions注解是什么意思_如何基于spring开发自定义注解实现对接口访问频次限制?...
做JavaWeb的开发的同学们都应该遇到过,客户要求某个接口进行频次的限制,如每秒并发10个,或者短信验证码发送场景,60秒内只允许发送一次. 通常开发的小伙伴们肯定是拿到以上需求在接口逻辑里进行实现 ...
- MyBatis-学习笔记04【04.自定义Mybatis框架基于注解开发】
Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...
- 接口访问次数_如何基于spring开发自定义注解实现对接口访问频次限制?
做JavaWeb的开发的同学们都应该遇到过,客户要求某个接口进行频次的限制,如每秒并发10个,或者短信验证码发送场景,60秒内只允许发送一次. 通常开发的小伙伴们肯定是拿到以上需求在接口逻辑里进行实现 ...
- 【开发随机】JAVA+POI+自定义注解+反射构建自定义工具类实现快捷简便的Excel模板化导出(附demo代码)
220907更新 项目UAT期间,用户反映了一个问题,数据量稍大的情况下,会出现"从某一行开始,往下所有行设置的字体和字体大小不生效"的BUG. 经过排查,发现原因是:POI的XS ...
- pytest框架二次开发之自定义注解
目录 一.背景: 二.闭包与装饰器(可以跳过这一章) 2.1 .什么是闭包 2.2 闭包的用途 2.3 .装饰器(decorator) 三.pytest自定义注解@author 3.1 自定义注解@a ...
- Spring自定义注解驱动开发使用及源码分析
目录 前言 注解驱动开发使用 需求 代码实现 测试效果 源码分析 BeanDefinitionRegistryPostProcessor接口 解析BeanDefinition 处理Bean上配置的注解 ...
最新文章
- mysql windows乱码_小白楠--windows系统下mysql乱码
- Python项目中 封装日志模块logging 及快速调用方法
- VC 位图按钮CBitmapButton的使用
- docker mysql 阿里云_阿里云docker部署mysql
- 2016.7.15 NOIP2014模拟试题解题报告(又名:方克顺和他的正余弦朋友们(
- CodeSnippet.info 开源说明 和 环境搭建 (第一版)
- 学成在线案例(完整代码)
- 深度解读:2021 中国低代码平台发展现状
- 每日一问 --信源编码的过程?
- go语言调用c 的头文件 so,golang 学习(10): 使用go语言调用c语言的so动态库-Go语言中文社区...
- 不同超声诊断仪器的原理和FPGA在超声中应用
- 怎么清理手机空间不足?苹果手机全面清理内存教程
- C++ 开源库,很完整介绍【转】
- 网易云歌单信息爬取及数据分析(1)爬虫部分
- 有钱人的心肠更硬吗?
- 2003版excel 删除某列数据相同的行只保留一行的方法
- 透视HTTP协议-03|HTTP协议进阶(一)
- 史上最全的软件测试面试题
- 多重比较校正中的一些概念
- GIS空间分析实验教程期末重点1718