栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot--参数校验--@Valid/@Validated--使用/实例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot--参数校验--@Valid/@Validated--使用/实例

原文网址:SpringBoot--参数校验--@Valid/@Validated--使用/实例_IT利刃出鞘的博客-CSDN博客

简介

说明

        本文介绍SpringBoot中的参数验证的用法。

JSR-349,hibernate validator,Spring validation之间的关系

        JSR-349是一项标准,是JSR303的升级版。JSR-349添加了一些新特性,包括一些校验规范(校验注解),如@Null,@NotNull,@Pattern,它们位于javax.validation.constraints包下,只提供接口不提供实现。

        hibernate validator对这个规范的实现(不要将hibernate和数据库orm框架联系在一起),它们位于org.hibernate.validator.constraints包下。

        Spring为了给开发者提供便捷,对hibernate validator进行了二次封装。

@Valid与@Validated

不同点

@Valid

@Validated

来源

javax.validation的校验注解

Spring validation 的校验注解。

注解位置

方法参数、字段、构造方法、方法。

类、方法参数、方法。

分组

无分组功能。

有分组功能。

可在验证时根据不同的分组采用不同的验证机制。

嵌套

支持。

放在字段上面。

不支持

字段注解大全

字段注解(所属包:javax.validation.constraints.*)。

字段注解

说明

@AssertFalse

限制必须为false

@AssertTrue

限制必须为true

@DecimalMax(value)

限制必须为一个不大于指定值的数字

@DecimalMin(value)

限制必须为一个不小于指定值的数字

@Digits(integer,fraction)

限制必须为一个小数,且整数部分的位数不能超过integer,

小数部分的位数不能超过fraction

@Email

验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

@Future

限制必须是一个将来的日期

@Max(value)

限制必须为一个不大于指定值的数字

@Min(value)

限制必须为一个不小于指定值的数字

@Past

限制必须是一个过去的日期

@Pattern(value)

限制必须符合指定的正则表达式

@NotEmpty

验证注解的元素值不为null或者空(isEmpty()方法)。

可用于字符串, Collection, Map, 数组。

@NotBlank

验证注解的元素值不为null且包含除了空格之外至少一个字符。

只用于字符串。

@Null

限制只能为null

@NotNull

限制必须不为null

@Past

验证注解的元素值(日期类型)比当前时间早

@Size(max,min)

限制字符长度必须在min到max之间

依赖

只需引入Spring的Validation即可。


	org.springframework.boot
	spring-boot-starter-validation

它里边依赖了hibernate validator,就是下边这个


	org.hibernate.validator
	hibernate-validator

pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.1.RELEASE
         
    
    com.example
    demo
    0.0.1-SNAPSHOT
    demo_SpringBoot_MVC_validation
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-validation
        

        
        
            org.projectlombok
            lombok
            1.18.22
            provided
        

        
            com.github.xiaoymin
            knife4j-spring-boot-starter
            3.0.3
        

    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


@Valid实例 代码

Controller

package com.example.demo.simple.controller;

import com.example.demo.simple.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;

@Api(tags = "不分组")
@RestController
@RequestMapping("valid")
public class ValidController {

    @ApiOperation("正常用法")
    @GetMapping("normal")
    public User normal(@Valid User user) {
        return user;
    }

    @ApiOperation("获得BindingResult")
    @GetMapping("bindingResult")
    public User bindingResult(@Valid User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()){
            List list = bindingResult.getAllErrors();
            for (ObjectError objectError : list) {
                System.out.println(objectError.getDefaultMessage());
            }
            //System.out.println(bindingResult.getFieldError().getDefaultMessage());
        }

        return user;
    }

}

Entity

User类

package com.example.demo.simple.entity;

import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class User {
    @NotBlank(message = "名字不能为空")
    private String name;

    private Integer age;
 
    @NotBlank(message = "密码不能为空")
    private String password;
 
    @NotEmpty(message = "分数不能为空")
    private List scoreArray;
 
    @Valid
    @NotNull(message = "账户不能为null")
    private Account account;
}

 Account类

package com.example.demo.simple.entity;
 
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;

@Data
public class Account {
    @NotBlank(message = "电话号码不能为空")
    private String phoneNumber;
 
    private String[] emails;
}
测试

        本文为了展示后端错误,直接用postman来进行请求。

        实际上,如果用了knife4j这个接口工具,它能自动识别是否为空的注解,并在前端进行控制。如果不能为空,则前端直接显示为红色的框。

测试1:缺少字段

postman访问:http://localhost:8080/valid/normal

postman访问结果:

后端结果:

