更加灵活的参数校验,Spring-boot自定义参数校验注解
上文测试开发专题:如何在spring-boot中进行参数校验,我们讨论了如何使用@Min、@Max等注解进行参数校验,主要是针对基本数据类型和级联对象进行参数校验的演示,但是在实际中我们往往需要更为复杂的校验规则,比如注册用户的密码和确认密码进行校验,这个时候基本的注解就无法满足我们的要求了,需要去按照业务需求去自定义注解进行校验
元注解
在自定义注解之前我们有必要了解一些元注解,元注解就是在注解上的注解,可以对一个注解进行配置,元注解包括@Retention、@Target、@Document、@Inherited四种
@Retention,表示注解保留到什么时候,有以下三种模式
- @Retention(RetentionPolicy.SOURCE) 表示注解仅存在于源码中,在class字节码文件中不包含
- @Retention(RetentionPolicy.CLASS) 表示 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
- @Retention(RetentionPolicy.RUNTIME) 表示注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target表示注解的作用目标是什么,只列出下面几个,剩余的大家自行谷歌把
- @Target(ElementType.TYPE) 表示注解可以应用于接口、类、枚举、注解
- @Target(ElementType.FIELD) 表示可以应用于字段、成员变量、枚举的常量等
- @Target(ElementType.METHOD)表示可以作用于方法
@Document表示注解包含在javadoc中
@Inherited表示注解可以被继承
自定义校验注解
就以用户注册为例,我们需要校验密码和确认密码是否一致以及是否符合密码的规则,先新建一个PasswordEqual注解类
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Constraint(validatedBy = PasswordValidator.class)
public @interface PasswordEqual {
String message() default "密码不一样";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
下面我们来解释一下上面的注解,在PasswordEqual注解上,又标记了四个注解,前三个我们上面已经说过了。
这里说一下@Constraint注解,它表示这个注解是一个验证注解,并且通过validatedBy指定自定义校验注解的关联类,PasswordValidator类就是我们自定义的注解关联的类。
注解里面的groups和payload方法是模板方法,实现自定义注解必须写这么两个方法。
定义验证类
验证类里面包含具体的验证逻辑了,下面是一个简版的:
public class PasswordValidator implements ConstraintValidator<PasswordEqual, BannerCreateDto> {
@Override
public boolean isValid(BannerCreateDto dto, ConstraintValidatorContext constraintValidatorContext) {
return false;
}
}
这里需要对上面的代码进行一下说明,实现自定义校验类必须实现
ConstraintValidator接口,它是一个泛型接口,需要指定两个类型参数,第一个是自定义注解类型,第二个类型指定自定义注解修饰目标的类型,就是准备把自定义注解标记到什么类型上面。
必须重写isValid方法,所有的校验逻辑都在这个方法里面,下面我们简单写一下:
@Override
public boolean isValid(UserDto dto, ConstraintValidatorContext constraintValidatorContext) {
if (dto.getPassword().equals(dto.getConfirmPassword())){
return true;
}
return false;
}
然后我们将自定义的注解类标记到UserDto类上:
@Builder
@Getter
@Setter
@PasswordEqual
public class UserDto {
@Length(min = 4, max = 10, message = "用户名长度必须在4-10个字符之间")
private String name;
private String password;
private String confirmPassword;
}
接下来我们在写一个简单的创建用户的接口:
@RestController
public class UserController {
@PostMapping("/v2/user/create")
@ResponseBody
public UserDto createUser(@RequestBody @Validated UserDto dto){
return dto;
}
}
注意这里有要使用@ResponseBody能够返回自动序列化自定义对象,并且要写上 @Validated开启校验机制。
我们先输入正确的密码和确认密码一下:

可以看到能够正常的返回数据,这时再把两个密码改的不一样,试试:

这个时候就抛出了异常,这里的异常信息是因为进了全局异常处理器,不清楚的童鞋可以看下之前的文章。我们再来看一下控制台的输出:

控制台已经输出了校验的错误信息。
总结
我们今天介绍了自定义参数校验,并编写了校验注解和校验类,但是最后返回给用户的信息非常不友好,需要针对参数校验错误,能够返回定义的message,能够让有用户明白是哪里错了,下篇文章我们将介绍这块的内容,敬请关注!!
欢迎大家去 我的博客 瞅瞅,里面有更多关于测试实战的内容哦!!
更加灵活的参数校验,Spring-boot自定义参数校验注解的更多相关文章
- spring boot+自定义 AOP 实现全局校验
最近公司重构项目,重构为最热的微服务框架 spring boot, 重构的时候遇到几个可以统一处理的问题,也是项目中经常遇到,列如:统一校验参数,统一捕获异常... 仅凭代码 去控制参数的校验,有时候 ...
- Spring Boot 2.X(四):Spring Boot 自定义 Web MVC 配置
0.准备 Spring Boot 不仅提供了相当简单使用的自动配置功能,而且开放了非常自由灵活的配置类.Spring MVC 为我们提供了 WebMvcConfigurationSupport 类和一 ...
- 玩转Spring Boot 自定义配置、导入XML配置与外部化配置
玩转Spring Boot 自定义配置.导入XML配置与外部化配置 在这里我会全面介绍在Spring Boot里面如何自定义配置,更改Spring Boot默认的配置,以及介绍各配置的优先 ...
- Spring boot 自定义 Resolver 支持 interface 类型参数
在编写 RestController 层的代码时,由于数据实体类定义了接口及实现类,本着面向接口编程的原则,我使用了接口作为 RestController 方法的入参. 代码大致如下(省略具体业务部分 ...
- Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践
Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践 本篇博文主要提供一个在 SpringBoot 中自定义 kafka配置的实践,想象这样一个场景:你的系统 ...
- Spring Boot自定义starter必知必会条件
前言 在目前的Spring Boot框架中,不管是Spring Boot官方还是非官方,都提供了非常多的starter系列组件,助力开发者在企业应用中的开发,提升研发人员的工作效率,Spring Bo ...
- spring boot自定义线程池以及异步处理
spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...
- Spring boot 配置文件参数映射到配置类属性
[参考文章]:SpringBoot之@EnableConfigurationProperties分析 [参考文章]:在Spring Boot中使用 @ConfigurationProperties 注 ...
- Spring Boot自定义配置与加载
Spring Boot自定义配置与加载 application.properties主要用来配置数据库连接.日志相关配置等.除了这些配置内容之外,还可以自定义一些配置项,如: my.config.ms ...
- Spring Boot自定义Redis缓存配置,保存value格式JSON字符串
Spring Boot自定义Redis缓存,保存格式JSON字符串 部分内容转自 https://blog.csdn.net/caojidasabi/article/details/83059642 ...
随机推荐
- Java优秀教程
1.java中局部变量是在栈上分配的: 2.数组是储存在堆上的对象,可以保存多个同类型变量: 3.在Java语言中,所有的变量在使用前必须声明. 4.局部变量没有默认值,所以局部变量被声明后,必须经过 ...
- [转+自]disable_functions之巧用LD_PRELOAD突破
写在前面: 通过知乎的一篇艰难的渗透提权,引发了一些对于disable_funcionts绕过的思考,虽然在暑假日记中记载了四种绕过disable_functions,比如com组件,pcntl_ex ...
- MergeSort归并排序和利用归并排序计算出数组中的逆序对
首先先上LeetCode今天的每日一题(面试题51. 数组中的逆序对): 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. ...
- 如何将Python项目发布到PyPI
The Python Package Index (PyPI) is a repository of software for the Python programming language. 如何打 ...
- Java的自动装箱
JDK5的新特性自动装箱:把基本类型转换为包装类类型自动拆箱:把包装类类型转换为基本类型 注意一个小问题: 在使用时,Integer x = null;代码就会出现NullPointerExcepti ...
- Java 反射调用方法 - 不跳过安全检查、跳过安全检查和普通方法性能比较测试
java中反射提供灵活性同时,给运行效率带来了一定影响.写个代码测试一下 package com.xzlf.reflectTest; import java.lang.reflect.Method; ...
- 反转链表-PHP的实现
<? //节点 class Node { private $Data;//节点数据 private $Next;//下一节点 public function setData($value) { ...
- java传参问题
参考链接:https://www.cnblogs.com/linkstar/p/5951141.html public class Example { String testString = publ ...
- 安装和使用redis
我现在只是在window上使用redis在其他平台上暂时没有操作过,如果你有其他好的意见欢迎提出来! 安装redis具体可查看:http://www.runoob.com/redis/redis-in ...
- Spring Boot JPA 中transaction的使用
文章目录 @Transactional的实现 @Transactional的使用 Transaction的传播级别 REQUIRED SUPPORTS MANDATORY NEVER NOT_SUPP ...