java的validation框架(参数校验)

news2024/12/23 13:42:25

一.bean validation和hibernate validator参数校验常用约束注解:

空值校验类:@Null,@NotNull,@NotEmpty,@NotBlank等
范围校验类:@Min,@Size,@Digits,@Future,@Negative等
其它校验类:@Email,@URL,@AssertTrue,@Pattern等

二.初级约束注解:

1. @NotNull(message = “用户id不能为空”)

  • 没有设置值时会返回
  • 设置为userInfo.setUserId(“”);时不会返回
  • userInfo.setUserId(" ");时不会返回

2.@NotEmpty(message = “用户名不能为空”)

  • 不会自动去掉字符串前后的空格再判断是否为空
  • 没有设置值时会返回
  • userInfo.setUserName(“”);时返回
  • userInfo.setUserName(" ");时不返回

3.@NotBlank(message = “密码不能为空”)

  • 自动去掉字符串前后的空格再判断是否为空
  • 没有设置值时会返回
  • userInfo.setPassWord(“”);时返回
  • userInfo.setPassWord(" ");时返回

4.@Length(min = 6,max = 20,message = “密码不能少于6位,也不能多于20位”)

  • 即数量必须在6到20之间(包含6和20)

5.@Email(message = “邮箱不正确”)

  • 可以直接不设置值
  • 必须是正确的邮箱格式

6. @Min(value = 18, message = “年龄不能小于18岁”)

  • 可以直接不设置值
  • 即年龄必须大于或者等于18岁

7. @Max(value = 60, message = “年龄不能大于60岁”)

  • 可以直接不设置值
  • 即年龄必须等于小于60岁

8.@Past(message = “生日只能是过去的时间或者现在的时间”)

  • 可以直接不设置值
  • 传来的时间只能是过去的时间或者现在的时间,不能是未来时间

9.@Size(min = 1,message = “不能少于一个好友”)

  • 可以直接不设置值
  • 集合里面的内容不能少于1

三.中级约束注解:

1.@Valid

  • private List<@Valid UserInfo> friends;表示对UserInfo类中里面的每个属性进行验证

2.@NotNull(message = “注册时邮箱不能为空”,groups = RegisterGroup.class)

  • //注册场景 public interface RegisterGroup{}
    //登录场景 public interface LoginGroup{}
  • 注册时邮箱不能为空,登录时可以为空
  • set = validator.validate(userInfo,UserInfo.RegisterGroup.class);

3.//组排序场景
@GroupSequence({
LoginGroup.class,
RegisterGroup.class,
Default.class
})
public interface Group{}

  • set = validator.validate(userInfo,UserInfo.Group.class);
  • 先验证 LoginGroup组的,都通过才验证下面的,不通过直接返回验证错误信息,验证顺序按照上面的顺序进行验证

四.高级约束注解:

1.public void setUserInfo(@Valid UserInfo userInfo){ }
set1 = executableValidator.validateParameters(service,method1,paramObject);

  • @Valid对方法输入参数进行约束注解校验

2.public @Valid UserInfo getUserInfo(){return new UserInfo();}
set1 = executableValidator.validateReturnValue(userInfoService,method,returnValue);

  • @Valid对方法返回值进行约束校验

3.public UserInfoService(@Valid UserInfo userInfo){}
set1 = executableValidator.validateConstructorParameters(constructor,paramObject);

  • @Valid对构造函数输入参数进行校验

五.上面初,中,高级注解示例:

pom.xml

<!-- Validation 相关依赖 -->
        <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>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
        </dependency>

待验证对象实体类UserInfo.java:

package com.mystudy.elastic.job.springboot.validation;

import org.hibernate.validator.constraints.Length;

import javax.validation.GroupSequence;
import javax.validation.Valid;
import javax.validation.constraints.*;
import javax.validation.groups.Default;
import java.util.Date;
import java.util.List;

/**
 * 待验证对象实体类
 * 用户信息类
 */
