先來看我覺得不好用的 JSR-303 Validator。
在 Spring MVC 裡設定 JSR-303 Validator
第一、要有 JSR-303 實做(Provider),目前知道是 Hibernate Validator,Maven 定義如下:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>4.2.0.Final</version> </dependency>會帶入 JSR-303 定義 validation-api-1.0.0.GA.jar 與實做 hibernate-validator-4.2.0.Final.jar。
第二、在 Spring 裡加入以下定義:
<mvc:annotation-driven />第三、在 classpath 裡加入 ValidationMessages.properties 以提供錯誤訊息,如果沒有提供,則會使用 Hibernate Validator 預設的訊息檔,可以在 hibernate-validator-4.2.0.Final.jar/org/hibernate/validator 裡找到,建議拿來修改成自己的訊息檔,因為可以知道有哪些 key 值要提供。
再來只要在 @Controller 裡遇到 @Valid,就會進行 JSR-303 的驗證。
Controller
@RequestMapping(method = RequestMethod.POST)
public String sync(@Valid @ModelAttribute("cmd") Product cmd, BindingResult result) {
if (result.hasErrors()) {
return "productForm";
}
if (cmd.getId() == null) {
this.productService.addProduct(cmd);
}
else {
this.productService.updateProduct(cmd);
}
return "redirect:/product/list.do";
}
Model @Entity @SuppressWarnings("serial") public class Product { @NotNull private String key; @Size(min = 10, max = 100) private String description; ... }再來看 Spring Validator。
在 Spring MVC 裡設定 Spring Validator
第一、在 @InitBinder 裡設定 Validator。
Controller
@InitBinder("cmd") public void initBinder(WebDataBinder binder) { binder.setValidator(new ProductValidator()); }ProductValidator
public class ProductValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return Product.class.equals(clazz); } @Override public void validate(Object target, Errors errors) { Product cmd = (Product) target; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "key", "key.empty"); // ... } }第二、先在 Spring 裡設定 MessageSource,再於 classpath 裡加入 validation.properties 以提供錯誤訊息。
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>validation</value> </list> </property> </bean>再來只要在 @Controller 裡遇到 @Valid,就會進行 Spring Validator 的驗證,特別注意,不是 binder.setValidator(...) 就會進行驗證,還必須加上 @Valid 才行。
JSR-303 與 Spring Validator 無法同時並存?
有趣的一點是,Spring Validator 與 JSR-303 都得加上 @Valid,除此之外的步驟並不一樣,所以當兩種驗證方式都設定時,會發生什麼事?兩個驗證都會執行嗎?經過演練發現,只要呼叫了 binder.setValidator(...) 就會切換成 Spring Validator 模式,不然就是 JSR-303 模式。
那可以兩種模式都用嗎?以下只是無聊的舉動。
在 @Controller 使用 JSR-303 模式,然後在 Post request 裡手動呼叫 Spring Validator 就可以了,這也是 Spring 強調 Spring Validator 不是專供 Spring MVC 使用,在一般的 Spring 程式裡就可以使用 Spring Validator。
@RequestMapping(method = RequestMethod.POST)
public String sync(@Valid @ModelAttribute("cmd") Product cmd, BindingResult result) {
new ProductValidator().validate(cmd, result);
if (result.hasErrors()) {
return "productForm";
}
if (cmd.getId() == null) {
this.productService.addProduct(cmd);
}
else {
this.productService.updateProduct(cmd);
}
return "redirect:/product/list.do";
}
最後來解釋我為什麼覺得 JSR-303 難用:第一、JSR-303 提供的驗證方式不多。
第二、可能是我沒有深入研究 JSR-303,我不知道怎麼作多欄位驗證或者需要資料庫查詢的唯一值驗證。
相關文章
沒有留言:
張貼留言