3

我正在使用HibernateValidator 4.3.1。驗證在整個應用程序中按照預期執行。使用Spring 3.2.0驗證

我已經註冊了一些自定義的編輯器來執行驗證全球範圍內,如在文本字段確保數值(doubleint等),以確保有關Joda-Time API等

在這種類型的有效日期驗證,通過像往常一樣將allowEmpty參數設置爲false來允許空值/空值,以分別對其進行驗證,尤其是當這些字段留空時顯示單獨的用戶友好錯誤消息。

因此,除了使用HibernateValidator和自定義編輯器進行驗證外,我還嘗試使用以下驗證策略。再次,這種驗證僅適用於那些註冊定製編輯器的字段留空時

以下是實現org.springframework.validation.Validator接口的類。

package test; 

import org.springframework.stereotype.Component; 
import org.springframework.validation.Errors; 
import org.springframework.validation.ValidationUtils; 
import org.springframework.validation.Validator; 
import validatorbeans.TempBean; 

@Component 
public final class TempValidator implements Validator { 

    @Override 
    public boolean supports(Class<?> clazz) { 
     System.out.println("supports() invoked."); 
     return TempBean.class.isAssignableFrom(clazz); 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     TempBean tempBean = (TempBean) target; 

     System.out.println("startDate = " + tempBean.getStartDate() + " validate() invoked."); 
     System.out.println("doubleValue = " + tempBean.getDoubleValue() + " validate() invoked."); 
     System.out.println("stringValue = " + tempBean.getStringValue() + " validate() invoked."); 

     ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startDate", "java.util.date.nullOrEmpty.error"); 
     ValidationUtils.rejectIfEmptyOrWhitespace(errors, "doubleValue", "java.lang.double.nullOrEmpty.error"); 
    } 
} 

類與@Component註釋指定,​​以便它可以自動連接到特定的春天控制器類。調試語句完全基於用戶提供的輸入顯示。

以下是控制器類。

package controller; 

import customizeValidation.CustomizeValidation; 
import java.util.Map; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.validation.Valid; 
import javax.validation.groups.Default; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.validation.BindingResult; 
import org.springframework.validation.DataBinder; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import test.TempValidator; 
import validatorbeans.TempBean; 

@Controller 
public final class TempController { 

    @Autowired 
    private TempService tempService; 

    private TempValidator tempValidator; 

    public TempValidator getTempValidator() { 
     return tempValidator; 
    } 

    @Autowired 
    public void setTempValidator(TempValidator tempValidator) { 
     this.tempValidator = tempValidator; 
    } 

    @RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"}) 
    public String showForm(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { 
     return "admin_side/Temp"; 
    } 

    @RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"}) 
    public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) { 
     //tempValidator.supports(TempBean.class); 
     //tempValidator.validate(tempBean, errors); 

     DataBinder dataBinder = new DataBinder(tempBean); 
     dataBinder.setValidator(tempValidator); 
     dataBinder.validate(); 

     //errors=dataBinder.getBindingResult(); 
     if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) { 
      System.out.println("Validated"); 
     } 

     return "admin_side/Temp"; 
    } 
} 

我被

DataBinder dataBinder = new DataBinder(tempBean); 
dataBinder.setValidator(tempValidator); 
dataBinder.validate(); 

調用從Spring控制器類本身(這是我確實想)驗證的驗證器調用,但預計該驗證執行。

如果我調用驗證器使用下面的語句(這在上面已經說明輸出)手動,

tempValidator.validate(tempBean, errors); 

然後執行驗證。所以我不相信我的驗證器是正確工作的。爲什麼它不能與DataBinder一起使用?

在我的application-context.xml文件中,該bean的配置如下。

<bean id="tempValidator" class="test.TempValidator"/> 

這許多包如以下包括test包其中TempValidator類內封入是自動檢測。

<context:component-scan base-package="controller spring.databinder validatorbeans validatorcommands test" use-default-filters="false"> 
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> 
    <context:include-filter expression="org.springframework.web.bind.annotation.ControllerAdvice" type="annotation"/> 
</context:component-scan> 

我甚至試圖把

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 

在我dispatcher-servlet.xml文件。

我在這裏忽略了什麼?

+0

如果你在行「dataBinder.validate();」並進入它,你能看到哪個驗證器最終被調用? – CodeChimp 2013-02-20 12:20:27

+0

@CodeChimp - 調用的驗證器是question -'tempValidator中指定的驗證器。 – Tiny 2013-02-21 18:30:50

回答

4

如果我沒有理解好你試圖達到什麼 - 空字段並輸入不正確的值之間的區別 - 你可以使用更多更簡單的方法:

public class MyBean { 

    @NotNull 
    @DateTimeFormat(pattern="dd.MM.yyyy HH:mm") 
    private DateTime date; 

    @NotNull 
    @Max(value=5) 
    private Integer max; 

    @NotNull 
    @Size(max=20) 
    private String name; 

