在项目开发中许多地方需要加以验证,对于使用if-else简单粗暴一个一个验证,spring的validation封装了Javax ValidationI校验参数,大大缩减了代码量。

以前的分层验证,从controller到落入数据库,一层一层验证,代码重复、冗余。

Javax ValidationI使用Java Bean验证通过注解将约束添加到域模型中,将验证逻辑从代码中分离出来。

Javax ValidationI的依赖:

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>

  

springboot对Javax ValidationI封装,依赖变成

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

 一、初级注解

JSR提供的验证注解:

@Null   被注释的元素必须为 null

@NotNull    被注释的元素必须不为 null

@AssertTrue     被注释的元素必须为 true

@AssertFalse    被注释的元素必须为 false

@Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值   &nbsp

@Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值

@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@Size(max=, min=)   被注释的元素的大小必须在指定的范围内

@Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内

@Past   被注释的元素必须是一个过去的日期

@Future     被注释的元素必须是一个将来的日期

@Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式

Validator提供的验证注解:

@NotBlank(message =)   验证字符串非null,且长度必须大于0

@Email  被注释的元素必须是电子邮箱地址

@Length(min=,max=)  被注释的字符串的大小必须在指定的范围内

@NotEmpty   被注释的字符串的必须非空

@Range(min=,max=,message=)  被注释的元素必须在合适的范围内

二、创建验证器

/**
* 验证测试类
*/
public class ValidationTest { // 验证器对象
private Validator validator;
// 待验证对象
private UserInfo userInfo;
// 验证结果集合
private Set<ConstraintViolation<UserInfo>> set; /**
* 初始化操作
*/
@Before
public void init() {
// 初始化验证器
validator = Validation.buildDefaultValidatorFactory()
.getValidator(); // 初始化待验证对象 - 用户信息
userInfo = new UserInfo(); } /**
* 结果打印
*/
@After
public void print() {
set.forEach(item -> {
// 输出验证错误信息
System.out.println(item.getMessage());
}); } @Test
public void nullValidation() {
// 使用验证器对对象进行验证
set = validator.validate(userInfo);
} }

  三、中级约束

    中级约束中分为分组约束、组序列

public class UserInfo {

    // 登录场景
public interface LoginGroup {} // 注册场景
public interface RegisterGroup {} /**
* 用户ID
*/
@NotNull(message = "用户ID不能为空",
groups = LoginGroup.class)
private String userId; /**
* 用户名
* NotEmpty 不会自动去掉前后空格
*/
@NotEmpty(message = "用户名称不能为空",groups = RegisterGroup.class)
private String userName; /**
* 用户密码
* NotBlank 自动去掉字符串前后空格后验证是否为空
*/
@NotBlank(message = "用户密码不能为空")
@Length(min = 6, max = 20,
message = "密码长度不能少于6位,多于20位")
private String passWord; }

  

  /**
* 分组验证测试方法
*/
@Test
public void groupValidation() {
set = validator.validate(userInfo,
UserInfo.RegisterGroup.class,
UserInfo.LoginGroup.class);
}

  组排序:

public class UserInfo {

    // 登录场景
public interface LoginGroup {} // 注册场景
public interface RegisterGroup {} // 组排序场景
@GroupSequence({
LoginGroup.class,
RegisterGroup.class,
Default.class
})
public interface Group {} /**
* 用户ID
*/
@NotNull(message = "用户ID不能为空",
groups = LoginGroup.class)
private String userId; /**
* 用户名
* NotEmpty 不会自动去掉前后空格
*/
@NotEmpty(message = "用户名称不能为空",
groups = RegisterGroup .class)
private String userName; /**
* 用户密码
* NotBlank 自动去掉字符串前后空格后验证是否为空
*/
@NotBlank(message = "用户密码不能为空")
@Length(min = 6, max = 20,
message = "密码长度不能少于6位,多于20位")
private String passWord;
}

  

    /**
* 组序列测试
*/
@Test
public void groupSequenceValidation() {
set = validator.validate(userInfo,
UserInfo.Group.class);
}

  三、高级约束

    高级约束是对参数、返回值的约束。

    使用注解:

      javax:@Valid

      spring:@Validated

    在检验参数、返回值是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同。

    @Validated:提供了一个分组功能,可以在入参、返回值验证时,根据不同的分组采用不同的验证机制。

    @Valid:不支持分组功能。

    注解地方:

    @Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上。

    @Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上。

