来咯来咯!2021年,开发者对SpringBoot中实现约束验证,你懂得多少

简介: 来咯来咯!2021年,开发者对SpringBoot中实现约束验证,你懂得多少

前言

首先呢,先祝大家新年快乐!!牛年大吉!!

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

Hibernate验证器

一般实现是通过使用Bean验证API进行验证。Bean验证API的参考实现是Hibernate验证器。

所有必需的依赖项都打包在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类。

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

如果有需要,通过创建自定义约束验证器来定义自己的验证约束。

请求数据验证

在使用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应用程序中处理验证的不同方法。

不同的使用,根据具体的业务需要,我们实际去做自己的开发策略。

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

目录
相关文章
|
6月前
|
前端开发 安全 Java
SpringBoot验证框架@Valid
SpringBoot验证框架@Valid
75 1
|
6月前
|
JSON 前端开发 Java
SpringBoot 的优雅的接口参数验证
1. 为什么需要参数验证 在应用程序的开发中,我们经常会遇到需要保证传入参数的正确性的情况。例如,当我们在注册用户时,需要验证用户填写的表单数据是否符合规范,是否缺少必填字段,或者格式是否正确,等等。如果不对参数进行验证,我们的应用程序可能会因此受到攻击或者运行出错。 为了保证参数的正确性,我们需要使用参数验证机制,来检测并处理传入的参数格式是否符合规范。 2. 如何进行参数验证 Spring Boot内置了一个很强大的参数验证框架——JSR 303 Bean Validation 标准,它可以对我们的实体类参数进行校验,并且可以给我们提供详细的错误提示信息。
132 1
|
18天前
|
JSON 安全 算法
|
1月前
|
前端开发 Java 数据安全/隐私保护
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
文章通过一个简单的SpringBoot项目,详细介绍了前后端如何实现用户登录功能,包括前端登录页面的创建、后端登录逻辑的处理、使用session验证用户身份以及获取已登录用户信息的方法。
146 2
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
|
22天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
32 0
|
3月前
|
开发框架 负载均衡 Java
当热门技术负载均衡遇上 Spring Boot,开发者的梦想与挑战在此碰撞,你准备好了吗?
【8月更文挑战第29天】在互联网应用开发中,负载均衡至关重要,可避免单服务器过载导致性能下降或崩溃。Spring Boot 作为流行框架,提供了强大的负载均衡支持,通过合理分配请求至多台服务器,提升系统可用性与可靠性,优化资源利用。本文通过示例展示了如何在 Spring Boot 中配置负载均衡,包括添加依赖、创建负载均衡的 `RestTemplate` 实例及服务接口调用等步骤,帮助开发者构建高效、稳定的应用。随着业务扩展,掌握负载均衡技术将愈发关键。
73 6
|
6月前
|
Java 数据库 数据安全/隐私保护
【SpringBoot】Validator组件+自定义约束注解实现手机号码校验和密码格式限制
【SpringBoot】Validator组件+自定义约束注解实现手机号码校验和密码格式限制
609 1
|
3月前
|
Java API UED
【实战秘籍】Spring Boot开发者的福音:掌握网络防抖动,告别无效请求,提升用户体验!
【8月更文挑战第29天】网络防抖动技术能有效处理频繁触发的事件或请求,避免资源浪费,提升系统响应速度与用户体验。本文介绍如何在Spring Boot中实现防抖动,并提供代码示例。通过使用ScheduledExecutorService,可轻松实现延迟执行功能,确保仅在用户停止输入后才触发操作,大幅减少服务器负载。此外,还可利用`@Async`注解简化异步处理逻辑。防抖动是优化应用性能的关键策略,有助于打造高效稳定的软件系统。
70 2
|
3月前
|
SQL Java 数据库连接
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
这篇文章介绍了在Spring Boot + MyBatis + Shiro项目中,如何使用Shiro框架实现登录用户的权限验证,包括用户、角色和权限表的设计,以及通过多个表查询来收集和验证用户权限的方法和代码实现。
springboot+mybatis+shiro项目中使用shiro实现登录用户的权限验证。权限表、角色表、用户表。从不同的表中收集用户的权限、
|
3月前
|
SQL 前端开发 Java
springboot项目中使用shiro实现用户登录以及权限的验证
这篇文章详细介绍了如何在Spring Boot项目中集成Apache Shiro框架来实现用户登录和权限验证,包括项目依赖配置、数据库连接、实体类定义、控制器、服务层、Mapper层以及前端页面的实现,并展示了实际效果和过滤器代码。
springboot项目中使用shiro实现用户登录以及权限的验证
下一篇
无影云桌面