spring-boot-starter-validation参数校验


一、spring-boot-starter-validation简介

spring-boot-starter-validation是快速使用参数校验的starter,方便在Springboot开发过程中进行参数的合法性校验。

二、校验说明

参数校验主要使用@Validated 和 @Valid注解
@Validated由spring框架提供
@Valid由validation框架提供

@Validated可以用在类型、方法和方法参数上,不能用在成员属性上
@Valid可以用在方法、构造函数、方法参数和成员属性上

@Validated具有分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

javax.validation.constraints包下提供的注解如下:

注解 说明
AssertFalse 必须为false,The annotated element must be false.
AssertTrue 必须为true, The annotated element must be true
DecimalMax 数字,其值必须小于或等于指定的最大值
DecimalMin 数字,其值必须大于或等于指定的最大值
Digits number,整数位数不能超过integer位,以及小数位数不能超过fraction位
Email 参数必须为email格式,如果参数为空,也会通过校验。所以如果参数为非空且必须为email格式时,需要与@NotNull结合使用
Future 参数必须为将来的日期或时间,适用于日期,时间等参数类型
FutureOrPresent 参数必须为当前或将来的日期或时间,The annotated element must be an instant, date or time in the present or in the future.
Max 参数为数值,不能超过某一个最大值
Min 参数为数值,必须大于或等于某一个值
Negative 参数为数值,必须为负数
NegativeOrZero 参数为数值,必须为负数或者0
NotBlank 参数为字符串,且不能为空,至少包含一个非空白字符串
NotEmpty 参数为字符串,且不能为空,不能为空字符串,空白字符串可以通过校验。
NotNull 参数为任意类型,且不能为空。
Null 参数必须为Null,The annotated element must be null.
Past 需要一个过去的时间或日期,The annotated element must be an instant, date or time in the past.
PastOrPresent 需要一个过去或当前的时间或日期,而不是将来
Pattern 字符串参数校验,必须满足对应的正则表达式
Positive 数值校验,值必须为正数,不包括0
PositiveOrZero 数值校验,值必须为正数或0

org.hibernate.validator.constraints包中注解只挑几个说明,其他的可以详细看org.hibernate.validator.constraints包里面的类

注解 说明
Length 校验字符串长度是否在最小与最大之间,Validate that the string is between min and max included.
Range 范围校验,数值型适用,Apply on numeric values or string representation of the numeric value.

三、pom.xml依赖引入

一般采用如下方式引入即可

		<!-- spring-boot-starter-validation start -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<!-- spring-boot-starter-validation end -->

如果不希望使用log4j(比如log4j漏洞原因),就将log4j相关依赖先排除

		<!-- spring-boot-starter-validation start -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
			<!-- 排除掉log4j -->
			<exclusions>
				<exclusion>
					<groupId>org.apache.logging.log4j</groupId>
					<artifactId>log4j-api</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.apache.logging.log4j</groupId>
					<artifactId>log4j-to-slf4j</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- spring-boot-starter-validation end -->

四、校验示例测试

1.get请求

get请求参数的校验,是直接在controller方法参数上加校验注解即可,Validated注解可以直接放在类名上面(springboot2.6.2测试只有放在类名上有效)

@RestController
@RequestMapping("/")
@Validated
public class TestController {
    
    
    @GetMapping("/gettest")
    public Object gettest(@NotBlank(message = "工单号不能为空") String orderId,
    		@NotBlank(message = "UserId不能为空") String userId) {
    
    
    	System.out.println(orderId);
        return orderId;
    }
}

2.post请求

    @PostMapping("/test")
    public Object test(@Validated User user) {
    
    
    	System.out.println("------------" + user.getUserId());
        return "ok";
        
    }
package cn.gzsendi.modules.test.controller;

import javax.validation.constraints.NotNull;

public class User {
    
    

	@NotNull(message="userId不能为空")
	private String userId;

	public String getUserId() {
    
    
		return userId;
	}

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

3.AssertFalse[必须为false]

必须为false,The annotated element must be false.

	@AssertFalse(message="结果必须为false")
	private boolean result;

3.AssertTrue[必须为true]

必须为true,支持类型有boolean和Boolean。The annotated element must be true. Supported types are boolean and Boolean.

	@AssertTrue(message="参数必须为true")
	private boolean result;

4.DecimalMax

数字,其值必须小于或等于指定的最大值,The annotated element must be a number whose value must be lower or equal to the specified maximum.支持的类型有:BigDecimal,BigInteger,CharSequence,byte,short,int,long以及他们的包装类。

