2009-06-25 58 views
6

我不確定是否根據數據庫的狀態使驗證程序驗證命令是一個很好的設計決策。例如,如果我需要驗證一個用戶bean,除了檢查電子郵件和用戶名是否爲空等我還需要拒絕值,如果他們已經被使用。這種邏輯是否應該進入驗證者或服務對象?Spring中的驗證器應該訪問數據庫嗎?

回答

10

那麼你的驗證器只是spring bean,所以它們可以注入處理數據訪問的服務對象。您可以讓驗證器從數據庫中獲取數據,而不會影響設計。

2

不,恕我直言驗證器應該很小,side-effect free爲了讓他們很容易組合。明確地說,驗證者應該與持久層分開

+0

當你想檢查一個引用是指一個真實的實體時,你會怎麼做?他們不應該更改數據,但有時您至少需要進行身份驗證。 – 2009-06-25 20:07:15

1

我檢查了我的一個,我從驗證調用服務層:

@Service 
public final class StartFormValidator { 
private FacilityService facilityService; 
private AdminService adminService; 

/** 
* Verify that they've selected a facility. Verify that they've selected a 
* valid facility. Verify that they've selected a view and that it's a valid 
* view. 
* 
* @param startForm 
* @param errors 
* @return true if no errors were set 
*/ 
public boolean isValid(final StartForm startForm, final Errors errors) { 
    if (startForm.getFacilityId() == 0) { 
     errors.rejectValue("facilityId", "facilityIdEmpty", 
       "Select a facility."); 
    } 

    if (!this.facilityService.isFacilWaitlistEnabled(startForm 
      .getFacilityId())) { 
     errors.rejectValue("facilityId", "facilityInvalid", 
       "Invalid facility"); 
    } 

    if (StringUtils.isBlank(startForm.getPassword())) { 
     errors.rejectValue("password", "passwordEmpty", 
       "Enter the password."); 

     return (false); 
    } 

    if (!this.adminService.validateAdmin(startForm.getPassword())) 
     errors.rejectValue("password", "passwordInvalid", 
       "Incorrect password"); 

    return (!errors.hasErrors()); 
} 

/** 
* @param _facilityService 
*/ 
@Autowired 
public void setFacilityService(final FacilityService _facilityService) { 
    this.facilityService = _facilityService; 
} 

/** 
* @param _adminService 
*/ 
@Autowired 
public void setAdminService(final AdminService _adminService) { 
    this.adminService = _adminService; 
} 

}

6

這將在很大程度上取決於你如何定義驗證。考慮一下:你在買東西,然後你輸入你的信用卡號碼。如果校驗位不匹配,則驗證失敗。沒有嘗試過任何交易。但是,如果它是一個有效的信用卡號碼,但它與您的郵政編碼不相符(需要DB /第三方交互),那麼這是一個付款錯誤。

現在考慮一下:你輸入你的地址,然後你輸入Mastiffica作爲你的國家。爲什麼系統甚至允許你輸入 - 它們應該只將接口限制爲有效輸入(不需要輸入數據庫)。

或者您在銀行付款屏幕的金額字段中輸入「五十」。爲什麼它允許那裏的字母 - 驗證失敗(不需要DB)。但是,您在金額字段中輸入50,結果表明您的帳戶中沒有50英鎊。這是一個驗證錯誤?或者它是一個失敗的交易?

現在,考慮到您已通過所有基本入境驗證(信用卡校驗碼,國家,數字,郵政編碼),並且交易失敗,因爲您的信用卡已過期。是驗證錯誤還是失敗的事務?

您可以將驗證視爲用戶不會輸入完全自然數據的基本保證,也可以將驗證視爲「我可以使用所提供的數據完成此交易」。我個人會喜歡前者,但同樣,這是定義的問題。

再就是作爲一種安全措施,第一線的驗證的方面 - 已接受了過去的頂部UI層可以是安全風險(SQL注入,例如)

1

如果你真的相信「MVC野外數據「那麼我不這麼認爲,你會希望你的驗證器去數據庫。驗證是一個從業務邏輯的角度來驗證數據的階段。

數據庫不需要知道驗證器將如何使用它,驗證器也不應該知道數據庫是什麼樣的。這只是不適合MVC模型。明天,如果您有來自多個來源的數據,您是否仍會繼續並告訴驗證者,哪些來源具體應該在哪些條件下訪問。這本身將構成甚至不需要的邏輯。在應用中。

您正在尋找的驗證類型將被視爲業務對象的一部分,這將確保在調用服務對象之前;這種組合並不存在。

服務對象也不應包含業務驗證,因此它既不屬於驗證者也不屬於服務對象。但是,是的,如果應用程序足夠小以至於不用擔心太多的圖層,傾斜的方法就沒有問題,但只要「貫穿始終遵循標準」即可。

總之,我覺得spring驗證器是用於基本驗證而不是真正的業務驗證。

0

我贊成使用數據庫的驗證,因爲最終用戶的可用性。

在提交註冊表單時,您要檢查用戶名是否在語法上正確,並且該用戶名尚未提供(需要數據庫訪問權限)。

表單可以一次返回所有錯誤。它可以向用戶顯示所有問題。用戶可以修復它並再次發送表單。

我知道你可以用ajax等做得更聰明,這不是重點。

我總是檢查一切。我檢查這個表單是否將由即將到來的交易處理。如果沒有,我會因爲一些可以輕鬆處理的併發訪問而發生異常。