Java bean validation 規范與參考實現

jopen 11年前發布 | 20K 次閱讀 Java Java開發

JSR 303 – Bean Validation 是一個數據驗證的規范。 2009年11月正式發布最終版本。
在 任何時候,當你要處理一個應用程序的業務邏輯,數據校驗是你必須要考慮和面對的事情。應用程序必須通過某種手段來確保輸入進來的數據從語義上來講是正確 的。在通常的情況下,應用程序是分層的,比如表現層,業務層,持久化層等,很多時候同樣的數據驗證邏輯會出現在不同的層,這樣就會導致代碼冗余和一些管理 的問題,比如說語義的一致性等。為了避免這樣的情況發生,最好是將驗證邏輯與相應的域模型進行綁定,為各個層提供統一的數據校驗。

Bean Validation 為 JavaBean 驗證定義了相應的元數據模型和 API。缺省的元數據是 Java Annotations,通過使用 XML 可以對Java注解信息進行覆蓋和擴展。在應用程序中,通過使用 Bean Validation 或是你自己定義的 constraint,例如 @NotNull, @Max, @ZipCode, 就可以確保數據模型(JavaBean)的正確性。在JSR303規范中,constraint 可以附加到字段,getter 方法,類或者接口上面。對于一些特定的需求,用戶可以很容易的開發定制化的 constraint。Bean Validation 是一個運行時的數據驗證框架,在驗證之后驗證的錯誤信息會被馬上返回。

Hibernate Validator 4.0是 JSR 303 的參考實現。

IBM developerWorks網站有一篇很好的文章介紹它。

JSR 349是Bean Validation 1.1規范,根據社區的反饋對JSR 303進行了優化和加強。 可以點擊這里查看細節。
主要圍繞一下方面進行工作。

  • 集成其它最新發布的JSR
  • JAX-RS: 對HTTP method進行參數和返回值的校驗
  • JAXB: 集成JAXB.
  • JPA: 提升JPA的集成
  • CDI: 允許CDI風格的注入
  • CDI: 集成方法級別的校驗
  • EJB: 集成方法級別的校驗
  • JSF: 集成JSF

Hibernate Validator 5.x 是Bean Validation 1.1參考實現。

hibernate validator官方文檔提供了注解的列表。

Annotation Supported data types Use Hibernate metadata impact
@AssertFalse Boolean, boolean Checks that the annotated element is false None
@AssertTrue Boolean, boolean Checks that the annotated element is true None
@DecimalMax(value=, inclusive=) BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number Checks whether the annotated value is less than the specified maximum, when inclusive=false. Otherwise whether the value is less than or equal to the specified maximum. The parameter value is the string representation of the max value according to the BigDecimal string representation. None
@DecimalMin(value=, inclusive=) BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number Checks whether the annotated value is larger than the specified minimum, when inclusive=false. Otherwise whether the value is larger than or equal to the specified minimum. The parameter value is the string representation of the min value according to the BigDecimal string representation. None
@Digits(integer=, fraction=) BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of Number Checks whether the annoted value is a number having up to integer digits and fraction fractional digits Defines column precision and scale
@Future java.util.Date, supported by HV, if the Joda Time date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant Checks whether the annotated date is in the future None
@Max(value=) BigDecimal, BigInteger, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number Checks whether the annotated value is less than or equal to the specified maximum Adds a check constraint on the column
@Min(value=) BigDecimal, BigInteger, byte, short, int, long and the respective wrappers of the primitive types; Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the char sequence is evaluated), any sub-type of Number Checks whether the annotated value is higher than or equal to the specified minimum Adds a check constraint on the column
@NotNull Any type Checks that the annotated value is not null. Column(s) are not nullable
@Null Any type Checks that the annotated value is null None
@Past java.util.Date, java.util.Calendar; Additionally date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant Checks whether the annotated date is in the past None
@Pattern(regex=, flag=) CharSequence Checks if the annotated string matches the regular expression regex considering the given flag match None
@Size(min=, max=) CharSequence, Collection, Map and arrays Checks if the annotated element’s size is between min and max (inclusive) Column length will be set to max
@Valid Any non-primitive type Performs validation recursively on the associated object. If the object is a collection or an array, the elements are validated recursively. If the object is a map, the value elements are validated recursively. None

另外,Hibernate提供了額外的注解:

