2016-07-05 71 views
0

我期待通過僅允許請求中的兩個不同字段之一來驗證Web服務請求。我知道,從過去的使用經驗,XSD,你可以有這樣的事情,只允許任何FieldOne FieldTwo:是否存在相當於<xs:choice>的「選擇」Java註釋?

<xs:complexType name="SomeType"> 
    <xs:choice> 
     <xs:element name="FieldOne" type="target:FieldOneType"/> 
     <xs:element name="FieldTwo" type="target:FieldTwoType"/> 
    </xs:choice> 
</xs:complexType> 

我願做同樣的使用Java註解。我目前使用註釋來限制字段長度(@Digits)和空值檢查(@NotNull)。

有什麼我可以使用的'選擇'?

感謝您的任何幫助。

更新:基本上我正在尋找一種方法,只允許在Web服務請求中輸入兩個不同字段中的一個,而無需在我的代碼中手動執行此驗證。我目前使用bean validation annotations限制字段長度,並確定一個字段是強制性的還是可選的如:

@NotNull(message="Field cannot be empty") 
@Size(max = 6, message = "Field length is too long") 
private String fieldOne; 

我想能夠說的是,用戶只能輸入要麼 fieldOne或fieldTwo,但不是都。這是可能通過註釋或我堅持在我的代碼中寫這個驗證?

+0

你的意思是說你的班級有兩個字段('fieldOne'和'fieldTwo'),但只有其中一個允許有價值嗎? – Wilson

+0

是的,這就是我想要的。 – colmulhall

+0

我已經更新了答案。請看看它是否可以幫助 – Wilson

回答

1

編輯:

要驗證任何一個領域都有價值,但沒有其他的,我覺得你可以在類級別使用自定義的驗證。以下是思路:

1. 您的註釋創建界面:

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy = ChoiceValidator.class) 
@Documented 
public @interface Choice { 

    String[] fields(); 

    String message() default "{Choice.message}"; 
    Class<?>[] groups() default {}; 
    Class<? extends Payload>[] payload() default {}; 

} 

2. 創建的ConstraintValidator一個實施檢查,以驗證該值在fields裏面Choice註釋:

public class ChoiceValidator 
     implements ConstraintValidator<Choice, Object> { 

    private List<String> fields; 

    @Override 
    public void initialize(final Choice choice) { 
     fields = Arrays.asList(choice.fields()); 
    } 

    @Override 
    public boolean isValid(final Object value, final ConstraintValidatorContext ctx) { 

     int nonNullFieldCount = 0; 
     for (String field : fields) { 
      try { 
       final String fieldValue = BeanUtils.getProperty(value, field); 
       if (fieldValue != null) { 
        nonNullFieldCount++; 
       } 
      } catch (IllegalAccessException e) { 
       throw new RuntimeException(e); 
      } catch (InvocationTargetException e) { 
       throw new RuntimeException(e); 
      } catch (NoSuchMethodException e) { 
       throw new RuntimeException(e); 
      } 
     } 

     return nonNullFieldCount == 1; 
    } 

} 

之後,你可以使用類似於:

@Choice(fields= {"fieldOne", "fieldTwo"}) 
public class Foo { 

    String fieldOne; 

    String fieldTwo; 

} 

原文:

我不知道我真正得到你的意思,但看起來像你想的Class類型一個Object場的驗證。如果出現這種情況,您可以嘗試創建自定義註釋並執行ConstraintValidator。下面的理念是:

1. 您的註釋創建界面:

public @interface Choice { 

    Class<?>[] types(); 

} 

2。 創建的ConstraintValidator一個實施檢查值進行驗證是types裏面Choice註釋:

public class ChoiceValidator implements ConstraintValidator<Choice, Object> { 

    private List<Class<?>> clazzes; 

    @Override 
    public void initialize(Choice choice) { 
     clazzes = Arrays.asList(choice.types()); 
    } 

    @Override 
    public boolean isValid(Object value, ConstraintValidatorContext context) { 
     for (Class<?> clazz : clazzes) { 
      if (value.getClass().equals(clazz)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 

之後,你可以用它像:

@Choice(types = {FieldOneType.class, FieldTwoType.class}) 
public class Foo { 

    Object someType; 

} 

希望這可以幫助。

+0

感謝您的幫助。這不是我正在尋找的東西,但它幫助我更好地理解了這個問題。 – colmulhall

+0

你能提供關於你對這個問題的要求的更多細節嗎?這可能會幫助我和其他人提出一個更合適的解決方案。 – Wilson

+0

我已經添加了一些附加信息。謝謝。 – colmulhall