	@DecimalMax(value = "10",message = "参数age应该小于或等于10.")
	private int age;

5.DecimalMin

数字,其值必须大于或等于指定的值,The annotated element must be a number whose value must be higher or equal to the specified minimum.支持的类型有:BigDecimal,BigInteger,CharSequence,byte,short,int,long以及他们的包装类。

	@DecimalMin(value = "10",message = "参数age应该大于或等于10.")
	private int age;

6.Digits

整数位数不能超过integer位数,小数位数不能超过fraction位数.
The annotated element must be a number within accepted range.
Supported types are:BigDecimal、BigInteger、CharSequence、byte、short、int、long和他们的包装类。

	@Digits(integer = 1, fraction = 2,message = "整数位数不能超过1,小数位数不能超过2.")
	private BigDecimal value;

7.Email

参数必须为email格式,如果参数为空,也会通过校验,所以如果参数为非空且必须为email格式时,需要与@NotNull结合使用。
Accepts:CharSequence,也就是适用于字符串类型的校验

	@Email(message = "参数必须为email格式.")
	private String email;

8.Future

参数必须为将来的日期或时间,适用于日期,时间等参数类型:java.util.Date、java.util.Calendar、java.time.LocalDate、java.time.LocalDateTime等等。

	@Future(message = "日期参数必须为将来的时间.")
	private Date signDate;
	@Future(message = "任务时间参数必须为将来的时间.")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
	private Date taskTime;

9.FutureOrPresent

参数必须为当前或将来的日期或时间
The annotated element must be an instant, date or time in the present or in the future.

	@FutureOrPresent(message = "任务时间参数必须为当前或将来的时间.")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
	private Date taskTime;

10.Max

数值类型,值必面小于或等于一个值。
The annotated element must be a number whose value must be lower or equal to the specified maximum.

	@Max(value = 99 , message = "年龄参数最大不能超过99.")
	private int age;

11.Min

数值类型,值必面大于或等于一个值。

	@Min(value = 18 , message = "年龄参数必须大于或等于18.")
	private int age;

12.Negative

数值,参数校验必须为负数。
The annotated element must be a strictly negative number.

	@Negative(message = "value必须为负数.")
	private int value;

13.NegativeOrZero

数值,参数校验必须为负数或者0。
The annotated element must be a negative number or 0.

	@Negative(message = "value必须为负数.")
	private int value;

14.NotBlank

参数为字符串,且不能为空,至少包含一个非空白字符串
must not be null and must contain at least one non-whitespace character.

	@NotBlank(message = "value参数不能为空.")
	private String value;

15.NotEmpty

参数为字符串,且不能为空,不能为空字符串,空白字符串可以通过校验。
must not be null and must contain at least one non-whitespace character.

	@NotEmpty(message = "value参数不能为空,不能为空字符串.")
	private String value;

16.NotNull

参数为任意类型,且不能为空。
The annotated element must not be null。

	@NotNull(message = "value参数不能为空.")
	private String value;

17.Null

参数必须为Null
The annotated element must be null.

	@Null(message = "value参数应该为空.")
	private String value;

18.Past

时间参数需要一个过去的时间
The annotated element must be an instant, date or time in the past.

	@Past(message = "时间参数需要是过去的时间")
	private Date value;

19.PastOrPresent

时间参数需要是过去的时间或当前的时间,而不是将来。
The annotated element must be an instant, date or time in the past or in the present.

	@PastOrPresent(message = "时间参数需要是过去的时间或当前的时间,而不是将来。")
	private Date value;

20.Pattern

正则表达式参数校验,必须满足对应的正则表达式语法
The annotated CharSequence must match the specified regular expression.
比如电话号码校验

