领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多大家好!
这是我上个月加入 Interface21 后的第一篇博文。我之前的博客现在正式弃用,我不会再更新它了。
那么,我的第一篇博文主题是什么(除了自我介绍)?验证逻辑。它不会逐步介绍如何在 Spring 框架中执行验证,而是会讨论我个人特别讨厌的一个问题 :)
特别是,我想讨论一下验证逻辑中应该包含什么。这似乎是一个显而易见的问题;“验证指定数据的逻辑”。好的,这是显而易见的,但请继续阅读:)。如您所知,Spring 框架通过Errors和Validator接口为您提供了验证的良好抽象层。特别是 Validator 是您将特定于业务的验证规则应用于已填充的域对象的地方。Spring 优秀的绑定支持负责根据某些输入更新您的域模型,Validator 负责确保已填充的域模型在语义上是正确的。那么我的烦恼是什么呢?我一次又一次地遇到允许验证逻辑从验证器泄漏到控制器(对于 Web 应用程序)甚至更糟糕地泄漏到中间层的应用程序。在人们开始提出异议之前;我并不是说验证不属于中间层,而是说 Validator 是放置验证逻辑的地方!
最常见的示例是添加新实体(例如用户)。通常,验证器会执行一些“简单”检查(字段不为空、文本字段长度超过 25 个字符等)。然后,控制器(例如)将调用中间层 (userService.add(user)) 并捕获 DuplicateKeyException(或强类型 DuplicateUserException)异常。如果引发此异常,则控制器将填充错误对象,然后重新显示表单。
那么这张图有什么问题呢?简而言之,某些验证现在隐式地通过引发 DuplicateKeyException 来指示验证失败!。数据库(在此示例中)会在插入数据之前验证数据以确保其唯一性,如果数据不唯一,则会引发异常。
我的观点(我承认我在表达时非常冗长;))是,这都是属于 Validator 的验证逻辑。将此唯一性检查移到 Validator 中它应该在的地方(!)可以带来许多好处
注意:有人认为您正在重复验证逻辑;数据库知道什么内容是唯一的,什么内容不是唯一的,所以为什么要在控制器中重复该逻辑呢?好吧,关键是您确实在重复该逻辑,您正在使用引发 DuplicateXXXException 来指示验证失败,因此这实际上不是一个有效的论点。
还有一个论点认为这不能保证捕获所有(在这种情况下)重复键。这是真的。在调用验证后但在进行中间层调用之前,存在一个小窗口,在此窗口中,另一个进程可能会偷偷溜进来并创建唯一的行,但这是一个非常非常小的窗口(通常为毫秒),并且可能仍会引发 OptimisticLockingException。还要考虑数据的性质。两个不同的线程同时创建单个唯一实体的可能性极低。如果确实发生了,没关系。让异常传递到容器,因为它现在确实是一个异常情况。
抱怨结束。
附注:我的其他博文可能也同样冗长 :)