【问题标题】:Is there a 'choice' Java annotation equivalent to <xs:choice>?是否有等效于 <xs:choice> 的“选择”Java 注释?
【发布时间】:2016-07-05 08:52:59
【问题描述】:

我希望通过仅允许请求中的两个不同字段之一来对 Web 服务请求进行字段验证。我从过去使用 xsd 的经验中知道,你可以有这样的东西,只允许 FieldOne FieldTwo:

<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;

我想说用户只能输入 either fieldOne 或 fieldTwo,但不能同时输入。这是否可以通过注释实现,还是我坚持在我的代码中编写此验证?

【问题讨论】:

  • 你的意思是你的类中有 2 个字段(fieldOnefieldTwo),但其中只有一个允许有值?
  • 是的,这就是我想要的。
  • 我已经更新了答案。请看看有没有帮助

标签: java web-services validation xsd annotations


【解决方案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;

}

原文:

我不确定我是否真的理解你的意思,但看起来你想要验证 Object 字段的 Class 类型。如果出现这种情况,您可以尝试创建自定义注释和 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;

}

希望这能有所帮助。

【讨论】:

  • 感谢您的帮助。这不是我要找的,但它帮助我更好地理解了问题。
  • 您能否提供更多有关您对该问题的要求的详细信息?这可能有助于我和其他人提出更合适的解决方案。
  • 完美,感谢您为此所做的工作。这解决了我的问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 2012-01-15
  • 2019-01-13
  • 2013-06-10
相关资源
最近更新 更多