2013-03-14 33 views
3

我正在寫有Bean驗證(JSR-303)是這樣的顯式調用代碼:如何獲取ConstraintValidatorContext?

public class Example { 

    @DecimalMin(value = "0") 
    private static final String ANNOTATED = ""; 

    public void isPossitiveNumber(String str){ 

     ValidatorFactory factory = 
      Validation.buildDefaultValidatorFactory(); 

     ConstraintValidator<DecimalMin, String> 
      validator = 
        factory.getConstraintValidatorFactory().getInstance(
          DecimalMinValidatorForString.class); 


     validator.initialize(
        ReflectionUtils.findField(getClass(), "ANNOTATED") 
         .getAnnotation(
          DecimalMin.class)); 

     boolean isValid = validator.isValid(str, null); 

     return isValid; 


    } 


} 

注行布爾參考isValid = validator.isValid(STR,NULL); 我轉讓nullConstraintValidatorContext,因爲我發現沒有辦法獲得/構造它。在這個特殊的情況下,這個如果沒有問題,因爲在內部沒有使用ConstraintValidatorContext,但它顯然是一個黑客。我應該如何獲得ConstraintValidatorContext

ADDED

我被要求提供使用情況。所以,例如,我寫了自定義驗證器,我想重新使用現有的驗證。或者我在上面描述了寫平面Java代碼,我想重新使用現有的驗證。

+0

您可以在您的用例中添加一些細節嗎?作爲用戶,您通常通過'javax.validation.Validator' API與Bean驗證交互,而不是通過手動創建和調用約束驗證器。 'ConstraintValidatorContext'由引擎在驗證過程中傳遞給驗證器,所以它的實現通常不會暴露給用戶。 – Gunnar 2013-03-14 15:51:08

+0

例如,我正在寫自定義驗證程序,我想重新使用現有的驗證。或者我在上面描述了寫平面Java代碼,我想重新使用現有的驗證。我將在我的文章中添加這個說明。 – alexsmail 2013-03-14 20:12:36

回答

1

簡單的答案是你不能。 ConstraintValidatorContext是一個接口,並沒有Bean驗證API來獲取這樣的實例。你可以編寫你自己的實現,但爲了正確實現它,你必須重新實現Bean驗證提供者的很多功能。在Hibernate Validator特定實現中尋找示例 - https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/constraintvalidation/ConstraintValidatorContextImpl.java

這就是說,我相信您的重用嘗試是錯誤的。這不在Bean Validation的縮進中,並且最終以非便攜式和難以維護的代碼結束。如果要重用現有約束,請查看約束組合,例如@NotEmpty可重複使用@NotNull和@Size

@Documented 
@Constraint(validatedBy = { }) 
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 
@Retention(RUNTIME) 
@ReportAsSingleViolation 
@NotNull 
@Size(min = 1) 
public @interface NotEmpty { 
    String message() default "{org.hibernate.validator.constraints.NotEmpty.message}"; 

    Class<?>[] groups() default { }; 

    Class<? extends Payload>[] payload() default { }; 

    /** 
    * Defines several {@code @NotEmpty} annotations on the same element. 
    */ 
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 
    @Retention(RUNTIME) 
    @Documented 
    public @interface List { 
     NotEmpty[] value(); 
    } 
} 
+0

這對我來說有點奇怪。我認爲應該重新使用驗證... – alexsmail 2013-03-17 08:09:05

+0

您正在重複使用約束 – Hardy 2013-03-17 14:12:47

+0

並非如此。我無法調用上面的純代碼驗證,也無法調用某些複雜流程中的自定義驗證驗證。 – alexsmail 2013-03-17 18:59:00

0

在這種情況下,您應該爲您驗證的約束聲明一個組。然後你可以調用該組的正常驗證。有關組定義及其語義,請參見規範的第2.1.1.2節和第3.4節。爲了驗證組,您只需撥打Validator.validate(T Object, Class<?>... groups)即可。在這種情況下,沒有必要亂用ConstraintValidatorContext

+0

我想重用現有的ConstraintValidator,而不是處理bean驗證。 – alexsmail 2013-03-14 14:40:29

+0

@alexsmail從'ConstraintValidator'的文檔:'這個方法可以併發訪問,線程安全必須通過實現來保證。「並且規範還指出'允許兼容實現緩存從ConstraintValidatorFactory檢索到的ConstraintValidator實例 。 '(2.4節) – SpaceTrucker 2013-03-14 19:08:09