2021-12-22 15:32:20.032  WARN 94176 --- [nio-8080-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'user' on field 'account': rejected value [null]; codes [NotNull.user.account,NotNull.account,NotNull.com.example.demo.simple.entity.Account,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.account,account]; arguments []; default message [account]]; default message [账户不能为null]
Field error in object 'user' on field 'password': rejected value [null]; codes [NotBlank.user.password,NotBlank.password,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.password,password]; arguments []; default message [password]]; default message [密码不能为空]
Field error in object 'user' on field 'scoreArray': rejected value [null]; codes [NotEmpty.user.scoreArray,NotEmpty.scoreArray,NotEmpty.java.util.List,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.scoreArray,scoreArray]; arguments []; default message [scoreArray]]; default message [分数不能为空]]

测试2:不缺少字段

postman访问:http://localhost:8080/valid/normal

postman结果:

测试3:缺少字段,后端获取BindResult 

postman访问:http://localhost:8080/valid/bindingResult

postman结果:

后端结果

账户不能为null
密码不能为空
分数不能为空

可以看到,没有报错。 

@Validated实例 不分组

跟上边“@Valid实例”的结果是一样的,只是把入参处的@Valid改为@Validated。

代码

Controller

package com.example.demo.validated.without_group.controller;

import com.example.demo.validated.without_group.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;

@Api(tags = "不分组")
@RestController
@RequestMapping("validatedWithoutGroup")
public class ValidatedWithoutGroupController {

    @ApiOperation("正常用法")
    @GetMapping("normal")
    public User normal(@Validated User user) {
        return user;
    }

    @ApiOperation("获得BindingResult")
    @GetMapping("bindingResult")
    public User bindingResult(@Validated User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()){
            List list = bindingResult.getAllErrors();
            for (ObjectError objectError : list) {
                System.out.println(objectError.getDefaultMessage());
            }
            //System.out.println(bindingResult.getFieldError().getDefaultMessage());
        }

        return user;
    }

}

Entity

User类

package com.example.demo.validated.without_group.entity;

import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class User {
    @NotBlank(message = "名字不能为空")
    private String name;

    private Integer age;
 
    @NotBlank(message = "密码不能为空")
    private String password;
 
    @NotEmpty(message = "分数不能为空")
    private List scoreArray;
 
    @Valid
    @NotNull(message = "账户不能为null")
    private Account account;
}

Account类

package com.example.demo.validated.without_group.entity;
 
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data
public class Account {
    @NotBlank(message = "电话号码不能为空")
    private String phoneNumber;
 
    private String[] emails;
}
测试

测试1:缺少字段

postman访问:http://localhost:8080/validatedWithoutGroup/normal

postman结果:

后端结果:

2021-12-22 16:12:26.549  WARN 79176 --- [nio-8080-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'user' on field 'scoreArray': rejected value [null]; codes [NotEmpty.user.scoreArray,NotEmpty.scoreArray,NotEmpty.java.util.List,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.scoreArray,scoreArray]; arguments []; default message [scoreArray]]; default message [分数不能为空]
Field error in object 'user' on field 'password': rejected value [null]; codes [NotBlank.user.password,NotBlank.password,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.password,password]; arguments []; default message [password]]; default message [密码不能为空]
Field error in object 'user' on field 'account': rejected value [null]; codes [NotNull.user.account,NotNull.account,NotNull.com.example.demo.validated.without_group.entity.Account,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.account,account]; arguments []; default message [account]]; default message [账户不能为null]]

测试2:不缺少字段

postman访问:http://localhost:8080/validatedWithoutGroup/normal

postman结果:

测试3: 获得BindingResult

postman访问:http://localhost:8080/validatedWithoutGroup/bindingResult

postman结果:

后端结果:

分数不能为空
密码不能为空
账户不能为null
分组 代码

Controller

package com.example.demo.validated.with_group.controller;

import com.example.demo.validated.with_group.entity.User;
import com.example.demo.validated.with_group.validatation.IGroupA;
import com.example.demo.validated.with_group.validatation.IGroupAll;
import com.example.demo.validated.with_group.validatation.IGroupB;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Api(tags = "分组")
@RestController
@RequestMapping("validatedWithGroup")
public class ValidatedWithGroupController {
    @ApiOperation("使用组:GroupA")
    @GetMapping("groupA")
    public User groupA(@Validated({IGroupA.class}) User user) {
        return user;
    }

    @ApiOperation("使用组:GroupB")
    @GetMapping("groupB")
    public User groupB(@Validated({IGroupB.class}) User user) {
        return user;
    }

    @ApiOperation("使用组:GroupA和GroupB")
    @GetMapping("groupAAndGroupB")
    public User groupAAndGroupB(@Validated({IGroupA.class, IGroupB.class}) User user) {
        return user;
    }