Annotation Supported data types Use Hibernate metadata impact
@CreditCardNumber(ignoreNonDigitCharacters=) CharSequence Checks that the annotated character sequence passes the Luhn checksum test. Note, this validation aims to check for user mistakes, not credit card validity! See also Anatomy of Credit Card Numbers. ignoreNonDigitCharacters allows to ignore non digit characters. The default is false. None
@EAN CharSequence Checks that the annotated character sequence is a valid EAN barcode. type determines the type of barcode. The default is EAN-13. None
@Email CharSequence Checks whether the specified character sequence is a valid email address. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression flags) which the email must match. None
@Length(min=, max=) CharSequence Validates that the annotated character sequence is between min and max included Column length will be set to max
@LuhnCheck(startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=) CharSequence Checks that the digits within the annotated character sequence pass the Luhn checksum algorithm (see also Luhn algorithm). startIndex and endIndex allow to only run the algorithm on the specified sub-string. checkDigitIndex allows to use an arbitrary digit within the character sequence as the check digit. If not specified it is assumed that the check digit is part of the specified range. Last but not least, ignoreNonDigitCharacters allows to ignore non digit characters. None
@Mod10Check(multiplier=, weight=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=) CharSequence Checks that the digits within the annotated character sequence pass the generic mod 10 checksum algorithm. multiplier determines the multiplier for odd numbers (defaults to 3), weight the weight for even numbers (defaults to 1). startIndex and endIndex allow to only run the algorithm on the specified sub-string. checkDigitIndex allows to use an arbitrary digit within the character sequence as the check digit. If not specified it is assumed that the check digit is part of the specified range. Last but not least, ignoreNonDigitCharacters allows to ignore non digit characters. None
@Mod11Check(threshold=, startIndex=, endIndex=, checkDigitIndex=, ignoreNonDigitCharacters=, treatCheck10As=, treatCheck11As=) CharSequence Checks that the digits within the annotated character sequence pass the mod 11 checksum algorithm. threshold specifies the threshold for the mod11 multiplier growth; if no value is specified the multiplier will grow indefinitely. treatCheck10As and treatCheck11As specify the check digits to be used when the mod 11 checksum equals 10 or 11, respectively. Default to X and 0, respectively. startIndex, endIndex acheckDigitIndex and ignoreNonDigitCharacters carry the same semantics as in @Mod10Check. None
@NotBlank CharSequence Checks that the annotated character sequence is not null and the trimmed length is greater than 0. The difference to @NotEmpty is that this constraint can only be applied on strings and that trailing whitespaces are ignored. None
@NotEmpty CharSequence, Collection, Map and arrays Checks whether the annotated element is not null nor empty None
@Range(min=, max=) BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types Checks whether the annotated value lies between (inclusive) the specified minimum and maximum None
@SafeHtml(whitelistType=, additionalTags=, additionalTagsWithAttributes=) CharSequence

Checks whether the annotated value contains potentially malicious fragments such as <script/>. In order to use this constraint, the jsoup library must be part of the class path.

With the whitelistType attribute a predefined whitelist type can be chosen which can be refined via additionalTags or additionalTagsWithAttributes. The former allows to add tags without any attributes, whereas the latter allows to specify tags and optionally allowed attributes using the annotation @SafeHtml.Tag.

None
@ScriptAssert(lang=, script=, alias=) Any type Checks whether the given script can successfully be evaluated against the annotated element. In order to use this constraint, an implementation of the Java Scripting API as defined by JSR 223 ("Scripting for the JavaTM Platform") must part of the class path. The expressions to be evaluated can be written in any scripting or expression language, for which a JSR 223 compatible engine can be found in the class path. None
@URL(protocol=, host=, port= regexp=, flags=) CharSequence Checks if the annotated character sequence is a valid URL according to RFC2396. If any of the optional parameters protocol, host or port are specified, the corresponding URL fragments must match the specified values. The optional parameters regexp and flags allow to specify an additional regular expression (including regular expression flags) which the URL must match. None

你可以通過下面的代碼校驗帶注解的Java Bean實例。

Validator validator = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true )
.buildValidatorFactory()
.getValidator();
Set<ConstraintViolation<Car>> constraintViolations = validator.validate( anInstance );

在Spring中可以配置如下:

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass"
value="org.hibernate.validator.HibernateValidator" />
</bean>

Apache BVal提供了JSR 303另外一個實現。

ValidatorFactory avf =
Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory();
Validator validator = avf.getValidator();
Set<ConstraintViolation<Car>> constraintViolations = validator.validate( anInstance );

在Spring中可以配置如下:

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass"
value="org.apache.bval.jsr303.ApacheValidationProvider" />
</bean>

另外Apache還有一個較老的項目:Apache Commons Validator,提供了一些校驗類。

DateValidator validator = DateValidator.getInstance();
// Validate/Convert the date
Date fooDate = validator.validate(fooString, "dd/MM/yyyy");
if (fooDate == null) {
// error...not a valid date
return;
}

依照carinae.net網站(http://carinae.net /2010/06/benchmarking-hibernate-validator-and-apache-beanvalidation-the- two-jsr-303-implementations/)的2010年的測試,
Apache bval性能要好于hibernate。 這么多年過去了,不知道現在的性能怎么樣了。
性能比較性能比較

來自:http://colobu.com/2014/08/08/Java-bean-validation-spec-and-framework/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!