正则校验空格_validator 自动化校验

本文详细介绍了 Hibernate-Validator 的使用,它实现了 JSR 380 和 303 规范,提供了一种在控制器、服务、DAO 层进行统一数据校验的方式。通过 @Valid 和 @Validated 等注解,可以简化校验逻辑,提高代码可维护性。文章还列举了 22 个常用的约束注解,如 @NotNull、@Size 等,并给出了实际应用示例,帮助读者掌握校验工具的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bc51c079ec34692e64d538d7e842b1b3.png

温馨提示

请收藏再看。此文篇幅太长,你短时间看不完;此文干货太多,错过太可惜。

示例代码可以私信我获取。

收获

  1. 讲解详细:能让你掌握使用 hibernate-validator 及类似校验工具的各种使用姿势
  2. 内容全面:可以当做知识字典来查询

what

注意:hibernate-validator 与 持久层框架 hibernate 没有什么关系,hibernate-validator 是 hibernate 组织下的一个https://github.com/hibernate/hibernate-validator。

hibernate-validator 是 JSR 380(Bean Validation 2.0)、JSR 303(Bean Validation 1.0)规范的实现。

JSR 380 - Bean Validation 2.0 定义了一个实体和方法验证的元数据模型和 API。

JavaEE(改名为:Jakarta EE)中制定了 validation 规范,即:javax.validation-api(现为 jakarta.validation-api,jar 包的名字改变,包里面的包名、类名未变,因此使用方式不变)包,spring-boot-starter-web、spring-boot-starter-webflux 包都已引入此依赖,直接使用即可。

有点类似于 slf4j 与 logback(log4j2)的关系,使用的时候,代码中使用 javax.validate 提供的接口规范功能,加载的时候,根据 SPI 规范加载对应的规范实现类。

它和 hibernate 没什么关系,放心大胆的使用吧。

why

hibernate-validator 官方有如下说明:

以前的校验如下:

f47426fd207c5a7dd377a39f1dd1087e.png

使用 hibernate-validator 后,校验逻辑如下:

6b67af36cf3caa7718c04b1626556d2f.png

controller、service、dao 层相同的校验逻辑可以使用同一个数据校验模型。

how

标识注解

@Valid(规范、常用)

标记用于验证级联的属性、方法参数或方法返回类型。

在验证属性、方法参数或方法返回类型时,将验证在对象及其属性上定义的约束。

此行为是递归应用的。

@Validated(spring)

spring 提供的扩展注解,可以方便的用于分组校验

22 个约束注解

下面除了列出的参数,每个约束都有参数 message,groups 和 payload。这是 Bean Validation 规范的要求。

其中,message 是提示消息,groups 可以根据情况来分组。

以下每一个注解都可以在相同元素上定义多个。

@AssertFalse

检查元素是否为 false,支持数据类型:boolean、Boolean

@AssertTrue

检查元素是否为 true,支持数据类型:boolean、Boolean

@DecimalMax(value=, inclusive=)

inclusive:boolean,默认 true,表示是否包含,是否等于value:当 inclusive=false 时,检查带注解的值是否小于指定的最大值。当 inclusive=true 检查该值是否小于或等于指定的最大值。参数值是根据 bigdecimal 字符串表示的最大值。支持数据类型:BigDecimal、BigInteger、CharSequence、(byte、short、int、long 和其封装类)

@DecimalMin(value=, inclusive=)

支持数据类型:BigDecimal、BigInteger、CharSequence、(byte、short、int、long 和其封装类)inclusive:boolean,默认 true,表示是否包含,是否等于value:当 inclusive=false 时,检查带注解的值是否大于指定的最大值。当 inclusive=true 检查该值是否大于或等于指定的最大值。参数值是根据 bigdecimal 字符串表示的最小值。

@Digits(integer=, fraction=)

检查值是否为最多包含 integer 位整数和 fraction 位小数的数字支持的数据类型:BigDecimal, BigInteger, CharSequence, byte, short, int, long 、原生类型的封装类、任何 Number 子类。

