2013-09-16 125 views
1

我想驗證一個字段birthYear:「用戶的年齡必須低於50」。JSR-303 - 作爲參數的計算值?

所以我想使用JSR-303註釋驗證這樣的:

@Max(Calendar.getInstance().get(Calendar.YEAR) - 50) 
private int birthYear; 

但是編譯器說,「屬性值必須是恆定的。」

有沒有辦法以一種簡單的方式來做到這一點?還是有必要爲此實現我自己的驗證器?

+0

可能重複[用於註釋屬性的值Min.value必須是一個常量表達式(http://stackoverflow.com/questions/16744067/the-value-for-annotation-attribute-min-value-must-be-a-constant-expression) – BalusC

+0

是的,你是對的。我無法谷歌它。 – StaNov

+0

但仍然有辦法做到這一點嗎?比實現自定義驗證器更容易? – StaNov

回答

0

正如您的錯誤消息所示,您不能在註釋值中使用表達式,因此您需要使用自定義驗證註釋。

這是比較容易做到這一點:

註釋

@Constraint(validatedBy = AgeConstraintValidator.class) 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) 
public @interface MaxAge { 

/** 
* The age against which to validate. 
*/ 
int value(); 

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

約束驗證

public class AgeConstraintValidator implements ConstraintValidator<MaxAge, Integer> { 

private int maximumAge; 

@Override 
public void initialize(MaxAge constraintAnnotation) { 
    this.maximumAge = constraintAnnotation.value(); 
} 

@Override 
public boolean isValid(Integer value, ConstraintValidatorContext context) { 
    if (value == null) { 
     return true; 
    } 

    return value.intValue() <= this.maximumAge; 
} 

} 

然後,你可以註解你的領域與@MaxAge(50),它應該工作。

1

問題是註釋參數需要有一個可以在編譯時解析的值,但只能在運行時解析調用Calendar.getInstance().get(Calendar.YEAR)因此編譯器錯誤。

您在這種情況最好寫在二傳手邏輯驗證邏輯,就像

public void setBirthYear(int year){ 
    if(Calendar.getInstance().get(Calendar.YEAR) - year < 50) { 
    { 
    throw IllegalAgumentException() 
    } 
    this.birthYear = year; 
} 

替代的東西是,你可以寫一個自定義的JSR 303註解像@VerifyAge(maxAge=50)然後在可以檢查該值是否小於50.

有關如何編寫自定義驗證註釋的詳細信息,請參閱http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/validator-customconstraints.html

0

如果您使用的是Spring框架,那麼您可以使用Spring表達式語言(SpEL)。我寫了一個小型庫,提供基於SpEL的JSR-303驗證器。看看https://github.com/jirutka/validator-spring

有了這個庫,你可以寫你的驗證這樣的:

@SpELAssert("#this < T(java.util.Calendar).getInstance().get(T(java.util.Calendar).YEAR) - 50") 
private int birthYear; 

然而,代碼,即可獲得當前年份是相當難看,是不是?讓我們把它變成一個幫手類!

public class CalendarHelper { 
    public static int todayYear() { 
     return Calendar.getInstance().get(Calendar.YEAR); 
    } 
} 

然後你可以這樣做:

@SpELAssert(value="#this < #todayYear() - 50", helpers=CalendarHelper.class) 
private int birthYear;