2014-11-25 79 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