public class UserInfo {

    //登录场景
    public interface LoginGroup{}

    //注册场景
    public interface RegisterGroup{}

    //组排序场景
    @GroupSequence({
            LoginGroup.class,
            RegisterGroup.class,
            Default.class
    })
    public interface Group{}

    /**
     * 用户id
     */
    @NotNull(message = "用户id不能为空")
    private String userId;

    /**
     * 用户名
     */
    @NotEmpty(message = "用户名不能为空")
    private String userName;

    /**
     * 密码
     */
    @NotBlank(message = "密码不能为空")
    @Length(min = 6, max = 20, message = "密码不能少于6位,也不能多于20位")
    private String passWord;

    /**
     * 邮箱
     */
//    @NotNull(message = "注册时邮箱不能为空",groups = RegisterGroup.class)
    @Email(message = "邮箱不正确")
    private String email;

    /**
     * 年龄
     */
    @Min(value = 18, message = "年龄不能小于18岁")
    @Max(value = 60, message = "年龄不能大于60岁")
    private Integer age;

    /**
     * 手机号
     */
    @Phone(message = "手机号不是158后面随便的手机号")
    private String phone;

    /**
     * 生日
     */
    @Past(message = "生日只能是过去的时间或者现在的时间")
    private Date birthday;

    /**
     * 好友列表
     */
    @Size(min = 1,message = "不能少于一个好友")
    private List<@Valid UserInfo> friends;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public List<UserInfo> getFriends() {
        return friends;
    }

    public void setFriends(List<UserInfo> friends) {
        this.friends = friends;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

用户信息服务类UserInfoService.java:

package com.mystudy.elastic.job.springboot.validation;

import javax.validation.Valid;

/**
 * 用户信息服务类
 */
public class UserInfoService {
    /**
     *  userInfo作为输入参数
     * @param userInfo
     */
    public void setUserInfo(@Valid UserInfo userInfo){

    }

    /**
     * userInfo作为输出参数
     * @return
     */
    public @Valid UserInfo getUserInfo(){
        return new UserInfo();
    }

    /**
     * 默认构造函数
     */
    public UserInfoService(){

    }

    /**
     * 接收userInfo作为参数的构造函数
     * @param userInfo
     */
    public UserInfoService(@Valid UserInfo userInfo){

    }
}

验证测试类ValidationTest.java:

package com.mystudy.elastic.job.springboot.validation;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;

/**
 * 验证测试类
 */
public class ValidationTest {

    //验证器对象
    private Validator validator;

    //待验证对象
    private UserInfo userInfo;

    //验证结果集合
    private Set<ConstraintViolation<UserInfo>> set;

    //验证结果集合
    private Set<ConstraintViolation<UserInfoService>> set1;

    /**
     * 初始化操作
     */
    @Before
    public void init() {
        //初始化验证器
        validator = Validation.buildDefaultValidatorFactory().getValidator();
        //初始化待验证对象 用户信息
        userInfo = new UserInfo();
        userInfo.setUserId(" ");
        userInfo.setUserName("  ");
        userInfo.setPassWord("  ");
        userInfo.setPassWord("333333");
        userInfo.setAge(18);
        userInfo.setBirthday(new Date());
        userInfo.setPhone("15987377373");

        UserInfo friend = new UserInfo();
        friend.setUserId("wangxiaoxi");
        friend.setUserName("王小喜");
        friend.setPassWord("wangxiaoxi");
        userInfo.setFriends(new ArrayList() {{
            add(friend);
        }});

    }

    /**
     * 结果打印
     */
    @After
    public void print() {
        set.forEach(item -> {
            //输出验证错误信息
            System.out.println(item.getMessage());
        });
//        set1.forEach(item -> {
//            //输出验证错误信息
//            System.out.println(item.getMessage());
//        });
    }

    @Test
    public void nullValidation() {
        //使用验证器对对象进行验证
        set = validator.validate(userInfo);
    }

    /**
     * 级联验证测试方法
     */
    @Test
    public void graphValidation() {
        set = validator.validate(userInfo);
    }

    /**
     * 验证注册时,邮箱是否为空
     */
    @Test
    public void groupValidation() {
        set = validator.validate(userInfo, UserInfo.RegisterGroup.class);
    }

    /**
     * 组排序
     */
    @Test
    public void groupSequenceValidate() {
        set = validator.validate(userInfo, UserInfo.Group.class);
    }

    /**
     * 对方法输入参数进行约束注解校验
     */
    @Test
    public void paramValidation() throws NoSuchMethodException {
        //获取校验执行器
        ExecutableValidator executableValidator = validator.forExecutables();

        //待验证对象
        UserInfoService service = new UserInfoService();
        //待验证方法
        Method method1 = service.getClass().getMethod("setUserInfo", UserInfo.class);
        //方法的输入参数
        Object[] paramObject = new Object[]{new UserInfo()};

        //对方法的输入参数进行校验
        set1 = executableValidator.validateParameters(service, method1, paramObject);

    }

    /**
     * 对方法返回值进行约束校验
     */
    @Test
    public void returnValueValidation() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //获取校验执行器
        ExecutableValidator executableValidator = validator.forExecutables();

        //构造要验证的方法对象
        UserInfoService userInfoService = new UserInfoService();
        Method method = userInfoService.getClass().getMethod("getUserInfo");

        //调用方法得到返回值
        Object returnValue = method.invoke(userInfoService);

        //校验方法返回值是否符合约束
        set1 = executableValidator.validateReturnValue(userInfoService, method, returnValue);
    }

    /**
     * 对构造函数输入参数进行校验
     */
    @Test
    public void constructorValidation() throws NoSuchMethodException {

        //获取验证执行器
        ExecutableValidator executableValidator = validator.forExecutables();

        //获取构造函数
        Constructor<UserInfoService> constructor = UserInfoService.class.getConstructor(UserInfo.class);
        Object[] paramObject = new Object[]{new UserInfo()};

        //校验构造函数
        set1 = executableValidator.validateConstructorParameters(constructor, paramObject);

    }
}

六.自定义注解:

自定义手机号注解@interface Phone:

package com.mystudy.elastic.job.springboot.validation;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 自定义手机号注解
 */
@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 {};
}

