我在控制器中有一个端点处理程序方法:
@PutMapping("/users/{userId}")
public UserDto updateUser(@PathVariable UUID userId, @RequestBody UserRequestDto updateRequest) {
...
}
内部 UserRequestDto
对象我有一个 email
现场。
我想确认 email
值尚未使用。
这不是一个问题的创建,因为我只需要检查,如果电子邮件不在数据库中。我创建了一个简单的constraintvalidator,一切都正常。
但是对于更新,我需要检查更新的电子邮件地址是否未被其他人使用,并忽略当前更新的用户。所以我两个都要动手术 userId
以及 updateRequest
马上。是否可以创建自定义constraintvalidator来处理这种情况?
4条答案
按热度按时间8ftvxx2r1#
因为你从一个
@RestController
,我假设我们讨论的是控制器级别的验证。我可以分享一些看法:1) 请注意,您正在尝试将业务逻辑相关的验证放到
ConstraintValidator
. 在您的例子中,它验证来自数据传输对象的字段(即。UserRequestDto
)保存请求属性的。在控制器级别,我们应该只验证请求本身(即“是否提供了所有必要的信息,以便我可以真正开始执行操作?”)。2) 因为对“有效”的理解很可能因业务用例的不同而不同,所以与业务逻辑相关的验证应该进入一个新的阶段
@Service
bean,其中可以执行特定于用例的验证(例如“是否有其他用户具有相同的用户名或电子邮件?”)。大多数情况下,这是通过手动检查不同的条件来完成的,例如执行数据库查询或咨询其他应用程序。在这个层次上ConstraintValidator
这样做会适得其反。3)
ConstraintValidator
大部分时间是用来执行语法验证的(例如,“所有必需的值是否都以预期的格式出现?”),而不是用于语义验证的(例如,“根据我的业务逻辑,信息是否正确(可能涉及数据库查询和咨询其他应用程序)”)。所以在你的情况下,验证你的
UserRequestDto
使用自定义ConstraintValidator
如果您需要检查客户机是否以特定格式传递了所有必需的属性,那么这是绝对正确的。但是,检查用户名/电子邮件是否已经被另一个用户使用,应该由逻辑层以特定于用例的方式执行-在一个应用程序之外ConstraintValidator
.yjghlzjz2#
我可以想到两种方法:
方法1:
在数据库架构中对电子邮件id设置唯一约束。如果尝试保存/更新已使用的电子邮件id,将引发约束冲突异常。
方法2:
在研究上述主题时,我发现了这个链接。你可以参考一下,看看你的需要是否足够。
x4shl7ld3#
也许可以使用类级约束:
最后但并非最不重要的一点是,还可以在类级别上放置约束。在这种情况下,验证的对象不是单个属性,而是整个对象。如果验证依赖于对象的多个属性之间的关联,则类级约束非常有用。
您可以从中访问更多详细信息https://docs.jboss.org/hibernate/stable/validator/reference/en-us/html_single/?v=6.1#validator-使用验证程序类级别
lg40wkob4#
您可以使用spring的
@Validated
然后@NotBlank @PathVariable String something
也可以。spring将在您的所有方法周围创建一个aop代理,并在每个参数上查找jsr303注解,但它不会触及
@RequestBody
,所以对于身体,你还是要加上@Valid
将采用标准方法进行检验。另外,请参见本期https://github.com/spring-projects/spring-framework/issues/26219