0

我們有,我們有一個相當製作粗糙的豆含有像這樣領域的使用情況:JSR303驗證 - 使用組從一個自定義類驗證

public class DataBean { 
    private boolean flag1; 
    private boolean flag2; 

    private String phone1; 
    private String address1; 
    private String city1; 
    private String state1; 

    private String phone2; 
    private String address2; 
    private String city2; 
    private String state2; 
} 

我們需要驗證電話/地址/城市/只有在標誌[1 | 2]爲真的情況下狀態[1 | 2]。壞的,糟糕的設計,授予。

我們目前的策略是在每一個「真實」的數據字段的使用@NotNull(或任何驗證,我們需要),並使用羣體指標,像這樣:

public class DataBean { 
    private boolean flag1; 
    private boolean flag2; 

    @NotNull(groups = Info.First.class) 
    private String phone1; 
    @NotNull(groups = Info.First.class) 
    private String address1; 
    @NotNull(groups = Info.First.class) 
    private String city1; 
    @NotNull(groups = Info.First.class) 
    private String state1; 

    @NotNull(groups = Info.Second.class) 
    private String phone2; 
    @NotNull(groups = Info.Second.class) 
    private String address2; 
    @NotNull(groups = Info.Second.class) 
    private String city2; 
    @NotNull(groups = Info.Second.class) 
    private String state2; 
} 

在我們的業務邏輯在那裏我們正在驗證這個bean(其中有各種其他字段,將由「默認」驗證組驗證),我們將違反「default」組,然後檢查flag1是否爲true,如果是,則運行驗證Info.First.class,檢查flag2是否爲真,然後對Info.Second.class運行驗證。

現在的問題......是否有任何方式從一個自定義的類驗證程序鉤入這些組?我設想有一個類驗證程序,它採用flag1/flag2屬性及其相應的自定義組,並且在調用isValid時,它會爲這些組執行這些二級/三級調用。其目的僅僅是自定義類驗證器將處於默認組中,因此驗證此類的業務邏輯將不必將此醜陋的遺留設計的細節泄漏到其中,因爲必須單獨調用驗證。

想法?謝謝!

回答

0

我不完全確定我已經掌握了你正試圖解決的問題。我的解釋是,試圖避免明確地爲每個驗證組分別調用,但根據標誌調用兩個非默認組?不能只定義一些組序列並使用這些而不是標誌?組序列以與組相同的方式使用。關於他們唯一的事情是,如果一個組失敗,他們將停止驗證組。

如果您需要驗證是否始終根據標誌驗證所有組,那麼您的自定義類驗證程序可以調用groups()傳遞給其初始化方法的約束註釋。

+0

我還沒有研究組序列,我會檢查了這一點。謝謝。 – bruth

+1

[組序列](http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#d0e968) – Will

0

創建類級別驗證程序並初始化其中的驗證程序。然後,您可以通過在每個字段上添加約束例外,在類級約束的主要有效方法內通過組驗證對象。請看下圖:

約束接口:

@Documented 
@Constraint(validatedBy = {DataBeanValidator.class}) 
@Target({METHOD, FIELD, ANNOTATION_TYPE, TYPE}) 
@Retention(RUNTIME) 
public @interface DataBeanConstraint { 

    String message() default "validation.dataBean"; 

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

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

驗證:

public class DataBeanValidator implements ConstraintValidator<DataBeanConstraint, DataBean> { 

    private Validator validator; 

    @Override 
    public void initialize(DataBeanConstraint constraintAnnotation) { 
     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
     validator = factory.getValidator(); 
    } 

    @Override 
    public boolean isValid(BeanData beanData, ConstraintValidatorContext context) { 
     if (beanData == null) { 
      return true; 
     } 
     if (beanData.isFlag1) { 
      Set<ConstraintViolation<DataBean>> constraintViolations = validator.validate(beanData, Info.First.class); 
      if (constraintViolations != null) { 
       for (ConstraintViolation<BeanData> constraintViolation : constraintViolations) { 
        context.disableDefaultConstraintViolation(); 
        context.buildConstraintViolationWithTemplate("required field"). 
          addNode(constraintViolation.getPropertyPath().toString()) 
          .addConstraintViolation(); 
       } 
      } 
     } 

    } 
} 

類級別的驗證:

@DataBeanConstraint 
public class DataBean { 
    private boolean flag1; 
    private boolean flag2; 

    @NotNull(groups = Info.First.class) 
    private String phone1; 
    @NotNull(groups = Info.First.class) 
    private String address1; 
    @NotNull(groups = Info.First.class) 
    private String city1; 
    @NotNull(groups = Info.First.class) 
    private String state1; 

    @NotNull(groups = Info.Second.class) 
    private String phone2; 
    @NotNull(groups = Info.Second.class) 
    private String address2; 
    @NotNull(groups = Info.Second.class) 
    private String city2; 
    @NotNull(groups = Info.Second.class) 
    private String state2; 
}