/**
* 用户信息
*/
public class UserInfoService { /**
* UserInfo 作为输入参数
* @param userInfo
*/
public void setUserInfo(@Valid UserInfo userInfo) {} /**
* UserInfo 作为输出参数
* @return
*/
public @Valid UserInfo getUserInfo() {
return new UserInfo();
} }

  

/**
* 验证测试类
*/
public class ValidationTest { // 验证器对象
private Validator validator;
// 待验证对象
private UserInfo userInfo;
// 验证结果集合
private Set<ConstraintViolation<UserInfoService>> otherSet; /**
* 初始化操作
*/
@Before
public void init() {
// 初始化验证器
validator = Validation.buildDefaultValidatorFactory()
.getValidator(); // 初始化待验证对象 - 用户信息
userInfo = new UserInfo();
} /**
* 结果打印
*/
@After
public void print() {
set.forEach(item -> {
// 输出验证错误信息
System.out.println(item.getMessage());
}); } /**
* 对方法输入参数进行约束注解校验
*/
@Test
public void paramValidation() throws NoSuchMethodException {
// 获取校验执行器
ExecutableValidator executableValidator =
validator.forExecutables(); // 待验证对象
UserInfoService service = new UserInfoService();
// 待验证方法
Method method = service.getClass()
.getMethod("setUserInfo", UserInfo.class);
// 方法输入参数
Object[] paramObjects = new Object[]{new UserInfo()}; // 对方法的输入参数进行校验
otherSet = executableValidator.validateParameters(
service,
method,
paramObjects);
} /**
* 对方法返回值进行约束校验
*/
@Test
public void returnValueValidation()
throws NoSuchMethodException,
InvocationTargetException, IllegalAccessException { // 获取校验执行器
ExecutableValidator executableValidator =
validator.forExecutables(); // 构造要验证的方法对象
UserInfoService service = new UserInfoService();
Method method = service.getClass()
.getMethod("getUserInfo"); // 调用方法得到返回值
Object returnValue = method.invoke(service); // 校验方法返回值是否符合约束
otherSet = executableValidator.validateReturnValue(
service,
method,
returnValue);
} }

  在controller中验证入参一般使用@Validated

@RequestMapping(method = RequestMethod.POST)
public UserInfo create(@RequestBody @Validated( { RegisterGroup.class }) UserInfo userInfo) {
return userService.create(userInfo);
} @RequestMapping(method = RequestMethod.GET)
public UserInfo getUserById(@NotNull(message = "id不能为空") int userId) {
return userService.getUserById(userId);
}

  四、自定义约束注解

/**
* 自定义手机号约束注解
*/
@Documented
// 注解的作用目标
@Target({ElementType.FIELD})
// 注解的保留策略
@Retention(RetentionPolicy.RUNTIME)
// 不同之处:于约束注解关联的验证器
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone { // 约束注解验证时的输出信息
String message() default "手机号校验错误"; // 约束注解在验证时所属的组别
Class<?>[] groups() default {}; // 约束注解的有效负载(严重程度)
Class<? extends Payload>[] payload() default {};
}

  

/**
* 自定义手机号约束注解关联验证器
*/
public class PhoneValidator
implements ConstraintValidator<Phone, String> { /**
* 自定义校验逻辑方法
* @param value
* @param context
* @return
*/
@Override
public boolean isValid(String value,
ConstraintValidatorContext context) { // 手机号验证规则:158后头随便
String check = "158\\d{8}";
Pattern regex = Pattern.compile(check); // 空值处理
String phone = Optional.ofNullable(value).orElse("");
Matcher matcher = regex.matcher(phone); return matcher.matches();
}
}

  自定义注解使用:

public class UserInfo{
/**
* 手机号
*/
@Phone(message = "手机号不是158后头随便")
private String phone;
}

  