	@Pattern(regexp = "^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$",message = "参数必须为电话号码!")
	private String value;

21.Positive

数值校验,校验参数必须为正数。
The annotated element must be a strictly positive number (i.e. 0 is considered as an invalid value.

	@Positive(message = "参数必须为正数!")
	private BigDecimal value;

22.PositiveOrZero

数值校验,校验参数必须为正数或者0。
The annotated element must be a positive number or 0.

	@PositiveOrZero(message = "参数必须为正数或者0!")
	private BigDecimal value;

23.Size

字符数校验,最小min个字符,最大max字符,max可以省去,默认为Integer.MAX_VALUE
The annotated element size must be between the specified boundaries (included).

	@Size(min = 5, max = 10,message = "参数需要最少五个字符,最大10个字符!")
	private String value;
	@Size(min = 5, message = "参数需要最少五个字符!")
	private String value;

24.Length

org.hibernate.validator.constraints中的注解,有点类似Size注解
校验字符串长度是否在min和max之间
Validate that the string is between min and max included.

import org.hibernate.validator.constraints.Length;

	@Length(min = 5, max = 10, message = "参数需要最少五个字符,最大10个字符!")
	private String value;

25.Range

范围校验,数值型适用,Apply on numeric values or string representation of the numeric value.

	@Range(min = 60, max = 100, message = "Value值需要在60至100之间")
	private int value;

五、其他

1.使用@Valid校验属性对象

比如ReqBody对象中有data对象,在conroller中的方式如下:

    @PostMapping("/test")
    public Object test(@RequestBody @Validated ReqBody<User> query) {
    
    
        return "ok";
    }

如果ReqBody中按以下的校验进行

    @NotNull(message = "请求参数不能为空")
    private T data;

data参数校验不能为空,可以正常,但如果我们希望对User对象里面的属性如age继续进行校验,需要在data上再加上@Valid才会生效,如下:

    @NotNull(message = "请求参数不能为空")
    @Valid
    private T data;

此时在data属性为User时,会继续校验User对象中的属性,比如,
如果在data上不加上@Valid,不会校验User中的value属性

public class User implements Serializable{
    
    
	@Length(min = 5, max = 10, message = "参数需要最少五个字符,最大10个字符!")
	private String value;
}

2.分组参数校验

有时需要在不同的方法中共用相同的Bean对象,但校验规则可能不同。比如,修改User时需要检验id字段不能为空,但新增时不需要校验。此时可以将不同的校验规则分给不同的组,在使用时,指定不同的校验规则

  1. 定义好Group接口类,比如:
package cn.gzsendi.modules.model;

public interface ValidationGroup {
    
    

    //新增分组
    interface  Add{
    
    }

    //修改分组
    interface Update{
    
    }

}
  1. 在controller类绑定接口类
    //新增用户
    @PostMapping("/add")
    public Object add(@RequestBody @Validated(ValidationGroup.Add.class) User user) {
    
    
        System.out.println(user);
        return "ok";
    }

    //修改用户
    @PostMapping("/update")
    public Object update(@RequestBody @Validated(ValidationGroup.Update.class) User user) {
    
    
        System.out.println(user);
        return "ok";
    }
  1. 在Bean类绑定接口类
@Data
public class User implements Serializable{
    
    

	private static final long serialVersionUID = 6413803405134098800L;

	@NotNull(groups = {
    
    ValidationGroup.Update.class} ,message = "修改User时Id不能为空!")
	private Integer id;

	private String userName;

}

经过以上之后,在被调用新增接口/add时,不会对Id参数进行校验,而/update接口被调用时,如果id参数为空,将不通过参数验证。

3.validator自定义校验

如果springboot自带的校验规则不满足要求,我们可以自己定义的校验逻辑。
比如User对象中,userId必须为admin,test,manager三个值中的一个,其他情况下均需要校验失败。

  1. 定义我们自己的注解
package cn.gzsendi.modules.validators;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
    
     ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
@Constraint(validatedBy = MytestValidator.class)
public @interface MytestValid {
    
    
    String message() default "默认的校验失败提示信息";
    Class<?>[] groups() default {
    
    };
    Class<? extends Payload>[] payload() default {
    
    };
}
  1. 定义我们自己的校验器
    自定义的校验器实现ConstraintValidator类接口
package cn.gzsendi.modules.validators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.List;

public class MytestValidator implements ConstraintValidator<MytestValid, String> {
    
    

    private List<String> userIds = Arrays.asList("admin","test","manager");

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
    
    
        System.out.println(this.hashCode());
        return userIds.contains(value);
    }
}

  1. 在我们的Bean实体类属性上使用自定义的校验注解
    使用自定义的注解,可以结合其他注解一起使用,比如:
	@NotBlank(message = "userId不能为空!")
	@MytestValid(message = "userId参数只能取admin,test,manager中的一个")
	private String userId;

猜你喜欢

转载自blog.csdn.net/jxlhljh/article/details/125926588