    // getters, setters ... 
} 

控制器映射:

public void submitForm(@ModelAttribute @Valid MyBean myBean, BindingResult result) { 

    if (result.hasErrors){ 
     // do something} 
    else{ 
     // do something else 
    }   
} 

驗證消息:

NotNull=Required field. 
NotNull.date=Date is required field. 
NotNull.max=Max is required field. 
Size=Must be between {2} and {1} letters. 
Max=Must be lower than {1}. 
typeMismatch.java.lang.Integer=Must be number. 
typeMismatch.org.joda.time.DateTime=Required format dd.mm.yyyy HH:mm 

Spring配置:

@Configuration 
public class BaseValidatorConfig { 

    @Bean 
    public LocalValidatorFactoryBean getValidator() { 

     LocalValidatorFactoryBean lvfb = new LocalValidatorFactoryBean(); 
     lvfb.setValidationMessageSource(getValidationMessageSource()); 
     return lvfb; 
    } 

    protected MessageSource getValidationMessageSource() {// return you validation messages ...} 
} 

如果需要,我可以提供更多的細節和解釋。

+0

啊!我從來沒有使用過這個'LocalValidatorFactoryBean'。諸如'@ NotEmpty','@ NotBlank','@NotNull'等註解可以自己工作(在我目前使用的Spring 3.2.2中)。這是什麼'LocalValidatorFactoryBean'?更重要的是,'@ Configuration'比XML配置更好嗎?謝謝。 – Tiny 2013-06-13 19:30:08

+2

'LocalValidatorFactoryBean'在Spring MVC驗證器和JSR-303 Bean驗證實現之間提供了一個橋樑 - 它使您能夠在控制器方法中使用'@ Valid'註釋,該方法提供了綁定到綁定結果的開箱驗證錯誤在示例代碼中),並以Spring的方式使用驗證消息(錯誤代碼消息解析器)。 '@ Configuration'提供了更多的靈活性,並且不易出錯,但是您可以在java和XML配置中實現相同的功能。 – 2013-06-16 07:06:09

0

我不知道爲什麼問題中提到的方法不起作用。我沒有做到這一點,但走過這個document,我發現另一種方法,根據我的要求爲我工作。

我在@InitBinder註釋中指定的方法內設置驗證器。

docs

確認者例如當一個@Valid方法參數是遇到可以以兩種方式配置 調用。首先,您可以在@ Controller的@InitBinder 回調中調用 binder.setValidator(Validator)。這可以讓你每 配置驗證實例@Controller類:

具體而言,在我的要求,只應執行的驗證,同時更新或插入數據到數據庫即當相關的這些行動是提交按鈕(在我的應用程序中名稱爲btnSubmit)的這兩項任務(插入和更新)都有一個通用按鈕。

在任何其他情況下(例如,當按下刪除按鈕時),應驗證該靜音。爲了滿足這個要求,我已經註冊驗證器如下。

@InitBinder 
protected void initBinder(WebDataBinder binder, WebRequest webRequest) { 
    if (webRequest.getParameter("btnSubmit") != null) { 
     binder.setValidator(new TempValidator()); 
    } else { 
     binder.setValidator(null); 
    } 
} 

在這種情況下,驗證 - TempValidator將只設置時提交按鈕的名字屬性btnSubmit由客戶端點擊。

無需任何地方配置xml配置以及自動佈線。

示例性控制器類現在看起來如下所示。

@Controller 
public final class TempController { 

    @Autowired 
    private TempService tempService; 

    @InitBinder 
    protected void initBinder(WebDataBinder binder, WebRequest webRequest) { 
     if (webRequest.getParameter("btnSubmit") != null) { 
      binder.setValidator(new TempValidator()); 
     } else { 
      binder.setValidator(null); 
     } 
    } 

    //Removed the @Valid annotation before TempBean, since validation is unnecessary on page load. 
    @RequestMapping(method = {RequestMethod.GET}, value = {"admin_side/Temp"}) 
    public String showForm(@ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) { 
     return "admin_side/Temp"; 
    } 

    @RequestMapping(method = {RequestMethod.POST}, value = {"admin_side/Temp"}) 
    public String onSubmit(@ModelAttribute("tempBean") @Valid TempBean tempBean, BindingResult errors, Map model, HttpServletRequest request, HttpServletResponse response) { 
     if (CustomizeValidation.isValid(errors, tempBean, TempBean.ValidationGroup.class, Default.class) && !errors.hasErrors()) { 
      System.out.println("Validated"); 
     } 
     return "admin_side/Temp"; 
    } 
} 

WebRequest paramenter在initBinder()方法並不意味着用於處理整個Http請求那樣明顯。這只是使用通用請求元數據。

Javadocs約WebRequest

Web請求的通用接口。主要用於通用網絡 請求攔截器,使它們可以訪問一般請求元數據 而不是實際處理請求。

如果有什麼不對,我可能會跟隨,那麼請善加澄清或添加其他答案。