首页 > 解决方案 > 如何在 Spring 的一个 ConstraintValidator 中同时验证 @PathVariable 和 @RequestBody?

问题描述

我在控制器中有一个端点处理程序方法:

@PutMapping("/users/{userId}")
public UserDto updateUser(@PathVariable UUID userId, @RequestBody UserRequestDto updateRequest) {
  ...
}

UserRequestDto对象内部,我有一个email字段。

我想验证该email值是否尚未使用。

创建不是问题,因为我只需要检查电子邮件是否不在数据库中。我创建了一个简单的 ConstraintValidator 并且一切正常。

但是对于更新,我需要检查更新的电子邮件地址是否未被其他人使用并省略当前更新的用户。所以我需要同时对两者进行userId操作updateRequest。创建自定义 ConstraintValidator 来处理这种情况是否可行?

标签: javaspringvalidationbean-validation

解决方案


由于您从 a 发布了代码@RestController,我假设我们正在讨论控制器级别的验证。我可以分享一些观察:

1)请注意,您正在尝试将与业务逻辑相关的验证放入ConstraintValidator. 在您的情况下,它正在验证来自保存请求属性的数据传输对象(即)的字段。UserRequestDto在控制器级别,我们应该只验证请求本身(即“是否提供了所有必要的信息,以便我可以实际开始执行操作?”)。

2)因为对“有效”的理解很可能因业务用例而异,业务逻辑相关的验证应该进入一个@Service可以执行特定于用例的验证的 bean(例如“是否有任何其他用户具有相同的用户名或电子邮件?”)。大多数情况下,这是通过手动检查不同的条件来完成的,例如执行数据库查询或咨询其他应用程序。在这个级别上ConstraintValidator,s 会适得其反。

3) ConstraintValidators 大部分时间用于执行语法验证(即“所有必要的值都以预期的格式存在吗?”)但用于语义验证的时间不多(即“根据我的业务逻辑,信息是否正确(这可能涉及数据库查询和咨询其他应用程序)?”)。

因此,在您的情况下,如果您需要检查客户端是否以特定格式传递了所有必需的属性,则使用自定义验证您的UserRequestDto对象 绝对没问题。ConstraintValidator但是,检查用户名/电子邮件是否已被另一个用户使用应该由逻辑层以特定于用例的方式执行 - 在ConstraintValidator.


推荐阅读