@Email

检查指定的字符序列是否为有效的电子邮件地址。可选参数 regexp 和 flags 允许指定电子邮件必须匹配的附加正则表达式(包括正则表达式标志)。支持的数据类型:CharSequence

@Max(value=)

检查值是否小于或等于指定的最大值支持的数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@Min(value=)

检查值是否大于或等于指定的最大值支持的数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@NotBlank

检查字符序列是否为空,以及去空格后的长度是否大于 0。与 @NotEmpty 的不同之处在于,此约束只能应用于字符序列,并且忽略尾随空格。支持数据类型:CharSequence

@NotNull

检查值是否为 null支持数据类型:任何类型

@NotEmpty

检查元素是否为 null 或 空支持数据类型:CharSequence, Collection, Map, arrays

@Size(min=, max=)

检查元素个数是否在 min(含)和 max(含)之间支持数据类型:CharSequence,Collection,Map, arrays

@Negative

检查元素是否严格为负数。零值被认为无效。支持数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@NegativeOrZero

检查元素是否为负或零。支持数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@Positive

检查元素是否严格为正。零值被视为无效。支持数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@PositiveOrZero

检查元素是否为正或零。支持数据类型:BigDecimal, BigInteger, byte, short, int, long, 原生类型的封装类, CharSequence 的任意子类(字符序列表示的数字), Number 的任意子类, javax.money.MonetaryAmount 的任意子类

@Null

检查值是否为 null支持数据类型:任何类型

@Future

检查日期是否在未来支持的数据类型:java.util.Date, java.util.Calendar, java.time.Instant, java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime, java.time.MonthDay, java.time.OffsetDateTime, java.time.OffsetTime, java.time.Year, java.time.YearMonth, java.time.ZonedDateTime, java.time.chrono.HijrahDate, java.time.chrono.JapaneseDate, java.time.chrono.MinguoDate, java.time.chrono.ThaiBuddhistDate如果 http://www.joda.org/joda-time/ API 在类路径中,ReadablePartial 和ReadableInstant 的任何实现类

@FutureOrPresent

检查日期是现在或将来支持数据类型:同@Future

@Past

检查日期是否在过去支持数据类型:同@Future

@PastOrPresent

检查日期是否在过去或现在支持数据类型:同@Future

@Pattern(regex=, flags=)

根据给定的 flag 匹配,检查字符串是否与正则表达式 regex 匹配支持数据类型:CharSequence

实现示例

@Size

从上文可知,规范中,@Size 支持的数据类型有:CharSequence,Collection,Map, arrayshibernate-validator 中的实现如下:

efcb8847ae02c356d2d0a4f6fe92c8bd.png

针对 CharSequence、Collection、Map 都有一个实现,由于 arrays 有多种可能,提供了多个实现。其中,SizeValidatorForCollection.java 如下:

import java.lang.invoke.MethodHandles;

import java.util.Collection;

import javax.validation.ConstraintValidator;

import javax.validation.ConstraintValidatorContext;

import javax.validation.constraints.Size;

@SuppressWarnings("rawtypes")

// as per the JLS, Collection> is a subtype of Collection, so we need to explicitly reference

// Collection here to support having properties defined as Collection (see HV-1551)

public class SizeValidatorForCollection implements ConstraintValidator {

private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );

private int min;

private int max;

@Override

public void initialize(Size parameters) {

min = parameters.min();

max = parameters.max();

validateParameters();

}

@Override

public boolean isValid(Collection collection, ConstraintValidatorContext constraintValidatorContext) {

if ( collection == null ) {

return true;

}

int length = collection.size();

return length >= min && length <= max;

}

private void validateParameters() {

if ( min < 0 ) {

throw LOG.getMinCannotBeNegativeException();

}

if ( max < 0 ) {

throw LOG.getMaxCannotBeNegativeException();

}

if ( max < min ) {

throw LOG.getLengthCannotBeNegativeException();

}

}

}

实现逻辑就是按照规范的说明来实现的。

实战

声明 Java Bean 约束

