上文测试开发专题:如何在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自定义参数校验注解的更多相关文章

  1. spring boot+自定义 AOP 实现全局校验

    最近公司重构项目,重构为最热的微服务框架 spring boot, 重构的时候遇到几个可以统一处理的问题,也是项目中经常遇到,列如:统一校验参数,统一捕获异常... 仅凭代码 去控制参数的校验,有时候 ...

  2. Spring Boot 2.X(四):Spring Boot 自定义 Web MVC 配置

    0.准备 Spring Boot 不仅提供了相当简单使用的自动配置功能,而且开放了非常自由灵活的配置类.Spring MVC 为我们提供了 WebMvcConfigurationSupport 类和一 ...

  3. 玩转Spring Boot 自定义配置、导入XML配置与外部化配置

    玩转Spring Boot 自定义配置.导入XML配置与外部化配置       在这里我会全面介绍在Spring Boot里面如何自定义配置,更改Spring Boot默认的配置,以及介绍各配置的优先 ...

  4. Spring boot 自定义 Resolver 支持 interface 类型参数

    在编写 RestController 层的代码时,由于数据实体类定义了接口及实现类,本着面向接口编程的原则,我使用了接口作为 RestController 方法的入参. 代码大致如下(省略具体业务部分 ...

  5. Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践

    Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践 本篇博文主要提供一个在 SpringBoot 中自定义 kafka配置的实践,想象这样一个场景:你的系统 ...

  6. Spring Boot自定义starter必知必会条件

    前言 在目前的Spring Boot框架中,不管是Spring Boot官方还是非官方,都提供了非常多的starter系列组件,助力开发者在企业应用中的开发,提升研发人员的工作效率,Spring Bo ...

  7. spring boot自定义线程池以及异步处理

    spring boot自定义线程池以及异步处理@Async:什么是线程池?线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使 ...

  8. Spring boot 配置文件参数映射到配置类属性

    [参考文章]:SpringBoot之@EnableConfigurationProperties分析 [参考文章]:在Spring Boot中使用 @ConfigurationProperties 注 ...

  9. Spring Boot自定义配置与加载

    Spring Boot自定义配置与加载 application.properties主要用来配置数据库连接.日志相关配置等.除了这些配置内容之外,还可以自定义一些配置项,如: my.config.ms ...

  10. Spring Boot自定义Redis缓存配置,保存value格式JSON字符串

    Spring Boot自定义Redis缓存,保存格式JSON字符串 部分内容转自 https://blog.csdn.net/caojidasabi/article/details/83059642 ...

随机推荐

  1. Java优秀教程

    1.java中局部变量是在栈上分配的: 2.数组是储存在堆上的对象,可以保存多个同类型变量: 3.在Java语言中,所有的变量在使用前必须声明. 4.局部变量没有默认值,所以局部变量被声明后,必须经过 ...

  2. [转+自]disable_functions之巧用LD_PRELOAD突破

    写在前面: 通过知乎的一篇艰难的渗透提权,引发了一些对于disable_funcionts绕过的思考,虽然在暑假日记中记载了四种绕过disable_functions,比如com组件,pcntl_ex ...

  3. MergeSort归并排序和利用归并排序计算出数组中的逆序对

    首先先上LeetCode今天的每日一题(面试题51. 数组中的逆序对): 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. ...

  4. 如何将Python项目发布到PyPI

    The Python Package Index (PyPI) is a repository of software for the Python programming language. 如何打 ...

  5. Java的自动装箱

    JDK5的新特性自动装箱:把基本类型转换为包装类类型自动拆箱:把包装类类型转换为基本类型 注意一个小问题: 在使用时,Integer x = null;代码就会出现NullPointerExcepti ...

  6. Java 反射调用方法 - 不跳过安全检查、跳过安全检查和普通方法性能比较测试

    java中反射提供灵活性同时,给运行效率带来了一定影响.写个代码测试一下 package com.xzlf.reflectTest; import java.lang.reflect.Method; ...

  7. 反转链表-PHP的实现

    <? //节点 class Node { private $Data;//节点数据 private $Next;//下一节点 public function setData($value) { ...

  8. java传参问题

    参考链接:https://www.cnblogs.com/linkstar/p/5951141.html public class Example { String testString = publ ...

  9. 安装和使用redis

    我现在只是在window上使用redis在其他平台上暂时没有操作过,如果你有其他好的意见欢迎提出来! 安装redis具体可查看:http://www.runoob.com/redis/redis-in ...

  10. Spring Boot JPA 中transaction的使用

    文章目录 @Transactional的实现 @Transactional的使用 Transaction的传播级别 REQUIRED SUPPORTS MANDATORY NEVER NOT_SUPP ...