2017-03-13 26 views
1

新的Spring開發人員在這裏。我已經搜索了SO和春季文檔,但無法弄清楚這一點。Spring驗證 - 避免重複約束消息

我試圖使用Spring驗證通過構造函數任何適用Validator實現適用於任意對象注入所有註冊的驗證,並通過他們呼籲迭代和supports()然後有條件validate()。這是有效的,除非它產生重複的驗證消息,因爲JSR-303約束註釋經過兩次驗證 - 一次爲jsr303Validator,再次爲mvcValidator

我試過調用所有驗證器,然後刪除重複的錯誤,但ObjectError上的equals()實現不能按需要工作(它會使條目具有相同的錯誤代碼和消息)。

驗證程序實行:

import org.springframework.validation.BindException; 
import org.springframework.validation.Validator; 

@Service 
class ObjectValidatorImpl { 
    private final Validator[] validators; 

    public ObjectValidatorImpl(Validator[] validators) { 
     this.validators = validators; 
    } 

    public void validate(Object obj) throws BindException { 
     // Container for holding any validation errors that are found 
     BindException errors = new BindException(obj, obj.getClass().getName()); 

     for (Validator validator : validators) { 
      if (validator.supports(obj.getClass())) { 
       validator.validate(obj, errors); 
      } 
     } 

     if (errors.hasErrors()) { 
      throw errors; 
     } 
    } 
} 

實施例程序表示錯誤:

@SpringBootApplication 
public class ValidationTestApplication implements CommandLineRunner { 

    @Autowired 
    private ObjectValidator objectValidator; 

    public static void main(String[] args) { 
     SpringApplication.run(ValidationTestApplication.class, args); 
    } 

    @Override 
    public void run(String... args) throws Exception { 
     try { 
      objectValidator.validate(new TestObject()); 
     } 
     catch (BindException ex) { 
      System.out.println(ex); 
     } 
    } 
} 

class TestObject { 
    @NotEmpty 
    String name; 
} 

實施例誤差輸出:

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors 
Field error in object 'validationtest.TestObject' on field 'name': rejected value [null]; codes [NotEmpty.validationtest.TestObject.name,NotEmpty.name,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validationtest.TestObject.name,name]; arguments []; default message [name]]; default message [may not be empty] 
Field error in object 'validationtest.TestObject' on field 'name': rejected value [null]; codes [NotEmpty.validationtest.TestObject.name,NotEmpty.name,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [validationtest.TestObject.name,name]; arguments []; default message [name]]; default message [may not be empty] 

注意 '名稱不能爲空' 報告兩次錯誤,通過jsr303ValidatormvcValidator

搖籃依賴性:

dependencies { 
    compile('org.springframework.boot:spring-boot-starter-data-jpa') 
    compile('org.springframework.boot:spring-boot-starter-validation') 
    compile('org.springframework.boot:spring-boot-starter-web') 
    runtime("com.h2database:h2") 
} 

什麼是正確的(最有彈性的?)的方式來解決這種情況?感覺這是一個類路徑配置問題,我應該避免在同一個項目中同時擁有兩個驗證器,但是這個代碼位於共享庫中,可能會或可能不會與Spring Web MVC一起使用,而且我不知道如何防止這種情況。

+0

一些代碼將有助於理解您的問題 – Jaiwo99

回答

0

難道這不該發生什麼?

您有多個驗證程序註冊了該對象,因此當您遍歷所有對象時,請求驗證消息時,您將得到重複項,因爲它們都相似。

+0

這可能是應該發生的事情,但這不是我想要發生的事情。這個問題可以重新表述爲:如何避免在使用Spring Web時註冊多個JSR303驗證器?我沒有明確註冊驗證器,所以我不確定爲什麼有兩個JSR303驗證器或如何避免這種情況。 – Eric

+0

這很公平。你是否自動連線這些驗證器?他們有不同的目的。我相信mvc會允許將表單綁定到消息上。你可以放棄其中一個驗證器,但他們可能在將來做不同的事情(如果有人添加了一個自定義的)。 – TheNorthWes

+0

我沒有明確自動裝配驗證器。我想只包括'org.springframework.boot:spring-boot-starter-web'註冊MVC驗證器。我想避免使用硬編碼邏輯來排除MVC驗證器(例如按類名稱),因爲您指出這看起來很脆弱。我正在尋找一種方法來控制注入或至少運行 - 基本上我需要標準的JSR303驗證器('LocalValidatorFactoryBean')和任何特定於應用程序的自定義驗證器。我只是不確定如何過濾注入的驗證器列表(或選擇更好的方法)。 – Eric