可以用以下方式声明约束:

  1. 字段级别约束

@NotNull

private String manufacturer;

  1. 属性级别约束

@NotNull

public String getManufacturer(){

return manufacturer;

}

  1. 容器级别约束

private Map fuelConsumption = new HashMap<>();

  1. 类级别约束
  2. 在这种情况下,验证的对象不是单个属性,而是完整的对象。如果验证依赖于对象的多个属性之间的相关性,则类级约束非常有用。
  3. 如:汽车中,乘客数量不能大于座椅数量,否则超载

@ValidPassengerCount

public class Car {

private int seatCount;

private List passengers;

//...

}

  1. 约束继承
  2. 当一个类继承/实现另一个类时,父类声明的所有约束也会应用在子类继承的对应属性上。
  3. 如果方法重写,约束注解将会聚合,也就是此方法父类和子类声明的约束都会起作用。
  4. 级联验证
  5. Bean Validation API 不仅允许验证单个类实例,也支持级联验证。
  6. 只需使用 @Valid 修饰对象属性的引用,则对象属性中声明的所有约束也会起作用。
  7. 如以下示例,当验证 Car 实例时,Person 对象中的 name 字段也会验证。

public class Car {

@NotNull

@Valid

private Person driver;

//...

}

public class Person {

@NotNull

private String name;

//...

}

声明方法约束

参数约束

通过向方法或构造函数的参数添加约束注解来指定方法或构造函数的前置条件,官方示例如下:

public RentalStation(@NotNull String name){}

public void rentCar(@NotNull Customer customer,

@NotNull @Future Date startDate,

@Min(1) int durationInDays){}

返回值约束

通过在方法体上添加约束注解来给方法或构造函数指定后置条件,官方示例如下:

public class RentalStation {

@ValidRentalStation

public RentalStation() {

//...

}

@NotNull

@Size(min = 1)

public List getCustomers() {

//...

return null;

}

}

此示例指定了三个约束:

  • 任何新创建的 RentalStation 对象都必须满足 @validRentalStation 约束
  • getCustomers() 返回的客户列表不能为空,并且必须至少包含 1 个元素
  • getCustomers() 返回的客户列表不能包含空对象

级联约束

类似于 JavaBeans 属性的级联验证,@Valid 注解可用于标记方法参数和返回值的级联验证。

类似于 javabeans 属性的级联验证(参见第 2.1.6 节“对象图”),@valid 注释可用于标记可执行参数和级联验证的返回值。当验证用@valid 注释的参数或返回值时,也会验证在参数或返回值对象上声明的约束。而且,也可用在容器元素中。

public class Garage {

public boolean checkCars(@NotNull List cars) {

//...

return false;

}

}

继承验证

当在继承体系中声明方法约束时,必须了解两个规则:

  • 方法调用方要满足前置条件不能在子类型中得到加强
  • 方法调用方要保证后置条件不能再子类型中被削弱

这些规则是由子类行为概念所决定的:在使用类型 T 的任何地方,也能在不改变程序行为的情况下使用 T 的子类。

当两个类分别有一个同名且形参列表相同的方法,而另一个类用一个方法重写/实现上述两个类的同名方法时,这两个父类的同名方法上不能有任何参数约束,因为不管怎样都会与上述规则冲突。示例:

public interface Vehicle {

void drive(@Max(75) int speedInMph);

}

public interface Car {

void drive(int speedInMph);

}

public class RacingCar implements Car, Vehicle {

@Override

public void drive(int speedInMph) {

//...

}

}

分组约束

请求组

注意:上述的 22 个约束注解都有 groups 属性。当不指定 groups 时,默认为 Default 分组。

JSR 规范支持手动校验,不直接支持使用注解校验,不过 spring 提供了分组校验注解扩展支持,即:@Validated,参数为 group 类集合

分组继承

在某些场景下,需要定义一个组,它包含其它组的约束,可以用分组继承。如:

public class SuperCar extends Car {

@AssertTrue(

message = "Race car must have a safety belt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值