学习Validator验证框架总结的更多相关文章

  1. Validator验证框架

    Validator验证框架 系统分析 在设计Validator验证框架时,需要明确以下问题. (1)当用户没有输入数据时,弹出英文提示信息. (2)当用户输入的数据长度大于系统设置的数据长度,弹出英文 ...

  2. Hibernate Validator验证框架中@NotEmpty、@NotBlank、@NotNull 的区别

    Hibernate Validator验证框架中@NotEmpty.@NotBlank.@NotNull的主要使用情况 @NotEmpty  用在集合类上面 @NotBlank   用在String上 ...

  3. spring MVC 使用 hibernate validator验证框架,国际化配置

    spring mvc使用hibernate validator框架可以实现的功能: 1. 注解java bean声明校验规则. 2. 添加message错误信息源实现国际化配置. 3. 结合sprin ...

  4. SAR-303 xml validator验证框架

    // 配置文件详解 <mvc:annotation-driven validator="validator" /> <bean id="validato ...

  5. hibernate validate验证框架中@NotEmpty、@NotbBank、@NotNull的区别

    Hibernate Validator验证框架中@NotEmpty.@NotBlank.@NotNull 的区别 Hibernate Validator验证框架中@NotEmpty.@NotBlank ...

  6. struts2学习笔记(三)—— 在用户注冊程序中使用验证框架

    实现目标:       1.使用验证框架对用户注冊信息进行验证       2.验证username.password.邮箱不能为空       3.验证username.password长度     ...

  7. vue学习记录:vue引入,validator验证,数据信息,vuex数据共享

    最近在学习vue,关于学习过程中所遇到的问题进行记录,包含vue引入,validator验证,数据信息,vuex数据共享,传值问题记录 1.vue 引入vue vue的大致形式如下: <temp ...

  8. (七)Struts2 验证框架

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:Struts2 验证简介 Struts2 基于Struts2 拦截器,为 ...

  9. 【转】Struts2 表单验证与验证框架

    版权声明:好笔头不如烂记性 https://blog.csdn.net/zsbgood/article/details/81114038 表单数据验证是很常见的功能,通常前端页面会有一次 js验证,但 ...

随机推荐

  1. Helium文档11-WebUI自动化-attach_file上传文件或图片

    前言 attach_file关键字根据官方介绍的作用是上传文件 入参介绍 def attach_file(file_path, to=None): """ :param ...

  2. 技术实操丨HBase 2.X版本的元数据修复及一种数据迁移方式

    摘要:分享一个HBase集群恢复的方法. 背景 在HBase 1.x中,经常会遇到元数据不一致的情况,这个时候使用HBCK的命令,可以快速修复元数据,让集群恢复正常. 另外HBase数据迁移时,大家经 ...

  3. JS之关于函数

    Javascript的函数也是一个对象 function test() { ... } var test = function(){ ... } 函数内部一旦执行return,则函数执行完毕,如果没有 ...

  4. PHP实现Bitmap的探索 - GMP扩展使用

    原文地址:https://blog.fanscore.cn/p/22/ 一.背景 公司当前有一个用户群的系统,核心功能是根据不同的条件组去不同的业务线中get符合条件的uid列表,然后存到redis中 ...

  5. I-Isolated Pointset

    题意:给定T组数据,每组数据有一个数n,表示点集的个数,问是否存在一个点数为n的点集,使得任意两个点组成的边的垂直平分线过点集中的第三个点 本题非常巧妙,只需构造一个由(n-2)个相同共点(圆心)等边 ...

  6. tomcat 启动失败

    1.tomcat单独通过脚本可以启动,但是http://localhost:8080加载页面失败 tomcat 启动失败: a.检查JAVA_HOME和CATALINA_HOME是否配置正确:或者直接 ...

  7. 数据结构(C++)——顺序表

    顺序表和链表的比较 1.存取方式 顺序表可以随机访问,而链表只能从表头顺序查找.(因此经常查找顺序表某一个元素时,顺序表更适合) 2.逻辑结构与物理结构 顺序表中,逻辑上相邻的元素,其物理存储位置也相 ...

  8. 群晖DS218+部署kafka

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  9. 【开源】使用.Net Core和GitHub Actions实现哔哩哔哩每日自动签到、投币、领取奖励

    BiliBiliTool是一个B站自动执行任务的工具,使用.NET Core编写,通过它可以实现B站帐号的每日自动观看.分享.投币视频,获取经验,每月自动领取会员权益.自动为自己充电等功能,帮助我们轻 ...

  10. 容器之间通讯方式\与pod关系

    1.概述 k8s里面容器是存在于pod里面的,所以容器之间通讯,一般分为三种类型:1. pod内部容器之间 2. pod 与 pod 容器之间 3. pod 访问service服务 (1) pod内部 ...