2012-05-04 198 views
6

我有一个简单的bean与enumJSR-303 Bean验证,枚举领域

public class TestBean{ 
    @Pattern(regexp = "A|B") //does not work 
    private TestEnum testField; 
    //getters + setters 
} 

enum TestEnum{ 
    A, B, C, D 
} 

我想用Bean验证验证testField。具体而言,我想确保只允许A和B的值(对于特定的calidation gropus)。看起来,枚举不是处理JSR 303(我试图使用@Pattern验证器),或者我正在做一些错误的方法。

我得到异常:

javax.validation.UnexpectedTypeException: No validator could be found for type: packagename.TestEnum 

有什么办法来验证枚举域,而无需编写自定义的验证?

回答

3

如果你想把约束放在testField你需要一个自定义的验证器。没有默认的处理枚举。

作为一种变通方法,您可以添加返回枚举

public class TestBean{ 
    private TestEnum testField; 
    //getters + setters 

    @Pattern(regexp = "A|B") //does not work 
    private String getTestFieldName() { 
     return testField.name(); 
    } 
} 

的字符串值自定义验证可能是清洁的解决方案,虽然getter方法。

3

由于由于某些原因不支持枚举,因此可以简单地使用基于String的验证器来处理此限制。

验证:

/** 
* Validates a given object's String representation to match one of the provided 
* values. 
*/ 
public class ValueValidator implements ConstraintValidator<Value, Object> 
{ 
    /** 
    * String array of possible enum values 
    */ 
    private String[] values; 

    @Override 
    public void initialize(final Value constraintAnnotation) 
    { 
     this.values = constraintAnnotation.values(); 
    } 

    @Override 
    public boolean isValid(final Object value, final ConstraintValidatorContext context) 
    { 
     return ArrayUtils.contains(this.values, value == null ? null : value.toString()); 
    } 
} 

接口:

@Target(value = 
{ 
    ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER 
}) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy = 
{ 
    ValueValidator.class 
}) 
@Documented 
public @interface Value 
{ 
    public String message() default "{package.Value.message}"; 

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

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

    public String[] values() default 
    {}; 
} 

验证使用Apache公共图书馆。先进的胁迫类型方法将进一步增强此验证器的灵活性。

替代方案可以使用单个字符串属性而不是数组并按分隔符分割。由于阵列没有被打印,这也会很好地输出错误消息的值,但处理空值可能是一个问题,使用String.valueOf(...)