如果我有一個Web應用程序,比如說我正在使用Spring MVC,並且我在表單和控制器中添加了驗證。如果客戶以其他方式訪問我的應用程序(通過REST服務等),我可能還會在服務層進行驗證。在這種情況下,我可能會在多個地方有驗證邏輯/代碼。如何避免Web層和服務層中的重複驗證?
是否有建議的方法來保持驗證部分幹?
如果我有一個Web應用程序,比如說我正在使用Spring MVC,並且我在表單和控制器中添加了驗證。如果客戶以其他方式訪問我的應用程序(通過REST服務等),我可能還會在服務層進行驗證。在這種情況下,我可能會在多個地方有驗證邏輯/代碼。如何避免Web層和服務層中的重複驗證?
是否有建議的方法來保持驗證部分幹?
很多人會告訴你如何做到這一點。我要回答你爲什麼不想要。
在N層系統中,層級都是半自主操作的。但這並不意味着他們可以 - 或者應該 - 依靠另一層來保證數據的一致性和有效性。
有兩個主要原因。首先,N層系統是可擴展的。例如,在網絡系統中,新的前端可能會利用現有的網絡層來完成原始設計中從未想過的事情。所以你的設計證明你的系統允許在層級的某個中間點出現新的東西。
其次,驗證往往是最有效的越接近用戶。如果我在基於瀏覽器的解決方案中,並且在雙輸入驗證字段中輸入了錯誤的密碼,我希望瀏覽器立即指出。等待往返需要時間並使用戶感到沮喪。
現在採取相同的例子,並將其移動到邏輯層。邏輯層,不完全確定誰在發送數據,想要確定它正在接收兩個匹配的密碼。所以它也檢查,並且如果它們不匹配則返回一個錯誤。這可以保護數據免遭不良變化。
這只是一種哲學,但它在過去對我來說效果很好。
這可能是值得看看JSR-303 bean驗證。如果爲不同的接口使用相同的JavaBean,則可以避免重複的驗證邏輯。
Hibernate實現提供了最好的參考文檔:
http://hibernate.org/subprojects/validator
和Spring參考文檔告訴你如何整合它。
Spring使用validator接口是單向的。我不知道你爲什麼不能在服務層中使用它的原因。或者,您可以使用AOP並根據需要在任何層中定義切入點。
首先,業務/功能級驗證應始終在服務層進行。如果你說你正在複製在你的MVC層完成的驗證在服務層複製,聽起來令人擔憂。例如,您可以在視圖上驗證電話號碼格式,信用卡格式等內容。您不得在服務層中複製這些內容。
與此同時,您可能必須重複驗證,例如「空白」檢查,並且從設計的角度來看,這些都是可以的。
我會建議這些是不同種類的驗證。
客戶機/控制器驗證檢查,以確保所需的值都存在,格式服從等
綁定HTTP請求參數爲對象傳遞到服務層是控制器的全部責任。
服務層將執行與客戶端相同的驗證,但也會涉及與用例相關的「業務驗證」。控制器無法知道這些。
避免重複的一種方法是在客戶端和服務器端執行相同的JavaScript函數。服務器端使用JavaScript引擎執行客戶端驗證以及與業務驗證相關的附加服務器驗證。
你說得對,驗證更接近用戶,但通常可以在服務層中使用的域模型中描述驗證約束。例如。服務層返回一個錯誤對象,Web層負責翻譯它,另一個服務層用戶將按照他們需要的方式處理它。 – Daff 2011-01-26 18:23:53