自定义手机号注解关联的验证器class PhoneValidator implements ConstraintValidator<Phone, String>:

package com.mystudy.elastic.job.springboot.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义手机号注解关联的验证器
 */
public class PhoneValidator implements ConstraintValidator<Phone, String> {

    /**
     * 自定义校验逻辑方法
     *
     * @param s
     * @param constraintValidatorContext
     * @return
     */
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {

        //手机号验证规则:158后面随便
        String check = "158\\d{8}";
        Pattern regex = Pattern.compile(check);

        String phone = Optional.ofNullable(s).orElse("");
        Matcher matcher = regex.matcher(phone);

        //返回是否匹配
        return matcher.matches();
    }
}

待验证对象实体类UserInfo:

package com.mystudy.elastic.job.springboot.validation;

/**
 * 待验证对象实体类
 * 用户信息类
 */
public class UserInfo {

    /**
     * 手机号
     */
    @Phone(message = "手机号不是158后面随便的手机号")
    private String phone;

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

}

验证测试类ValidationTest

package com.mystudy.elastic.job.springboot.validation;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

/**
 * 验证测试类
 */
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();
        userInfo.setPhone("15987377373");
    }

    /**
     * 结果打印
     */
    @After
    public void print() {
        set.forEach(item -> {
            //输出验证错误信息
            System.out.println(item.getMessage());
        });
    }

    @Test
    public void nullValidation() {
        //使用验证器对对象进行验证
        set = validator.validate(userInfo);
    }

}

结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/442483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Web Components 技术分析

