【javax.validation】Group分组校验

在很多时候,同一个模型可能会在多处被用到,但每处的校验场景又不一定相同(如:新增用户接口、修改用户接口,参数都是User模型,在新增时User中name字段不能为空,userNo字段可以为空;在修改时User中name字段可以为空,userNo字段不能为空)。我们可以用groups来实现:同一个模型在不同场景下,(动态区分)校验模型中的不同字段。

实现groups功能的主要逻辑源码,可详见org.hibernate.validator.internal.engine.ValidatorImpl#validate。

自定义分组

public interface Create {}
public interface Update extends Default {}

提示:继承Default并不是必须的。只是说,如果继承了Default,那么@Validated(value = Create.class)的校验范畴就为CreateDefault;如果没继承Default,那么@Validated(value = Create.class)的校验范畴只为Create,而@Validated(value = {Create.class, Default.class})的校验范畴才为CreateDefault
追注:原因可见下面的第二步中的说明。

第一步:在给模型里面的参数定义校验规则时,给校验分配所属分组。

// 当前校验属于Create组
@NotEmpty(groups = Create.class)
private String name;
// 当前校验属于Update组
@NotEmpty(groups = Update.class)
private String nick;
// 当前校验既属于Create组,又属于Update组
@NotEmpty(groups = {Create.class, Update.class})
private String hobby;
// 当前校验属于Default组
@NotEmpty(groups = Default.class)
private String idNo;
// 当前校验属于Default组
@NotEmpty
private String address;
// 当前校验既属于Create组,又属于Update组。@Range可重复
@Range(min = 1L, max = 3L, groups = Create.class)
@Range(min = 2L, max = 4L, groups = Update.class)
private Integer age;

注:Default组和无参构造机制类似,当没有指定分组时,会默认当前校验属于Default组,但是一旦主动给当前校验指定了分组(如上图中的nick字段,主动指定了属于Update组),那么就不会再额外指定属于Default组了。当然,也可以画蛇添足的主动指定所属分组为Default

@NotEmpty@NotEmpty(groups = Default.class)是等价的。若不指定groups.那么会默认属于Default
注:可详见源码org.hibernate.validator.internal.engine.ValidatorImpl#determineGroupValidationOrder

第二步:启动校验时,指定校验(组别)范畴。

说明:校验范畴,会向上递归查找组。可详见源码org.hibernate.validator.internal.engine.groups.ValidationOrderGenerator#getValidationOrder

// 因为Create未继承Default,所以这里的校验范畴是:
// 隶属于Create组下的校验设置,都会触发校验
@PostMapping("/one")
public String one(@RequestBody @Validated(Create.class) Man man) {return "one";}
// 因为Update继承了Default,所以这里的校验范畴是:
// 隶属于Update组或Default组下的校验设置,都会触发校验
@PostMapping("/two")
public String two(@RequestBody @Validated(Update.class) Man man) {return "two";}
// 隶属于Create组或Update组或Default组下的校验设置,都会触发校验
@PostMapping("/thr")
public String thr(@RequestBody @Validated({Create.class, Update.class}) Man man) {retur
// 隶属于Default组下的校验设置,都会触发校验
@PostMapping("/foe")
public String foe(@RequestBody @Validated(Default.class) Man man) {return "foe";}
// 隶属于Default组下的校验设置,都会触发校验
@PostMapping("/fiv")
public String fiv(@RequestBody @Validated Man man) {return "fiv";}
// 隶属于Default组下的校验设置,都会触发校验
@PostMapping("/six")
public String six(@RequestBody @Valid Man man) {return "six";}

@Valid@Validated@Validated(Default.class)是等价的。

具体校验情况如下:

  • Create未继承Default,则@Validated(Create.class)的校验范畴为Create。以下字段会触发校验
    name、hobby、age(@Range(1-3))
  • Update继承了Default,则@Validated(Update.class)的校验范畴为UpdateDefault。以下字段会触发校验
    nick、hobby、idNo、address、age(@Range(2-4))
  • @Validated({Create.class, Update.class})的校验范畴为CreateUpdateDefault。以下字段会触发校验
    name、nick、hobby、idNo、address、age(@Range(2-3))
  • @Valid@Validated@Validated(Default.class)的校验范畴一样,为Default。以下字段会触发校验
    nick、hobby、idNo、address、age(@Range(2-4))

注:还有一个用于联合校验(如:字段A的校验,依赖于字段B的校验)等场景的注解javax.validation.GroupSequence有时也非常实用,感兴趣的可自行了解。

参考文档

SpringBoot使用Validation校验参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值