@Validated @Valid 分组+内嵌 controller+service

@Validated @Valid 分组+内嵌 controller+service

作者:kaoli

如何实现优雅的参数校验?

看网上的文章都是实现分组的同时无法针对对象集合或者属性是自定义类的类型进行校验,也就是无法分组+内嵌同时校验,进而做了一大堆自定义的校验来实现,近期测试了一下,发现现有的校验框架足以实现该需求。

测试环境 web服务 springboot 2.0.6 比较老。。。

对于restful服务,可以在controller层结合使用@Validated 和 @Valid校验,

// =====controller层  支持分组+内嵌校验=======

//controller
@PostMapping("/buy")
public ApiResponse<?> buyInstantce(@Validated(InstatncePay.Buy.class) @RequestBody InstatncePay payD){
  //购买...

}

// 入参对象
@Data
public class InstatncePay {
    /**
     * 支付方式
     */
    @Pattern(regexp = "^KAOLI_PAY$", message = "只支持kaoli支付", groups = {Buy.class, Recharge.class})
    @NotBlank(message = "请选择支付方式")
    private String payChannel;
    
    /**
     * 续费时
     */
    @NotNull(message = "请选择续费实例", groups = {Recharge.class})
    private List<String> instatnceIds;
  
    // 注意 @Valid会内嵌校验
    @Valid
    @NotEmpty(message = "instances is empty", groups = Buy.class)
    private List<InstanceInfo> instances;

    public interface Buy {}
    public interface Recharge {}
}
// 属性对象
@Data
public class InstanceInfo{

    // 属性对象中可以继续分组
    /**
     * 购买数量
     */
    @Range(min = 1, max = 10, message = "一次性最多购买10个")
    @NotNull(message = "请填写购买数量", groups = {Buy.class})
    private Integer count;
    /**
     * 名称
     */
    @NotBlank(message = "名称不能为空", groups = {Buy.class})
    private String name;

}

我们更习惯在controller层校验,但是开发总是遇到各种各样的场景:

比如说,service层是我们经常写逻辑的地方,也是代码复用较多的地方,假如校验放在service层,我们每次调用的时候是不是不用重复校验了。

另外,有时我们要提供dubbo服务,在service层做校验也是逃不掉的。。。

那么在现有的校验框架下,service层也可以像controller一样实现优雅校验吗?

当然可以

// =====service层 支持分组+内嵌=======

// insterface
public interface InstanceService {
    // 注意 参数校验 @Valid,此处必须有
    void buy(@Valid InstatncePay payDTO);
}

// impl
@Service
@Validated // 注意 @Validated 校验是支持加到类上的   这些校验注解加到接口也可直接生效
public class InstanceServiceImpl implements InstanceService {
  
  @Override
  @Validated(InstatncePay.Buy.class) // 若不分组校验,可以不加该行
  public void buy(@Valid InstatncePay payDTO) {//接口处已经加过@Valid,此处@Valid可以删除,为方便查看也可以保留
    
    // 。。。。。
    return null;
  }
}

// 实现类中的 @Validated和@Valid等校验注解可全部放在接口中,依旧生效。

// 注意异常处理,service层校验不通过会抛 javax.validation.ConstraintViolationException,可以全局处理。

转载请标明来源 kaoli

这样就不用写一堆参数校验了,业务代码也能更简洁,CRUD也能更快了,又有时间摸鱼了。。

posted @ 2022-04-29 21:47  kaoli-烤梨  阅读(778)  评论(1)    收藏  举报