简括&#xff1a; Web Components 基于四个主要的规范&#xff1a; Custom Elements&#xff0c;Shadow DOM&#xff0c;HTML Templates 和 HTML Imports。 Custom Elements 可以让开发人员创建自定义的 HTML 标签。 Shadow DOM 可以让开发人员将样式和行为封装到自定义元素内…

ASM字节码处理工具原理及实践(二)

0. 相关分享 ASM字节码处理工具原理及实践&#xff08;一&#xff09; 上一篇讲了ASM的简介、导入&#xff0c;以及字节码文件结构&#xff0c;并给出了ASM通过ClassVisitor对class进行访问的基础实战。本篇将进入MethodVisitor&#xff0c;尝试对方法进行访问、生成、转换。…

29.Linux网络编程

把昨天的 第二天的内容说一下&#xff0c;复习一下&#xff0c;第二天 讲的东西不算多&#xff0c;但是有两个作业题来写一写&#xff0c; 大致浏览一下&#xff0c;三次握手 四次挥手的过程&#xff0c;大家有没有画一下&#xff1f; 能画出来吗&#xff1f;同学们&#xff0…

前后端分离开发、Yapi、Swagger、项目部署

一、前后端分离开发 1.1、介绍 前后端分离开发&#xff0c;就是在项目开发过程中&#xff0c;对于前端代码的开发由专门的前端开发人员负责&#xff0c;后端代码则由后端开发人员负责&#xff0c;这样可以做到分工明确、各司其职&#xff0c;提高开发效率&#xff0c;前后端代…

RocketMQ单机环境搭建测试+springboot整合

1.资源下载 官网&#xff1a;下载 | RocketMQ 这里选择使用编译后可以直接用的 下载后解压&#xff1a;略 2.更改配置 主要是更改 conf/broker.conf 的配置&#xff0c;记得添加上下面这几行&#xff0c;否则消息发送失败 autoCreateTopicEnabletrue # 支持自动创建topic…

浅谈日出日落的计算方法以及替代工具 - 日出日落 API

引言 如果你想知道精确的日落日出时间&#xff0c;又或者你想设计一个日出日落时间查询的应用&#xff0c;又或者你只是好奇点进来了&#xff0c;还是可以过来围观一下涨涨知识&#xff0c;今天想跟大家聊一聊的是日出日落的计算方法以及替代工具 - 日出日落 API 。 日出日落…

大数据=SQL Boy,SQL Debug打破SQL Boy 的僵局

网上经常盛传 大数据sql boy&#xff0c;后端开发crud boy&#xff0c;算法工程师调参boy 在大数据领域也工作了好几年了&#xff0c;确实大数据开发&#xff0c;很多工作就是写sql&#xff0c;hive sql、spark sql、flink sql等等sql 一、背景&#xff1a; 但是经常有这样一…

NODEJS安装和vue安装及运行方法以及出现Cannot find module ‘node-sass‘ Require stack问题解决方法

安装nodejs 官网下载&#xff1a; https://registry.npmmirror.com/binary.html?pathnode/选择要下载的版本 一般建议下载msi 选择自己的安装位置一直下一步即可完成 检查一下是否安装成功 打开cmd&#xff0c;输入如下指令 node -vnpm -v输出了版本号就说明安装成功了 …

GCM与CCM的动作过程

CCM CCM&#xff08;Counter with CBC-MAC&#xff09;是一种基于对称加密算法的认证加密&#xff08;Authenticated Encryption&#xff09;模式&#xff0c;结合了CBC-MAC&#xff08;Cipher Block Chaining Message Authentication Code&#xff09;用于消息认证和CTR&…

[java聊天室]服务器发送消息给客户端守护线程同步锁(三)

守护线程 守护线程也称为:后台线程 守护线程是通过普通线程调用setDaemon(boolean on)方法设置而来的,因此创建上与普通线程无异.守护线程的结束时机上有一点与普通线程不同,即:进程的结束.进程结束:当一个进程中的所有普通线程都结束时,进程就会结束,此时会杀掉所有正在运行…

