JSF (JavaServer Faces) 內建強大的轉換與驗證框架,發生在請求處理生命週期的「應用請求值」與「處理驗證」階段。本文系統解析標準轉換器/驗證器、自訂實作步驟、錯誤訊息客製化、immediate 屬性機制與生命週期關鍵點。
基本生命週期階段:
轉換器 getAsObject() 在階段 2 執行,將請求字串轉為物件;驗證器 validate() 在階段 3 執行;getAsString() 在階段 6 將物件轉回字串呈現。
UIInput immediate="true":轉換+驗證提前至階段 2 (應用請求值)UICommand immediate="true":動作調用提前至階段 2,跳過驗證,適用「取消」、「跳過」按鈕| Converter ID | 實作類別 | 適用型別 |
|---|---|---|
| javax.faces.BigDecimal | BigDecimalConverter | BigDecimal |
| javax.faces.BigInteger | BigIntegerConverter | BigInteger |
| javax.faces.Boolean | BooleanConverter | Boolean/boolean |
| javax.faces.Byte | ByteConverter | Byte/byte |
| javax.faces.Character | CharacterConverter | Character/char |
| javax.faces.DateTime | DateTimeConverter | Date/Calendar |
| javax.faces.Double | DoubleConverter | Double/double |
| javax.faces.Float | FloatConverter | Float/float |
| javax.faces.Integer | IntegerConverter | Integer/int |
| javax.faces.Long | LongConverter | Long/long |
| javax.faces.Number | NumberConverter | Number 子類 |
| javax.faces.Short | ShortConverter | Short/short |
| 驗證器 | 標籤 | 用途 |
|---|---|---|
| DoubleRangeValidator | <f:validateDoubleRange> | 數值在 min/max 範圍 |
| LongRangeValidator | <f:validateLongRange> | 長整數在 min/max 範圍 |
| LengthValidator | <f:validateLength> | 字串長度在 min/max 範圍 |
業務邏輯驗證,如「信用額度檢查」、「用戶名唯一性」。在 Action 方法中執行:
public String register() {
if (userService.exists(user.getUsername())) {
FacesMessage msg = new FacesMessage("用戶名已存在");
facesContext.addMessage("registerForm:username", msg);
return null; // 留在當前頁
}
// 繼續註冊邏輯
return "success";
}
訊息關鍵:clientId = formId:componentId,對應視圖組件顯示錯誤。
步驟:
javax.faces.validator.Validatorvalidate(FacesContext, UIComponent, Object)faces-config.xml 註冊 <validator><f:validator validatorId="..."/>郵遞區號驗證器範例 (支援可選 +4 碼):
public class ZipCodeValidator implements Validator {
private boolean plus4Required, plus4Optional;
private static final String ZIP_REGEX = "[0-9]{5}";
private static final String PLUS4_REQUIRED = "[ |-]{1}[0-9]{4}";
private static final String PLUS4_OPTIONAL = "([ |-]{1}[0-9]{4})?";
public void validate(FacesContext ctx, UIComponent comp, Object value)
throws ValidatorException {
initProps(comp); // 讀取 f:attribute 設定
String regex = ZIP_REGEX + (plus4Required ? PLUS4_REQUIRED : plus4Optional ? PLUS4_OPTIONAL : "");
if (!Pattern.matches(regex, (String)value)) {
FacesMessage msg = new FacesMessage("郵遞區號格式錯誤");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
private void initProps(UIComponent comp) {
plus4Optional = Boolean.valueOf((String)comp.getAttributes().get("plus4Optional"));
plus4Required = Boolean.valueOf((String)comp.getAttributes().get("plus4Required"));
}
}
註冊:
com.example.ZipCodeValidator
com.example.validator.ZipCodeValidator
使用:
方法簽名必須符合 validate(FacesContext, UIComponent, Object):
// Backing Bean
public void validateEmail(FacesContext ctx, UIComponent comp, Object value) {
String email = (String)value;
if (email.indexOf('@') == -1) {
((UIInput)comp).setValid(false);
FacesMessage msg = new FacesMessage("Email 格式錯誤");
ctx.addMessage(comp.getClientId(ctx), msg);
}
}
JSF 頁面:<h:inputText validator="#{userRegistration.validateEmail}"/>
關鍵: 驗證發生在「更新模型值」之前,故無法直接存取 Backing Bean 屬性,必須透過 UIComponent 取得提交值。
required="false" 時完全跳過該組件驗證。
JSF 內建訊息在 jsf-impl.jar!/javax/faces/Messages.properties,內容冗長。客製化步驟:
messages.properties (或 messages_zh_TW.properties)javax.faces.component.UIInput.REQUIRED = {0} 為必填欄位javax.faces.converter.DateTimeConverter.DATE = {0} 日期格式錯誤,請輸入 {1}faces-config.xml 註冊訊息包:
com.example.messages
PhoneNumber),標準驗證器 (如 LengthValidator) 只能驗證字串,**不可混用**ConverterException),或撰寫對應物件型別的自訂驗證器converter-for-class 讓 JSF 自動處理,無需頁面標籤JSF 轉換/驗證框架提供從原型到生產的平滑演進:標準組件快速起步、自訂組件構建領域驗證庫、訊息包統一用戶體驗。深度理解生命週期階段、immediate 屬性、轉換驗證順序,是掌握 JSF 資料完整性控制的關鍵。