2016-08-17 45 views
2

我試圖使用JSR-303 Bean Validation APISpring's Validator的組合來實現彈簧引導端點的一些自定義驗證邏輯。使用JSR-303和Spring的驗證器的組合實現自定義驗證邏輯

基於驗證類圖上看來是可能延長的CustomValidatorBeanSpringValidatorAdapterLocalValidatorFactoryBean一個添加一些自定義驗證邏輯成重寫方法validate(Object target, Errors errors)

Validator class diagram

但是,如果我創建了一個驗證程序來擴展這三個類中的任何一個,並使用@InitBinder註冊它,那麼將不會調用其validate(Object target, Errors errors)方法,也不會執行驗證。如果我刪除@InitBinder,那麼默認的彈簧驗證器執行JSR-303 Bean Validation

休息控制器:

@RestController 
public class PersonEndpoint { 

    @InitBinder("person") 
    protected void initBinder(WebDataBinder binder) { 
     binder.setValidator(new PersonValidator()); 
    } 

    @RequestMapping(path = "/person", method = RequestMethod.PUT) 
    public ResponseEntity<Person> add(@Valid @RequestBody Person person) { 

     person = personService.save(person); 
     return ResponseEntity.ok().body(person); 
    } 
} 

自定義的驗證:

public class PersonValidator extends CustomValidatorBean { 

    @Override 
    public boolean supports(Class<?> clazz) { 
     return Person.class.isAssignableFrom(clazz); 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     super.validate(target, errors); 
     System.out.println("PersonValidator.validate() target="+ target +" errors="+ errors); 
    } 

} 

如果我的驗證實現org.springframework.validation.Validator那麼它validate(Object target, Errors errors)方法被調用,但JSR-303 Bean Validation是不是在它之前進行。我可以實現類似的方式我的自定義JSR-303的驗證SpringValidatorAdapter實現其JSR-303 Bean Validation但必須有一種方式來代替它擴大:

@Override 
    public void validate(Object target, Errors errors) { 
     if (this.targetValidator != null) { 
      processConstraintViolations(this.targetValidator.validate(target), errors); 
     } 
    } 

我已經看過了使用自定義JSR-303的限制,以避免使用org.springframework.validation.Validator所有的一起,但必須有一種方法來使自定義驗證工作。

春天validation documentation不上結合兩個超清晰:

應用程序也可以爲每個DataBinder的實例註冊附加彈簧驗證實例,如第9.8.3節「配置一個DataBinder的」。這對於插入驗證邏輯而不使用註釋可能很有用。

再後來上倒是上配置多個驗證實例

甲DataBinder的也可以與經由dataBinder.addValidators和dataBinder.replaceValidators多個驗證程序實例進行配置。將全局配置的Bean驗證與在DataBinder實例上本地配置的Spring驗證器相結合時,這非常有用。見???。

我使用的是spring boot 1.4.0。

+0

我不完全確定它很清楚你的實際問題是什麼。此外,如果你分享了一個完整的例子(例如整個代碼)。那麼我們很容易幫助你。 –

+0

您是否閱讀過文檔?在'Validator'中只實現你的自定義邏輯,並使用'addValidators'而不是'setValidator'。這將調用JSR-303(默認配置的驗證器)和您自定義的一個。但是,您可能更好地使用JSR-303驗證程序/約束,而不是使用2種不同的機制。 –

+0

Thanks @ M.Deinum - 使用'addValidators'而不是'setValidator'完成了這個訣竅。我也同意使用JSR-303,專門用於交叉字段驗證的@AssertTrue方法,可能是一個更乾淨的解決方案。代碼示例可在https://github.com/pavelfomin/spring-boot-rest-example/tree/feature/custom-validator中找到。在 的示例中,中間名驗證通過自定義彈簧 驗證程序執行,而姓名驗證由缺省jsr 303 驗證程序處理。 – pavel

回答

3

Per @ M.Deinum - 使用addValidators()代替setValidator()取得了訣竅。我也同意使用JSR-303,專門用於交叉字段驗證的基於方法的@AssertTrue註解,可能是一個更乾淨的解決方案。代碼示例可在https://github.com/pavelfomin/spring-boot-rest-example/tree/feature/custom-validator獲得。在該示例中,中間名驗證通過自定義彈簧驗證器執行,而名稱驗證由缺省的jsr 303驗證器處理。

+0

'@AssertTrue基於方法的專用於交叉字段驗證的註釋,可能是一種更清潔的解決方案'恕我直言,清潔解決方案是編寫自定義JSR-303驗證程序(例如:http://stackoverflow.com/questions/1972933/cross-field -validation與 - 休眠 - 驗證 - JSR-303)。 –