    @ApiOperation("使用组:GroupAll")
    @GetMapping("groupAll")
    public User groupAll(@Validated({IGroupAll.class}) User user) {
        return user;
    }

}

Entity

User类

package com.example.demo.validated.with_group.entity;

import com.example.demo.validated.with_group.validatation.IGroupA;
import com.example.demo.validated.with_group.validatation.IGroupB;
import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class User {
    @NotBlank(message = "名字不能为空")
    private String name;

    @NotNull(message = "年龄不能为空", groups = {IGroupA.class})
    private Integer age;

    @NotEmpty(message = "密码不能为空", groups = {IGroupB.class})
    private String password;

    @NotEmpty(message = "分数不能为空", groups = {IGroupA.class, IGroupB.class})
    private List scoreArray;

    @Valid
    @NotNull(message = "账户不能为null")
    private Account account;
}

Account类

package com.example.demo.validated.with_group.entity;

import lombok.Data;

import javax.validation.constraints.NotEmpty;

@Data
public class Account {
    @NotEmpty(message = "电话号码不能为空")
    private String phoneNumber;

    private String[] emails;
}

Group

IGroupA接口

package com.example.demo.validated.with_group.validatation;

public interface IGroupA {
}

IGroupB接口 

package com.example.demo.validated.with_group.validatation;

public interface IGroupB {
}

 IGroupAll接口 

package com.example.demo.validated.with_group.validatation;

import javax.validation.GroupSequence;
import javax.validation.groups.Default;

@GroupSequence({Default.class, IGroupA.class, IGroupB.class})
public interface IGroupAll {
}
测试

测试1:无参数请求groupA

postman访问:http://localhost:8080/validatedWithGroup/groupA

postman结果:

后端结果:

2021-12-22 16:32:44.138  WARN 85532 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'user' on field 'scoreArray': rejected value [null]; codes [NotEmpty.user.scoreArray,NotEmpty.scoreArray,NotEmpty.java.util.List,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.scoreArray,scoreArray]; arguments []; default message [scoreArray]]; default message [分数不能为空]
Field error in object 'user' on field 'age': rejected value [null]; codes [NotNull.user.age,NotNull.age,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age]]; default message [年龄不能为空]]

测试2:无参数请求groupB

postman访问:http://localhost:8080/validatedWithGroup/groupB

postman结果:

后端结果:

2021-12-22 16:33:15.773  WARN 85532 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'user' on field 'scoreArray': rejected value [null]; codes [NotEmpty.user.scoreArray,NotEmpty.scoreArray,NotEmpty.java.util.List,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.scoreArray,scoreArray]; arguments []; default message [scoreArray]]; default message [分数不能为空]
Field error in object 'user' on field 'password': rejected value [null]; codes [NotEmpty.user.password,NotEmpty.password,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.password,password]; arguments []; default message [password]]; default message [密码不能为空]]

测试3:无参数请求groupA和groupB

postman访问:http://localhost:8080/validatedWithGroup/groupAAndGroupB

postman结果:

后端结果:

2021-12-22 16:34:27.652  WARN 85532 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 3 errors
Field error in object 'user' on field 'scoreArray': rejected value [null]; codes [NotEmpty.user.scoreArray,NotEmpty.scoreArray,NotEmpty.java.util.List,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.scoreArray,scoreArray]; arguments []; default message [scoreArray]]; default message [分数不能为空]
Field error in object 'user' on field 'age': rejected value [null]; codes [NotNull.user.age,NotNull.age,NotNull.java.lang.Integer,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age]]; default message [年龄不能为空]
Field error in object 'user' on field 'password': rejected value [null]; codes [NotEmpty.user.password,NotEmpty.password,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.password,password]; arguments []; default message [password]]; default message [密码不能为空]]

测试4:无参数请求groupAll

postman访问:http://localhost:8080/validatedWithGroup/groupAll

postman结果:

后端结果:

2021-12-22 16:36:54.095  WARN 91820 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'user' on field 'name': rejected value [null]; codes [NotBlank.user.name,NotBlank.name,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.name,name]; arguments []; default message [name]]; default message [名字不能为空]
Field error in object 'user' on field 'account': rejected value [null]; codes [NotNull.user.account,NotNull.account,NotNull.com.example.demo.validated.with_group.entity.Account,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.account,account]; arguments []; default message [account]]; default message [账户不能为null]]

可以看到:走的校验逻辑是没有除了IGroupA和IGroupB注解的字段的逻辑。

自定义校验注解

也可以自定义校验的注解,自己写校验逻辑。

后续有时间补充。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/677380.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号