当前位置: 代码网 > it编程>编程语言>Java > springboot Validated失效的问题及解决思路

springboot Validated失效的问题及解决思路

2026年01月05日 Java 我要评论
1、 pom 加入依赖 <dependency> <groupid>org.springframework.boot</groupid

1、 pom 加入依赖

        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-validation</artifactid>
        </dependency>

2、实体类加入注解

@data
@accessors(chain = true)
@tablename("user")
@validated
public class user {
    private integer id;
    @notblank(message = "姓名不能为空")
    private  string name;
    @min(message = "年龄不正确1-100之间",value = 1)
    @max(message = "年龄不正确1-100之间",value = 1)

    private  integer age ;
    private integer sex;

}

3、控制器加入@valid注解

4、测试效果

常见的注解

通常情况下,在javax.validation.constraints 包下,定义了一系列的约束(constraint)注解,一共 22 个注解,快速略过即可。如下:

空和非空检查

  • @notblank:只能用于字符串不为 null ,并且字符串 .trim() 以后 length 要大于 0 。
  • @notempty:集合对象的元素不为 0 ,即集合不为空 。
  • @notnull:不能为 null 。
  • @null`:必须为 null 。

数值检查

  • @decimalmax(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值。 
  • @decimalmin(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值。 
  • @digits(integer, fraction):被注释的元素必须是一个数字,其值必须在可接受的范围内。 
  • @positive:判断正数。 
  • @positiveorzero:判断正数或 0 。 
  • @max(value):该字段的值只能小于或等于该值。 
  • @min(value):该字段的值只能大于或等于该值。 
  • @negative:判断负数。 
  • @negativeorzero:判断负数或 0 。

boolean 值检查

  • @assertfalse:被注释的元素必须为 true 。@asserttrue:被注释的元素必须为 false 。

长度检查

  • @size(max, min):检查字段的 size 是否在 min 和 max 之间,可以是字符串、数组、集合、map 等。

日期检查

  • @future:被注释的元素必须是一个将来的日期。
  • @futureorpresent:判断日期是否是将来或现在日期。
  • @past:检查该字段的日期是在过去。
  • @pastorpresent:判断日期是否是过去或现在日期。

其它检查

  • @email:被注释的元素必须是电子邮箱地址。
  • @pattern(value):被注释的元素必须符合指定的正则表达式。

hibernate validator 附加的约束注解,在org.hibernate.validator.constraints 包下,定义了一系列的约束(constraint)注解。常见的如示。

  • @range(min=, max=):被注释的元素必须在合适的范围内。
  • @length(min=, max=):被注释的字符串的大小必须在指定的范围内。
  • @url(protocol=,host=,port=,regexp=,flags=):被注释的字符串必须是一个有效的 url 。
  • @safehtml:判断提交的 html 是否安全。例如说,不能包含 javascript 脚本等等。

其他的就不一一列举了,有感兴趣的小伙伴可以去源码包看看。

@valid 和 @validated

@valid 注解,是 bean validation 所定义,可以添加在普通方法、构造方法、方法参数、方法返回、成员变量上,表示它们需要进行约束校验。

@validated 注解,是 spring validation 锁定义,可以添加在类、方法参数、普通方法上,表示它们需要进行约束校验。同时,@validated 有 value 属性,支持分组校验。

对于初学者来说,很容易搞混 @valid 和 @validated 注解。

  • ① 声明式校验:spring validation 仅对 @validated 注解,实现声明式校验。
  • ② 分组校验:bean validation 提供的 @valid注解,因为没有分组校验的属性,所以无法提供分组校验。此时,我们只能使用 @validated 注解。
  • ③ 嵌套校验:相比来说,@valid注解的地方,多了【成员变量】。这就导致,如果有嵌套对象的时候,只能使用@valid注解。

自定义校验注解

虽然 jsr303 和 hibernate validtor 已经提供了很多校验注解,但是当面对复杂参数校验时,还是不能满足我们的要求,这时候我们就需要 自定义校验注解。

下面以“list数组中不能含有null元素”为实例自定义校验注解

1、注解定义如示。

@target({elementtype.annotation_type, elementtype.method, elementtype.field})
@retention(runtime)
@documented
@constraint(validatedby = listnothavenullvalidatorimpl.class)//此处指定了注解的实现类
public @interface listnothavenull {
    /**
     * 添加value属性,可以作为校验时的条件,若不需要,可去掉此处定义
     */
    int value() default 0;
    string message() default "list集合中不能含有null元素";
    class<?>[] groups() default {};
    class<? extends payload>[] payload() default {};
    /**
     * 定义list,为了让bean的一个属性上可以添加多套规则
     */
    @target({method, field, annotation_type, constructor, parameter})
    @retention(runtime)
    @documented
    @interface list {
        listnothavenull[] value();
    }
}

2、编写自定义校验实现类

@service
public class listnothavenullvalidatorimpl implements constraintvalidator<listnothavenull, list> {
    private int value;
    @override
    public void initialize(listnothavenull constraintannotation) {
        //传入value 值,可以在校验中使用
        this.value = constraintannotation.value();
    }
    public boolean isvalid(list list, constraintvalidatorcontext constraintvalidatorcontext) {
        for (object object : list) {
            if (object == null) {
                //如果list集合中含有null元素,校验失败
                return false;
            } else if (object instanceof string) {
                string value = object.tostring();
                if (value.trim().length() == 0){
                    return false;
                }
            }
        }
        return true;
    }
}

3、model中添加注解:

@data
public class sysrole {

    private long roleid;

    @notblank(message = "角色名不能为空")
    private string name;

    @notempty(message = "资源列表不能为空")
    @listnothavenull(message = "list 中不能含有null元素")
    @valid
    private list<string> paths;

}

4、编写前端控制器

    @postmapping("/addrole")
    public r addrole(@requestbody @valid sysrole sysrole) {
        system.out.println("走到这里说明校验成功");
        system.out.println(sysrole);
        return r.ok(r.success_msg);
    }

使用方法同 “简单校验”,在在需要校验的model上面加上@valid即可。

通用的validtor校验工具类

public class validatorutils {
    private validatorutils() { }

    private static validator validator;
    static {
        validator = validation.builddefaultvalidatorfactory().getvalidator();
    }

    /**
     * 校验对象
     *
     * @param object 待校验对象
     * @param groups 待校验的组
     * @throws rrexception 校验不通过,则报rrexception异常
     */
    public static void validateentity(object object, class<?>... groups) throws rrexception {
        set<constraintviolation<object>> constraintviolations = validator.validate(object, groups);

        if (!constraintviolations.isempty()) {
            iterator<constraintviolation<object>> iterator = constraintviolations.iterator();
            stringbuilder msg = new stringbuilder();
            while (iterator.hasnext()) {
                constraintviolation<object> constraint = iterator.next();
                msg.append(constraint.getmessage()).append(',');
            }
            throw new rrexception(msg.tostring().substring(0,msg.tostring().lastindexof(',')));
        }
    }
}

使用方式,在接收到前端传递的参数后,使用validatorutils.validateentity(【参数名】);即可校验,支持分组校验,分组需要定义分组接口。

springboot2 @requestbody @valid校验失效问题

这是因为 @requestbody @valid 抛出的异常没有被捕获,所以需要建立一个全局自定义异常处理类

@restcontrolleradvice
public class globalexceptionhandler {
    @exceptionhandler(value = methodargumentnotvalidexception.class)
    @responsebody
    public result methodargumentnotvalidexceptionhandler(methodargumentnotvalidexception e)
    {
        //获取实体类定义的校验注解字段上的message作为异常信息,@notblank(message = "用户密码不能为空!")异常信息即为"用户密码不能为空!"
        list<objecterror> allerrors = e.getbindingresult().getallerrors();
        string message = allerrors.stream().map(s -> s.getdefaultmessage()).collect(collectors.joining(";"));
        list<string> msglist = new arraylist<>();
        msglist = arrays.aslist(message.split(";"));
        return result.failed(msglist.get(0));
    }
}

测试

校验get请求

这种情况下,使用@valid和@validated都可以。

requestparam/pathvariable参数校验

get请求一般会使用requestparampathvariable传参。如果参数比较多(比如超过6个),还是推荐使用dto对象接收。否则,推荐将一个个参数平铺到方法入参中。在这种情况下,必须在controller类上标注@validated注解,并在入参上声明约束注解(如@min等)。如果校验失败,会抛出constraintviolationexception异常。代码示例如下:

校验get必要条件

1、controller类上标注@validated注解

2、全局捕获该异常

    @exceptionhandler({constraintviolationexception.class})
    @responsebody
    public result handleconstraintviolationexception(constraintviolationexception ex) {
        return result.failed(ex.getmessage());
    }

3、如何get请求requestparam 则@requestparam(value = “customerid”) 不能添加该注解

4、如何get请求pathvariable 则需加上@pathvariable()

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

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

发表评论

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