java—如何在spring的一个constraintvalidator中同时验证@pathvariable和@requestbody?

mspsb9vt  于 2021-07-26  发布在  Java
关注(0)|答案(4)|浏览(491)

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

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

内部 UserRequestDto 对象我有一个 email 现场。
我想确认 email 值尚未使用。
这不是一个问题的创建,因为我只需要检查,如果电子邮件不在数据库中。我创建了一个简单的constraintvalidator,一切都正常。
但是对于更新,我需要检查更新的电子邮件地址是否未被其他人使用,并忽略当前更新的用户。所以我两个都要动手术 userId 以及 updateRequest 马上。是否可以创建自定义constraintvalidator来处理这种情况?

8ftvxx2r

8ftvxx2r1#

因为你从一个 @RestController ,我假设我们讨论的是控制器级别的验证。我可以分享一些看法:
1) 请注意,您正在尝试将业务逻辑相关的验证放到 ConstraintValidator . 在您的例子中,它验证来自数据传输对象的字段(即。 UserRequestDto )保存请求属性的。在控制器级别,我们应该只验证请求本身(即“是否提供了所有必要的信息,以便我可以真正开始执行操作?”)。
2) 因为对“有效”的理解很可能因业务用例的不同而不同,所以与业务逻辑相关的验证应该进入一个新的阶段 @Service bean,其中可以执行特定于用例的验证(例如“是否有其他用户具有相同的用户名或电子邮件?”)。大多数情况下,这是通过手动检查不同的条件来完成的,例如执行数据库查询或咨询其他应用程序。在这个层次上 ConstraintValidator 这样做会适得其反。
3) ConstraintValidator 大部分时间是用来执行语法验证的(例如,“所有必需的值是否都以预期的格式出现?”),而不是用于语义验证的(例如,“根据我的业务逻辑,信息是否正确(可能涉及数据库查询和咨询其他应用程序)”)。
所以在你的情况下,验证你的 UserRequestDto 使用自定义 ConstraintValidator 如果您需要检查客户机是否以特定格式传递了所有必需的属性,那么这是绝对正确的。但是,检查用户名/电子邮件是否已经被另一个用户使用,应该由逻辑层以特定于用例的方式执行-在一个应用程序之外 ConstraintValidator .

yjghlzjz

yjghlzjz2#

我可以想到两种方法:
方法1:
在数据库架构中对电子邮件id设置唯一约束。如果尝试保存/更新已使用的电子邮件id,将引发约束冲突异常。
方法2:
在研究上述主题时,我发现了这个链接。你可以参考一下,看看你的需要是否足够。

x4shl7ld

x4shl7ld3#

也许可以使用类级约束:
最后但并非最不重要的一点是,还可以在类级别上放置约束。在这种情况下,验证的对象不是单个属性,而是整个对象。如果验证依赖于对象的多个属性之间的关联,则类级约束非常有用。
您可以从中访问更多详细信息https://docs.jboss.org/hibernate/stable/validator/reference/en-us/html_single/?v=6.1#validator-使用验证程序类级别

lg40wkob

lg40wkob4#

您可以使用spring的 @Validated 然后 @NotBlank @PathVariable String something 也可以。
spring将在您的所有方法周围创建一个aop代理,并在每个参数上查找jsr303注解,但它不会触及 @RequestBody ,所以对于身体,你还是要加上 @Valid 将采用标准方法进行检验。
另外,请参见本期https://github.com/spring-projects/spring-framework/issues/26219

相关问题