当前位置: 代码网 > it编程>编程语言>Java > Java参数校验@Validated、@Valid介绍及使用详解

Java参数校验@Validated、@Valid介绍及使用详解

2024年08月19日 Java 我要评论
概述介绍及使用描述:javax.validation是 spring 集成自带的一个参数校验接口。可通过添加注解来设置校验条件。springboot框架创建web项目后,不需要再添加其他的依赖。使用:

概述

介绍及使用

描述:javax.validation是 spring 集成自带的一个参数校验接口。可通过添加注解来设置校验条件。springboot框架创建web项目后,不需要再添加其他的依赖。

使用:在controller上使用 @valid 或 @validated 注解 开启校验

public string test(@requestbody @valid myrequest req){};

@validated 和 @valid 的异同

相同点:

  • 在检验参数符合规范的功能上基本一致;

不同点:

  • 提供者不同:
    • validated 是spring validation验证框架对参数的验证机制;
    • valid是 javax 提供的参数验证机制
  • 作用域不同:
    • validated :类,方法,参数
    • valid:方法,字段,构造方法,参数,type_us

注:type_use:在 java 8 之前的版本中,只能允许在声明式前使用 annotation。而在 java 8 版本中,annotation 可以被用在任何使用 type 的地方,例如:初始化对象时 (new),对象类型转化时,使用 implements 表达式时,或者使用 throws 表达式时。

//初始化对象时
string mystring = new @valid string();
//对象类型转化时
mystring = (@valid string) str;
//使用 implements 表达式时
class mylist<t> implements list<@valid t> {...}
//使用 throws 表达式时
public void validatevalues() throws @valid validationfailedexception{...}

参数校验常用注解

除了前四个 @null,@ notnull,@ notblank,@notempty外,其他所有的注解,传 null 时都会被当作有效处理

注解常用参数值:message(校验不通过反馈信息)

jsr303定义的基础校验类型:

注解验证的数据类型备注
null任意类型参数值必须是 null
notnull任意类型参数值必须不是 null
notblank只能作用于字符串字符串不能为 null,而且字符串长度必须大于0,至少包含一个非空字符串
notemptycharsequence
collection
map
array
参数值不能为null,且不能为空
(字符串长度必须大于0,空字符串(“ ”)可以通过校验)
size(min,max )charsequence
collection
map
array
字符串:字符串长度必须在指定的范围内
collection:集合大小必须在指定的范围内
map:map的大小必须在指定的范围内
array:数组长度必须在指定的范围内
pattern(regexp)字符串类型验证字符串是否符合正则表达式
min(value)整型类型参数值必须大于等于 最小值
max(value)整型类型参数值必须小于等于 最大值
decimalmin(value)整型类型参数值必须大于等于 最小值
decimalmax(value)整型类型参数值必须小于等于 最大值
positive数字类型参数值为正数
positiveorzero数字类型参数值为正数或0
negative数字类型参数值为负数
negativeorzero数字类型参数值为负数或0
digits(integer,fraction)数字类型参数值为数字,且最大长度不超过integer位,整数部分最高位不超过fraction位
asserttrue布尔类型参数值必须为 true
assertfalse布尔类型参数值必须为 false
past时间类型(date)参数值为时间,且必须小于 当前时间
pastorpresent时间类型(date)参数值为时间,且必须小于或等于 当前时间
future时间类型(date)参数值为时间,且必须大于 当前时间
futureorpresent时间类型(date)参数值为时间,且必须大于或等于 当前日期
email字符串类型被注释的元素必须是电子邮箱地址

hibernate validator 中附加的 constraint :

注解验证的数据类型备注
length字符串类型字符串的长度在min 和 max 之间
range数字类型
字符串类型
数值或者字符串的值必须在 min 和 max 指定的范围内

pattern注解校验 常用正则表达式

@pattern(regexp = "^[1-9]]\\d*$", message = "xx参数值必须是正整数")

高阶使用

自定义分组校验

有时多个场景接口公用一个请求对象,不同业务场景对请求对象的参数校验需求不同,可以使用分组校验来解决

注意:

  • 没有指定显示分组的被校验字段和校验注解,默认都是 default 组(即 default.class)
  • 若自定义的分组接口未继承 default 分组,且 @validated(或 @valid)注解未传参 default.class,则只会校验请求对象中进行了显示分组的字段,不会校验默认分组(没有进行显示分组)的字段
  • 自定义的分组接口不继承 default 分组 + @validated(或 @valid)注解传参 {自定义分组接口.class, default.class}
  • = 自定义的分组接口继承 default 分组 + @validated(或 @valid)注解只传参自定义分组接口

示例:

新建自定义分组校验接口

public interface student {
}
import javax.validation.groups.default;
public interface teacher extends default {
}

新建请求对象

@data
public class userdto {
    @notblank(message = "不能没有名称")
    private string name;
    @notblank(message = "老师不能没有手机号", groups = teacher.class)
    private string phone;
    @notempty(message = "学生不能没有书", groups = student.clas)
    @size(min = 2, message = "学生必须有两本书", groups = student.class)
    private list<string> booknames;
}

