驗證邏輯(以及我的第一篇帖子!)

工程 | Colin Yates | 2006 年 8 月 25 日 | ...

大家好!

這是我上個月加入 Interface21 以來的第一篇帖子。我之前的部落格現在已正式棄用,我不會再更新它了。

那麼我第一篇帖子的主題是什麼(除了自我介紹)?驗證邏輯。 這不是如何在 Spring 框架中執行驗證的演練,而是討論我特別討厭的事情:)

特別地,我想討論驗證邏輯中應該包含什麼。這似乎是一個無需動腦筋的答案:“驗證指定資料的邏輯”。好的,這確實是無需動腦筋的,但請繼續閱讀:)。如您所知,Spring 框架透過 ErrorsValidator 介面為您的驗證提供了一個很好的抽象層。 特別是 Validator 是您將業務特定的驗證規則應用於填充的域物件的地方。 Spring 優秀的繫結支援負責基於某些輸入更新您的域模型,validator 負責確保填充的域模型在語義上是正確的。那麼我討厭的是什麼? 一次又一次,我不斷遇到允許驗證邏輯從 validator 中滲出到控制器(對於 Web 應用程式)的應用程式,甚至更糟的是滲出到中間層。 在人們開始提出異議之前:我不是說驗證不屬於中間層,我是說 Validator 是放置驗證邏輯的地方!

最常見的例子是當您新增新實體時,例如 User。 通常,validator 將執行許多“簡單”檢查(欄位不能為空,文字欄位的長度超過 25 個字元等)。 然後,控制器(例如)將呼叫中間層 (userService.add(user)) 並捕獲 DuplicateKeyException(或強型別的 DuplicateUserException)異常。 如果丟擲此異常,則控制器將填充 errors 物件,然後重新顯示錶單。

那麼這張圖有什麼問題呢? 簡單的事實是,某些驗證現在隱式地透過引發 DuplicateKeyException 來完成,表明驗證失敗! 在插入資料之前,資料庫(在本例中)正在驗證資料以確保其唯一,如果不是,則丟擲異常。

我的觀點(我承認我說的非常冗長;))是,這都是驗證邏輯,應該放在 Validator 中。 將此唯一性檢查移至 validator 它所屬的地方(!)可以帶來許多好處

  • 這是一個更簡潔、更直觀的實現; 在哪裡查詢驗證邏輯? 在 validator 中。
  • 現在 validator 實現是真正可重用的。 以前,validator 實際上只驗證了一部分資料。
  • 唯一使用者的單元測試在驗證單元測試中完成。 這比單元測試控制器容易得多,單元測試控制器需要模擬 Errors、HttpServletRequest、HttpServletResponse(實際上這很容易,但仍然......)。 測試 validator 需要模擬的物件數量是 Errors 物件、DAO 和您的域模型。
  • Controller 中的 onSubmit 方法現在遵循 SimpleFormController 指定的約定(表明僅在驗證成功時才呼叫),因此程式碼更加簡潔。
這不是火箭科學,但很多人就是不“理解”。 我認為這可能是因為他們將 validator 視為驗證請求引數是否正確的地方。 當然,您可以在域模型本身上執行此操作,但這仍然是他們的心態。 不是的。 它是關於應用所有您的業務驗證規則。

注意:有一種論點是您正在重複您的驗證邏輯; 資料庫知道什麼是唯一的,什麼不是唯一的,那麼為什麼在控制器中重複該邏輯? 好吧,關鍵是您正在重複該邏輯,您正在使用引發 DuplicateXXXException 來指示驗證失敗,因此這並不是一個有效的論點。

還有另一種論點是,這不能 100% 保證捕獲所有(在本例中)重複的鍵。 這是真的。 在呼叫驗證之後但在中間層呼叫之前,有一個很小的機會視窗,另一個程序可能會偷偷地建立唯一的行,但這只是一個非常非常小的視窗(通常是毫秒),並且無論如何都可能會丟擲 OptimisticLockingException。 還要考慮資料的性質。 兩個不同的執行緒同時建立一個唯一的實體是不太可能的。 如果確實發生了,那也沒關係。 讓異常傳遞到容器,因為它現在確實是異常情況。

咆哮結束。

附言。我的其餘部落格文章可能同樣冗長:)

獲取 Spring 新聞郵件

透過 Spring 新聞郵件保持聯絡

訂閱

取得領先

VMware 提供培訓和認證,以加速您的進步。

瞭解更多

獲得支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群中所有即將舉行的活動。

檢視全部