spring-boot-starter-validation参数校验
- 一、spring-boot-starter-validation简介
- 二、校验说明
- 三、pom.xml依赖引入
- 四、校验示例测试
-
- 1.get请求
- 2.post请求
- 3.AssertFalse[必须为false]
- 3.AssertTrue[必须为true]
- 4.DecimalMax
- 5.DecimalMin
- 6.Digits
- 7.Email
- 8.Future
- 9.FutureOrPresent
- 10.Max
- 11.Min
- 12.Negative
- 13.NegativeOrZero
- 14.NotBlank
- 15.NotEmpty
- 16.NotNull
- 17.Null
- 18.Past
- 19.PastOrPresent
- 20.Pattern
- 21.Positive
- 22.PositiveOrZero
- 23.Size
- 24.Length
- 25.Range
- 五、其他
一、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格式时,需要与@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字段不能为空,但新增时不需要校验。此时可以将不同的校验规则分给不同的组,在使用时,指定不同的校验规则
定义好Group接口类,比如:
package cn.gzsendi.modules.model;
public interface ValidationGroup {
//新增分组
interface Add{
}
//修改分组
interface Update{
}
}
在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";
}
在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三个值中的一个,其他情况下均需要校验失败。
- 定义我们自己的注解
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 {
};
}
- 定义我们自己的校验器
自定义的校验器实现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);
}
}
- 在我们的Bean实体类属性上使用自定义的校验注解
使用自定义的注解,可以结合其他注解一起使用
,比如:
@NotBlank(message = "userId不能为空!")
@MytestValid(message = "userId参数只能取admin,test,manager中的一个")
private String userId;