controller

@restcontroller
public class validatedcontroller {
    /**
     * 测试 校验student分组+默认分组
     */
    @postmapping("student")
    public userdto validatedstudent(@validated(value = {student.class, default.class}) @requestbody userdto userdto) {
        return userdto;
    }
    /**
     * 测试 校验student分组+默认分组
     */
    @postmapping("teacher")
    public userdto validatedteacher(@validated(value = {teacher.class}) @requestbody userdto userdto) {
        return userdto;
    }
    /**
     * 测试 分组校验  default
     */
    @postmapping("default")
    public userdto validateddefault(@validated(value = {default.class}) @requestbody userdto userdto) {
        return userdto;
    }
    /**
     * 测试 分组校验 onlystudent
     */
    @postmapping("onlystudent")
    public userdto validatedonlystudent(@validated(value = {student.class}) @requestbody userdto userdto) {
        return userdto;
}

自定义校验注解

定义注解

@documented
//指定注解的处理类
@constraint(validatedby = {versionvalidatorhandler.class })
@target({ method, field, annotation_type, constructor, parameter })
@retention(runtime)
public @interface constantversion {
   string message() default "{constraint.default.const.message}";
   class<?>[] groups() default {};
   class<? extends payload>[] payload() default {};
   string value();
}

注解处理类

public class versionvalidatorhandler implements constraintvalidator<constant, string> {
    private string constant;
    @override
    public void initialize(constant constraintannotation) {
        //获取设置的字段值
        this.constant = constraintannotation.value();
    }
    @override
    public boolean isvalid(string value, constraintvalidatorcontext context) {
        //判断参数是否等于设置的字段值,返回结果
        return constant.equals(value);
    }
}

自定义注解使用

@constantversion (message = "verson只能为1.0.0",value="1.0.0")
string version;

controller

@restcontroller
public class testcontroller {
    @requestmapping("/test")
    public string createuser(@valid user user, bindingresult bindingresult){
        if (bindingresult.haserrors()){
            return bindingresult.getfielderror().getdefaultmessage();
        }
        return  "success";
    }
}

嵌套检验

描述:当对象 man 的字段 houses 包含 house 对象类型时,在检验 houses 字段时可以检验 house 对象的属性字段时,就称为嵌套检验

方案:在被检验的字段上添加 @valid 注解就可以实现嵌套检验

示例如下:

  • 在检验 man 对象的 houses 字段时,在houses 字段上添加 @valid 注解后,就可以检验 list 中的 house 的属性是否符合要求;
  • 否则只会检验 houses 的集合大小是否大于1,不会校验集合中的 house 对象,比如 house 对象的 name 长度是否符合要求。
class man{
    @valid
    @size(min = 1)
    private list<house> houses;
}
class house{
    @length(min = 1,max = 10)
    private string name;
}

拓展

异常处理

参数校验异常:methodargumentnotvalidexception

方式一:基于异常监听@controlleradvice(参考:https://www.cnblogs.com/gezi0815/p/13815397.html)

/**
* 全局异常处理器
*/
@slf4j
@controlleradvice
public class globalexceptionhandler {
    /**
     * 异常处理
     */
    @responsebody
    @exceptionhandler(value = exception.class)
    public dataresult exceptionhandler(exception e) {
        log.error("globalexceptionhandler.exceptionhandler , 异常信息",e);
        return dataresult.fail(e.getmessage());
    }
    /**
     * 业务异常
     */
    @responsebody
    @exceptionhandler(value = bplcommonexception.class)
    public dataresult bplcommonexceptionhandler(bplcommonexception e) {
        log.warn("",e);
        return dataresult.fail(e.getmessage());
    }
    /**
     * 处理所有requestbody注解参数验证异常
     */
    @exceptionhandler(methodargumentnotvalidexception.class)
    @responsebody
    public dataresult handlemethodargumentnotvalidexception(methodargumentnotvalidexception e){
        log.warn(e.getmessage());
        return dataresult.fail(e.getbindingresult().getallerrors().get(0).getdefaultmessage());
    }
    /**
     * 处理所有requestparam注解数据验证异常
     */
    @exceptionhandler(bindexception.class)
    public dataresult handlebindexception(bindexception ex) {
        fielderror fielderror = ex.getbindingresult().getfielderror();
        log.warn("必填校验异常:{}({})", fielderror.getdefaultmessage(),fielderror.getfield());
        return dataresult.fail(ex.getbindingresult().getallerrors().get(0).getdefaultmessage());
    }
}

方式二:基于handle或filter(参考:https://blog.51cto.com/u_12012821/2511625)

if (e instanceof methodargumentnotvalidexception) {
	string errormsg = ((methodargumentnotvalidexception) e)
		.getbindingresult()
		.getallerrors()
        .stream()
		.map(defaultmessagesourceresolvable::getdefaultmessage)
		.collect(collectors.joining(","));
	resp = r.builder()
		.code(resultcodeenum.business_error.getcode())
		.message(errormsg).success(false)
		.build();
} 

到此这篇关于java参数校验@validated、@valid使用详解的文章就介绍到这了,更多相关java参数校验内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com