来咯来咯!2021年,开发者对SpringBoot中实现约束验证,你懂得多少|牛气冲天新年征文

前言

首先呢,先祝你们新年快乐!!牛年大吉!!html

咱们如今开启咱们新一年的学习吧。今天,咱们将聊一下在Springboot应用程序中验证数据的经常使用实现。java

Hibernate验证器

通常实现是经过使用Bean验证API进行验证。Bean验证API的参考实现是Hibernate验证器。spring

全部必需的依赖项都打包在springbootstarter POM springbootstarter验证中。所以,一般您只须要开始如下依赖关系:数据库

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
复制代码

验证约束是经过使用适当的Bean验证注解对字段进行注解来定义的。例如:编程

public class Address {
 
    @NotBlank
    @Size(max = 50)
    private String street;
 
    @NotBlank
    @Size(max = 50)
    private String city;
 
    @NotBlank
    @Size(max = 10)
    private String zipCode;
     
    @NotBlank
    @Size(max = 3)
    private String countryCOde;
 
    // getters + setters
}
复制代码

对于这些注解的做用是显而易见的。咱们将在下面的许多示例中使用到这个Address类。springboot

能够在Bean验证文档中找到内置约束注解的完整列表。markdown

若是有须要,经过建立自定义约束验证器来定义本身的验证约束。app

请求数据验证

在使用Springboot构建RestAPI接口时,大多时候须要验证传入的请求数据。这能够经过简单地将@Valid注解添加到@RequestBody方法参数来完成。框架

例如:函数

@RestController
public class AddressController {
 
    @PostMapping("/address")
    public void createAddress(@Valid @RequestBody Address address) {
        // ..
    }
}
复制代码

经过@Valid注解,就开启了数据约束验证。

Spring如今根据先前定义的约束自动验证传递的Address对象。

这种类型的验证一般用于确保客户端发送的数据语法正确。若是验证失败,则不调用控制器方法,并向客户端返回HTTP 400(错误请求)响应。更复杂的特定于业务的验证约束一般应该稍后在业务层中检查。

持久层数据验证

在Springboot应用程序中使用关系数据库时,持久层采用了Hibernate框架,也会支持验证。Hibernate支持Bean验证。若是实体包含Bean验证注解,则在持久化实体时会自动检查这些注解。

请注意,持久层绝对不该该是验证的惟一位置。若是验证在这里失败,一般意味着其余应用程序组件中缺乏某种验证。持久层验证应该被视为最后一道防线。除此以外,持久性层对于与业务相关的验证来讲一般为时已晚。

方法参数验证

Spring提供了对于方法参数的数据约束验证。经过向方法参数添加Bean验证注解。而后,Spring使用AOP拦截器在调用实际方法以前验证参数。

例如:

@Service
@Validated
public class CustomerService {
 
    public void updateAddress( @Pattern(regexp = "\\w{2}\\d{8}") String customerId, @Valid Address newAddress ) {
        // ..
    }
}
复制代码

另外,这种方法对于验证进入服务层的数据很是有用。可是,在使用这种方法以前,应该了解它的局限性,由于这种类型的验证只有在涉及Spring代理时才有效。

同时须要注意,这种方法会使单元测试变得更困难。

编程方式触发Bean验证

在上述的验证方案中,实际的验证是由Spring或Hibernate触发的。不少时候,咱们须要根据合适时机,灵活触发Bean验证。

下面,咱们尝试用编程方式,触发对于Bean验证。

咱们首先建立一个验证Facade bean:

@Component
public class ValidationFacade {
 
    private final Validator validator;
 
    public ValidationFacade(Validator validator) {
        this.validator = validator;
    }
 
    public <T> void validate(T object, Class<?>... groups) {
        Set<ConstraintViolation<T>> violations = validator.validate(object, groups);
        if (!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
}
复制代码

这个bean接受一个验证器做为有参构造函数。验证器是Bean验证API的一部分,负责验证Java对象。

在validate(..)方法中,咱们使用验证器来验证传递的对象。结果是一组约束冲突。若是未违反任何验证约束(=对象有效),则集合为空。不然,咱们抛出一个约束冲突异常。

咱们如今能够将咱们的验证门面注入到其余bean中。例如:

@Service
public class CustomerService {
 
    private final ValidationFacade validationFacade;
 
    public CustomerService(ValidationFacade validationFacade) {
        this.validationFacade = validationFacade;
    }
 
    public void updateAddress(String customerId, Address newAddress) {
        validationFacade.validate(newAddress);
        // ...
    }
}

复制代码

为了验证一个对象Address(这里是新地址),咱们只需调用validate(..)方法。固然,咱们也能够将验证器直接注入到咱们的客户服务中。可是,在验证错误的状况下,咱们一般不但愿处理返回的约束冲突集。相反,咱们可能只想抛出一个异常,这正是验证门面所作的。

一般,这是在服务/业务层进行验证的好的一种实现。它不只限于方法参数,并且能够用于不一样类型的对象。例如,咱们能够从数据库中加载一个对象,修改它,而后在继续以前验证它。

这种方法对于单元测试也很好,由于咱们能够简单地模拟验证门面。若是咱们想在单元测试中进行真正的验证,能够手动建立所需的验证器实例。

验证内部业务类

咱们能够对实际的业务Bean对象进行建立时的动态验证。

在DDD领域驱动设计开发时,采用动态验证比较重要。例如,在建立地址实例时,构造函数能够确保咱们不能构造无效的对象:

public class Address {
 
    @NotBlank
    @Size(max = 50)
    private String street;
 
    @NotBlank
    @Size(max = 50)
    private String city;
 
    ...
     
    public Address(String street, String city) {
        this.street = street;
        this.city = city;
        ValidationHelper.validate(this);
    }
}

复制代码

在这里,构造函数调用静态validate(..)方法来验证对象状态。这个静态validate(..)方法与前面在ValidationFacade中显示的方法相似:

这里的区别是,咱们没有经过Spring检索验证程序实例。相反,咱们使用如下方法手动建立:

Validation.buildDefaultValidatorFactory().getValidator()
复制代码

经过这种方式,咱们能够直接将验证集成到域对象中,而无需依赖外部人员来验证对象。

总结

今天咱们聊了下,在Springboot应用程序中处理验证的不一样方法。

不一样的使用,根据具体的业务须要,咱们实际去作本身的开发策略。

好了,今天聊天结束。新的一年,你们也要好好学习哦!

相关文章
相关标签/搜索