Bean 驗證
「Bean 驗證」API 隨 Java™ Enterprise Edition 6 平台引進,成為一種標準機制,在應用程式的所有層(包括呈現層、商業層及資料存取層)中驗證 JavaBeans。
在「Bean 驗證」規格之前,每一層都會驗證 JavaBeans。 為了防止在每一層重新實作驗證,開發人員就直接將驗證組合到類別中,或複製驗證程式碼,這通常變得很雜亂。具有一個針對應用程式的所有層次所共用的實作,會簡化開發人員的工作,並節省時間。
「Bean 驗證」規格定義 meta 資料模型和 API,用於驗證 JavaBeans 的資料完整性。 Meta 資料來源是已定義的限制註釋,可以使用 XML 驗證描述子來置換和延伸。API 集合提供簡易的程式設計模型,可讓任何應用程式層使用同一組驗證限制。驗證限制用來檢查標註欄位、方法和類型的值,以確保它們符合已定義的限制。
限制可以是內建或由使用者定義。javax.validation.constraints 套件中提供數個內建註釋。這些註釋用來定義一般限制定義及編寫限制。 請參閱「Bean 驗證」內建限制的相關資訊,以取得內建限制的清單。如需「Bean 驗證」meta 資料模型和 API 的詳細資料,請參閱「JSR 349 Bean 驗證」規格文件。
下列範例是使用內建限制註釋來裝飾的一個簡單 Enterprise JavaBeans (EJB) 類別。
public class Home {
@Size(Max=20)
String builder;
@NotNull @Size(Max=20)
String address;
public String getAddress() {
return address;
}
public String getBuilder() {
return address;
}
public String setAddress(String newAddress) {
return address = newAddress;
}
public String setBuilder(String newBuilder) {
return builder = newBuilder;
}
}
builder 和 address 的 @Size 註釋指定指派的字串值不應超過 20 個字元。address 的 @NotNull 註釋指出它不能為空值。 驗證 Home 物件時,builder 和 address 值會傳遞給 @Size 註釋所定義的驗證器類別。address 值也會傳遞給 @NotNull 驗證器類別。 驗證器類別負責檢查值是否符合適當的限制,如果有任何限制未通過驗證,則會建立 ConstraintViolation 物件,並整組傳回給驗證 Home 物件的呼叫端。
驗證 API
javax.validation 套件包含 Bean 驗證 API,用以說明如何以程式設計方式驗證 JavaBeans。
ConstraintViolation 是說明單一限制失敗的類別。整組的 ConstraintViolation 類別會傳回供驗證物件。發生限制違規時,還會顯示人類可讀訊息來描述違規情形。
如果驗證期間失敗,則會引發 ValidationException。
Validator 介面是主要的驗證 API,而 Validator 實例是物件,能夠驗證 Java 物件欄位、方法和類型的值。 引導 API 是用來存取 ValidatorFactory 的機制,而 ValidatorFactory 用於建立 Validator 實例。對於部署在本產品的應用程式,自動會進行引導。應用程式可以透過兩種方式取得 Validator 或 ValidatorFactory。一種方式是注入(例如,使用 @Resource 註釋),另一種方式是 java: 查閱。
@Resource ValidatorFactory _validatorFactory;
@Resource Validator _validator;
ValidatorFactory validatorFactory = (ValidatorFactory)context.lookup("java:comp/ValidatorFactory");
Validator validator = (Validator)context.lookup("java:comp/Validator");
限制 meta 資料要求 API
Meta 資料 API 支援工具提供者,可以與其他架構、程式庫和 Java Platform Enterprise Edition 技術整合。您可以透過給定類別的 Validator 實例,存取物件限制的 meta 資料儲存庫。
XML 部署描述子
除了在註釋中宣告限制之外,還支援使用 XML 來宣告限制。
驗證 XML 說明由兩種 XML 檔組成。 META-INF/validation.xml 檔說明模組的 Bean 驗證配置。另一種 XML 檔類型說明限制宣告,非常符合註釋宣告方法。 對於以 XML 說明的類別,依預設會忽略以註釋表達的所有限制宣告。您可以在 Bean 上使用 ignore-annotation="false" 設定,以強制驗證同時使用註釋和 XML 限制宣告。 本產品會建立模組(包含 XML 描述子)專用的驗證器實例,以確保隔離已部署的應用程式模組(包含 validation.xml 檔以及在 XML 檔中定義的限制)與其他模組 validation.xml 和限制檔案。
進階 Bean 驗證概念
「Bean 驗證」API 提供一組內建限制和一個可讓您宣告自訂限制的介面。作法是建立限制註釋,並於 Bean 類型、欄位或內容上宣告註釋。 編寫限制時也是在另一個限制定義上宣告限制。
下列範例顯示如何建立定義的 CommentChecker 限制,以確保註解字串欄位不是空值。 註解文字用方括弧括起來,例如 [text]。
package com.my.company;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = CommentValidator.class)
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface CommentChecker {
String message() default "The comment is not valid.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
…}
package com.my.company;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class CommentValidator implements ConstraintValidator<CommentChecker, String> {
public void initialize(CommentChecker arg0) {
}
public boolean isValid(String comment, ConstraintValidatorContext context) {
if (comment == null) {
// Null comment is not allowed, fail the constraint.
return false;
}
if (!comment.contains("[") && !comment.contains("]")) {
// Can't find any open or close brackets, fail the constraint
return false;
}
// Ignore leading and trailing spaces
String trimmedComment = comment.trim();
return // validate '[' prefix condition
trimmedComment.charAt(0) == '[' &&
// validate ']' suffix condition
trimmedComment.charAt(trimmedComment.length()!-1) == ']';
}
}
定義 @CommentChecker 之後,就可根據 CommentValidator isValid() 實作,用來確保註解字串欄位為有效的註解。下列範例顯示 @CommentChecker 限制的用法。驗證 myChecker Bean 時,CommentValidator 類別會驗證註解字串,確保符合定義的限制。package com.my.company;
public myChecker {
@CommentChecker
String comment = null;
...
}
本產品提供預設的 Bean 驗證提供者,但您可以在應用程式中使用替代的提供者。您可以呼叫 javax.validation.Validation.byProvider() 方法來建立驗證 Factory,以程式設計方式選擇替代提供者。 或者,您也可以在 validation.xml 檔中指定 <default-provider/> 元素,以宣告方式選擇替代提供者。如果要確保替代提供者類別與預設提供者不會發生衝突,請將伺服器或應用程式類別載入器順序設定為此值:Classes loaded with local class loader first (parent last)。有關如何設定此設定的其他資訊,請參閱類別載入文件。
「Bean 驗證」規格指出如果在類別路徑中找到多個 validation.xml 檔,則會發生 ValidationException。不過,WebSphere® Application Server 支援一種環境,可讓多個團隊開發模組,然後組合並一起部署到 Application Server。 在此環境中,應用程式內的所有 EJB 模組由同一類別載入器來載入,而且可以配置應用程式類別載入器,以便只透過單一類別載入器來載入所有 EJB 模組和 Web 保存檔 (WAR) 模組。 因此,本產品支援相同的類別路徑中可以有多個 validation.xml 檔案。
<constraint-mapping>META-INF/constraints-house.xml</constaint-mapping>
<constraint-mapping>META-INF/constraints-rooms.xml</constraint-mapping>
當所有 Bean 驗證限制類別和配置可讓所有應用程式模組看見時,將不會有此行為。 如果在 EAR 檔中只定義單一 validation.xml 檔,而且模組的類別路徑中看不到其他任何 validation.xml 檔,則任何會建立驗證器 Factory 或驗證器的模組,都將使用 EAR 檔中定義的 validation.xml 檔。 這使得其他模組可以建立驗證器 Factory 來使用另一個模組的 validation.xml 檔,前提是類別路徑已配置成可以在相同的類別路徑上看見這兩個模組,而且只有一個 validation.xml 檔可讓這些模組看見。
如需更詳細瞭解「Bean 驗證」API 和 meta 資料,請參閱「JSR 349 Bean 驗證」規格文件。