嵌入式Linux(2):将Helloworld驱动编译到内核

文章目录 分析一个例子仿写一个例子&#xff08;需要编译成.ko的&#xff09;写三个文件编辑上一级目录的Makefile文件编辑上一级目录的Kconfig文件make menuconfig进行配置 烧录到开发板上 分析一个例子 例子&#xff1a; source "drivers/redled/Kconfig" config…

简单分享微信怎么添加报名链接的步骤

最近看到很多小伙伴都在问有没有简单的报名链接制作办法&#xff0c;因为最近是暑期活动开展的前期&#xff0c;需要用到很多报名链接&#xff0c;希望可以直接通过微信小程序进行报名&#xff0c;扫一扫微信小程序的二维码就可以进入报名页面&#xff0c;然后制作步骤也是简单…

残差 Gabor 卷积网络和 FV-Mix 指数级数据增强策略用于手指静脉识别

论文背景 手指静脉识别系统的性能受到手指静脉训练样本不足的限制&#xff0c;导致特征学习不足和模型泛化能力弱&#xff1a;DCNN 需要大量的数据来学习更抽象的语义信息进行分类。对于指静脉识别&#xff0c;由于每个类别只包含少量样本&#xff0c;极易出现过拟合。原因之一…

MinIO快速入门

一、MinIO概述 官网地址&#xff1a;http://www.minio.org.cn/ 文档地址&#xff1a;http://docs.minio.org.cn/docs/ MinIO是一款基于Apache License v2.0开源协议的分布式文件系统&#xff08;或者叫对象存储服务&#xff09;&#xff0c;可以做为云存储的解决方案用来保存海…

如何借助测控终端实现设备远程运维?

随着物联网技术的发展&#xff0c;数字化越来越重要。数据是新的生产要素&#xff0c;是基础性资源和战略性资源&#xff0c;也是重要生产力。因此许多企业纷纷转型智慧工厂&#xff0c;但老旧的设备无法获取相应的数据&#xff0c;更换老旧设备的成本又太高&#xff0c;就无法…

【计算机架构】如何计算 CPU 时间

目录 0x00 响应时间和吞吐量&#xff08;Response Time and Throughput&#xff09; 0x01 相对性能&#xff08;Relative Performance&#xff09; 0x02 执行时间测量&#xff08;Measuring Execution Time&#xff09; 0x03 CPU 时钟&#xff08;Clocking&#xff09; 0x…

用docker承载mysql

这两天部署系统到生产服务器&#xff0c;前端后端部署docker是毫无疑义的&#xff0c;但mysql呢&#xff1f; 答案是mysql可以部署到docker。 1、数据文件挂载到宿主机 将mysql部署于docker&#xff0c;会有一个担心&#xff0c;就是docker容器的删除非常的容易&#xff0c;…

修改树莓派系统的更新源,软件安装源和pip安装源

本文目录 1、更换系统更新源2、更改软件源3、更换 pip 源4、更新系统与软件5、附加知识 Linux系统常用的安装源主要有系统更新源和软件安装源二大类&#xff0c;系统更新源是用于对Linux系统本身进行升级更新的&#xff0c;软件安装源是用于通过apt命令安装软件的。随着python的…

【Zigbee】解密Zigbee地址分配——你需要知道的一切

&#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;全栈领域优质创作者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 我的博客&#xff1a;Zeeland&#x1f4da; Github主页: Undertone0809 (Zeeland) (github.com)&…

URL 转为QR code(二维码)

推荐一个良心的网站&#xff0c;能够免费地将url、text编码为二维码&#xff0c;而且还能设计logo、颜色等。 https://www.the-qrcode-generator.com/ 如下图&#xff1a; 可以自己定义logo、颜色&#xff1a; 还能查看扫描历史等统计信息&#xff1a; 上述所有功能都是免…