2014-11-25 78 views
3

我有自定义的注释,像这样:如何在Hibernate中验证注释中的属性?

@Documented 
@Constraint(validatedBy = MyValidator.class) 
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 

    String message() default "message"; 

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

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

和校验,以验证的东西:

public class MyValidator implements ConstraintValidator<MyAnnotation, String> { 

    @Override 
    public void initialize(MyAnnotation myAnnotation) { 
    } 

    @Override 
    public boolean isValid(String value, ConstraintValidatorContext context) { 
     ConstraintValidatorContextImpl con = (ConstraintValidatorContextImpl)context; 

     String diff = getDiff(value, cleanForHTMLContext(value)); 
     if(diff.isEmpty()){ 
      return true; 
     } 
     return false; 
    } 

    private cleanForHTMLContext(String value) { 
     // Some stuff to clean up value 
    } 

    private String getDiff(String value, String cleanedValue) { 
     // Some stuff to compare values 
    } 
} 

我的目标是增加“差异”来注解属性,那么以后有可能通过ResourceBundle中的键和属性来解析消息。

作为例子:当使用类型无效的日期,但应该看到folloiwng消息:

数据无效,因为包含这样的文字:{DIFF}。其中diff将是运行时间比较结果,两个字符串将在isValid()方法中评估。

我试图从地图参数ovverrite值是这样的:

ConstraintValidatorContextImpl con = (ConstraintValidatorContextImpl)context; 
con.getConstraintDescriptor().getAttributes().put("diff", value); 

但不幸的是我得到了关于被在ConstraintDescriptorImpl

创建的任何其他可能添加自定义属性,这些属性将unmodifible地图例外然后用错误代码解决?

回答

4

刚刚尝试过这个,下面的解决方案适用于使用Hibernate Validator的情况。请注意,您的消息必须包含${}以标记可变部分,而不是{}

private MyAnnotation annotation; 

@Override 
public void initialize(MyAnnotation a) 
{ 
    this.annotation = a; 
} 

@Override 
public boolean isValid(String value, ConstraintValidatorContext ctx) 
{ 
    String diff = getDiff(value, cleanForHTMLContext(value)); 
    if (diff.isEmpty()) 
     return true; 

    String message = annotation.message(); 
    HibernateConstraintValidatorContext hctx = ctx.unwrap(HibernateConstraintValidatorContext.class); 

    ctx.disableDefaultConstraintViolation(); 
    ctx.addExpressionVariable("diff", diff) 
     .buildConstraintViolationWithTemplate(message) 
     .addConstraintViolation(); 
    return false; 
} 

注意你的消息应该包含${diff}为模板,不{diff}

... 
public @interface MyAnnotation { 
    String message() default "Data invalid, because contain this text: ${diff}."; 
... 
+0

感谢您的回答。但是,我已经尝试过这样的事情,但忘了指定。不幸的是,它不适用于我的情况。我与BindingResult对象一起工作的主要困难是随后转换为CustomObject以在客户端有可能解析消息。 – fashuser 2014-11-25 16:42:06

+0

当我尝试使用MyCustomAnnotation消息验证对象“数据无效,因为包含此文本:{diff}”。将被设置为该对象的defaultMessage字段。在这种情况下,我不知道何时从该字段中提取消息。例如,当通过Length hibernate注释验证字段时,它会自动将默认消息设置为BindingResult。 – fashuser 2014-11-25 16:42:29

+0

我扩展了答案以包含完整的'isValid()'方法。希望这使得它更清晰。我不知道做适当的模板替换的方法,但包含了一个可能或不可行的替代(更清洁)方法的建议。 – geert3 2014-11-25 17:00:17