資料轉換與驗證(3)

 1.JSF Gossip: 標準轉換器

Web應用程式與瀏覽器之間是使用HTTP進行溝通,所有傳送的資料基本上都是字串文字,而Java應用程式本身基本上則是物件,所以物件資料必須經由轉換傳送給瀏覽器,而瀏覽器送來的資料也必須轉換爲物件才能使用。

JSF定義了一系列標準的轉換器(Converter),對於基本資料型態(primitive type)或是其Wrapper類別,JSF會使用javax.faces.Boolean、javax.faces.Byte、 javax.faces.Character、javax.faces.Double、javax.faces.Float、 javax.faces.Integer、javax.faces.Long、javax.faces.Short等自動進行轉換,對於 BigDecimal、BigInteger,則會使用javax.faces.BigDecimal、javax.faces.BigInteger自動進行轉換。

至於DateTime、Number,我們可以使用<f:convertDateTime>、<f: convertNumber>標籤進行轉換,它們各自提供有一些簡單的屬性,可以讓我們在轉換時指定一些轉換的格式細節。

來看個簡單的例子,首先我們定義一個簡單的Bean:

  • UserBean.java
package onlyfun.caterpillar;

import java.util.Date;

public class UserBean {
private Date date = new Date();

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}
}


這個Bean的屬性接受Date型態的參數,按理來說,接收到HTTP傳來的資料中若有相關的日期資訊,我們必須剖析這個資訊,再轉換爲Date物件,然而我們可以使用JSF的標準轉換器來協助這項工作,例如:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>

<f:view>

<html>
<head>
<title>轉換器示範</title>
</head>
<body>

設定的日期是:
<b>
<h:outputText value="#{user.date}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</b>

<h:form>
<h:inputText id="dateField" value="#{user.date}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:inputText>
<h:message for="dateField" style="color:red"/>
<br>
<h:commandButton value="送出" action="show"/>
</h:form>
</body>
</html>

</f:view>


在<f:convertDateTime>中,我們使用pattern指定日期的樣式爲dd/MM/yyyy,即“日/月/西元”格式,如果轉換錯誤,則<h:message>可以顯示錯誤訊息,for屬性參考至<h:inputText> 的id屬性,表示將有關dateField的錯誤訊息顯示出來。

假設faces-config.xml是這樣定義的:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>show</from-outcome>
<to-view-id>/pages/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<managed-bean>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.UserBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


首次連上頁面時顯示的畫面如下:


如您所看到的,轉換器自動依pattern設定的樣式將Date物件格式化了,當您依格式輸入資料並送出後,轉換器也會自動將您輸入的資料轉換爲Date 物件,如果轉換時發生錯誤,則會出現以下的訊息:


<f:convertDateTime>標籤還有幾個可用的屬性,您可以參考 Tag Library Documentation  的說明,而依照類似的方式,您也可以使用<f:convertNumber>來轉換數值。

您還可以參考 Using the Standard Converters  這篇文章中有關於標準轉換器的說明。

2.JSF Gossip: 自訂轉換器

除了使用標準的轉換器之外,您還可以自行定製您的轉換器,您可以實作 javax.faces.convert.Converter介面,這個介面有兩個要實作的方法:

 public Object getAsObject(FacesContext context,
                           UIComponent component,
                           String str);
 public String getAsString(FacesContext context,
                           UIComponent component,
                           Object obj);

 
簡單的說,第一個方法會接收從客戶端經由HTTP傳來的字串資料,您在第一個方法中將之轉換爲您的自訂物件,這個自訂物件將會自動設定給您指定的Bean 物件;第二個方法就是將從您的Bean物件得到的物件轉換爲字串,如此才能藉由HTTP傳回給客戶端。

直接以一個簡單的例子來作說明,假設您有一個User類別:

  • User.java
package onlyfun.caterpillar;

public class User {
private String firstName;
private String lastName;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}
}


這個User類別是我們轉換器的目標物件,而您有一個GuestBean類別:

  • GuestBook.java
package onlyfun.caterpillar;

public class GuestBean {
private User user;

public void setUser(User user) {
this.user = user;
}

public User getUser() {
return user;
}
}


這個Bean上的屬性直接傳回或接受User型態的參數,我們來實作一個簡單的轉換器,爲HTTP字串與User物件進行轉換:

  • UserConverter.java
package onlyfun.caterpillar;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class UserConverter implements Converter {
public Object getAsObject(FacesContext context,
UIComponent component,
String str)
throws ConverterException {
String[] strs = str.split(",");

User user = new User();

try {
user.setFirstName(strs[0]);
user.setLastName(strs[1]);
}
catch(Exception e) {
// 轉換錯誤,簡單的丟出例外
throw new ConverterException();
}

return user;
}

public String getAsString(FacesContext context,
UIComponent component,
Object obj)
throws ConverterException {
String firstName = ((User) obj).getFirstName();
String lastName = ((User) obj).getLastName();

return firstName + "," + lastName;
}
}


實作完成這個轉換器,我們要告訴JSF這件事,這是在faces-config.xml中完成註冊:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>show</from-outcome>
<to-view-id>/pages/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<converter>
<converter-id>onlyfun.caterpillar.User</converter-id>
<converter-class>
onlyfun.caterpillar.UserConverter
</converter-class>
</converter>

<managed-bean>
<managed-bean-name>guest</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.GuestBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>


註冊轉換器時,需提供轉換器識別(Converter ID)與轉換器類別,接下來要在JSF頁面中使用轉換器的話,就是指定所要使用的轉換器識別,例如:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>

<f:view>

<html>
<head>
<title>自訂轉換器</title>
</head>
<body>

Guest名稱是:<b>
<h:outputText value="#{guest.user}"
converter="onlyfun.caterpillar.User"/>
</b>

<h:form>
<h:inputText id="userField"
value="#{guest.user}"
converter="onlyfun.caterpillar.User"/>
<h:message for="userField" style="color:red"/>
<br>
<h:commandButton value="送出" action="show"/>
</h:form>
</body>
</html>

</f:view>


您也可以<f:converter>標籤並使用converterId屬性來指定轉換器,例如:

 <h:inputText id="userField" value="#{guest.user}">
     <f:converter converterId="onlyfun.caterpillar.User"/>
 </h:inputText>     

 
除了向JSF註冊轉換器之外,還有一個方式可以不用註冊,就是直接在Bean上提供一個取得轉換器的方法,例如:

  • GuestBean.java
package onlyfun.caterpillar;

import javax.faces.convert.Converter;

public class GuestBean {
private User user;
private Converter converter = new UserConverter();

public void setUser(User user) {
this.user = user;
}

public User getUser() {
return user;
}

public Converter getConverter() {
return converter;
}
}


之後可以直接結合 JSF Expression Language 來指定轉換器:

 <h:inputText id="userField"
     value="#{guest.user}"
     converter="#{guest.converter}"/>




3.JSF Gossip: 標準驗證器

當應用程式要求使用者輸入資料時,必然考慮到使用者輸入資料之正確性,對於使用者的輸入必須進行檢驗,檢驗必要的兩種驗證是語法檢驗(Synatic Validation)與語意檢驗(Semantic Validation)。

語法檢驗是要檢查使用者輸入的資料是否合乎我們所要求的格式,最基本的就是檢查使用者是否填入了欄位值,或是欄位值的長度、大小值等等是否符合要求。語意檢驗是在語法檢驗之後,在格式符合需求之後,我們進一步驗證使用者輸入的資料語意上是否正確,例如檢查使用者的名稱與密碼是否匹配。

簡單的導航(Navigation) 中,我們對使用者名稱與密碼檢查是否匹配,這是語意檢驗,我們可以使用JSF所提供的標準驗證器,爲其加入語法檢驗,例如:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>驗證器示範</title>
</head>
<body>
<f:view>
<h:messages layout="table" style="color:red"/>
<h:form>
<h3>請輸入您的名稱</h3>
<h:outputText value="#{user.errMessage}"/><p>
名稱: <h:inputText value="#{user.name}"
required="true"/><p>
密碼: <h:inputSecret value="#{user.password}"
required="true">
<f:validateLength minimum="6"/>
</h:inputSecret><p>
<h:commandButton value="送出"
action="#{user.verify}"/>
</h:form>
</f:view>
</body>
</html>


在<h:inputText>、</h:inputSecret>中,我們設定了required屬性爲true,這表示這個欄位一定要輸入值,我們也在</h:inputSecret>設定了<f: validateLength>,並設定其minimum屬性爲6,這表示這個欄位最少需要6個字元。

這一次在錯誤訊息的顯示上,我們使用<h:messages>標籤,當有驗證錯誤發生時,相關的錯誤訊息會收集起來,使用<h: messages>標籤可以一次將所有的錯誤訊息顯示出來。

下面是一個驗證錯誤的訊息顯示:


JSF提供了三種標準驗證器:<f:validateDoubleRange>、<f:validateLongRange>、 <f:validateLength>,您可以分別查詢它們的 Tag Library Documentation,瞭解他們有哪些屬性可以使用,或者是參考 Using the Standard Validators  這篇文章中有關於標準驗證器的說明。
4.JSF Gossip: 自訂驗證器

您可以自訂自己的驗證器,所需要的是實作javax.faces.validator.Validator介面,例如我們實作一個簡單的密碼驗證器,檢查字元長度,以及密碼中是否包括字元與數字:

  • PasswordValidator.java
package onlyfun.caterpillar;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class PasswordValidator implements Validator {
public void validate(FacesContext context,
UIComponent component,
Object obj)
throws ValidatorException {
String password = (String) obj;

if(password.length() < 6) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"字元長度小於6",
"字元長度不得小於6");
throw new ValidatorException(message);
}

if(!password.matches(".+[0-9]+")) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"密碼必須包括字元與數字",
"密碼必須是字元加數字所組成");
throw new ValidatorException(message);
}
}
}


您要實作javax.faces.validator.Validator介面中的validate()方法,如果驗證錯誤,則丟出一個 ValidatorException,它接受一個FacesMessage物件,這個物件接受三個參數,分別表示訊息的嚴重程度(INFO、 WARN、ERROR、FATAL)、訊息概述與詳細訊息內容,這些訊息將可以使用<h:messages>或<h: message>標籤顯示在頁面上。

接下來要在faces-config.xml中註冊驗證器的識別(Validater ID),要加入以下的內容:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
....
<validator>
<validator-id>
onlyfun.caterpillar.Password
</validator-id>
<validator-class>
onlyfun.caterpillar.PasswordValidator
</validator-class>
</validator>
....
</faces-config>


要使用自訂的驗證器,我們可以使用<f:validator>標籤並設定validatorId屬性,例如:

 ....
 <h:inputSecret value="#{user.password}" required="true">
    <f:validator validatorId="onlyfun.caterpillar.Password"/>
 </h:inputSecret><p>
 ....

 

您也可以讓Bean自行負責驗證的工作,可以在Bean上提供一個驗證方法,這個方法沒有傳回值,並可以接收FacesContext、 UIComponent、Object三個參數,例如:

  • UserBean.java
package onlyfun.caterpillar;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

public class UserBean {
....

public void validate(FacesContext context,
UIComponent component,
Object obj)
throws ValidatorException {
String password = (String) obj;

if(password.length() < 6) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"字元長度小於6",
"字元長度不得小於6");
throw new ValidatorException(message);
}

if(!password.matches(".+[0-9]+")) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"密碼必須包括字元與數字",
"密碼必須是字元加數字所組成");
throw new ValidatorException(message);
}
}
}


接着可以在頁面下如下使用驗證器:

 .....
 <h:inputSecret value="#{user.password}"
                required="true" 
                validator="#{user.validate}"/>
 ....


5.JSF Gossip: 錯誤訊息處理

在使用標準轉換器或驗證器時,當發生錯誤時,會有一些預設的錯誤訊息顯示,這些訊息可以使用<h: messages>或<h:message>標籤來顯示出來,而這些預設的錯誤訊息也是可以修改的,您所要作的是提供一個訊息資源檔案,例如:

  • messages.properties
javax.faces.component.UIInput.CONVERSION=Format Error.
javax.faces.component.UIInput.REQUIRED=Please input your data.
....


javax.faces.component.UIInput.CONVERSION是用來設定當轉換器發現錯誤時顯示的訊息,而 javax.faces.component.UIInput.REQUIRED是在標籤設定了required爲true,而使用者沒有在欄位輸入時顯示的錯誤訊息。

您要在faces-config.xml中告訴JSF您使用的訊息檔案名稱,例如:

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<application>
<local-config>
<default-locale>en</default-locale>
<supported-locale>zh_TW</supported-locale>
</local-config>
<message-bundle>messages</message-bundle>
</application>
.....

</faces-config>


在這邊我們設定了訊息檔案的名稱爲messages_xx_YY.properties,其中xx_YY是根據您的Locale來決定,轉換器或驗證器的錯誤訊息如果有設定的話,就使用設定值,如果沒有設定的話,就使用預設值。

驗證器錯誤訊息,除了上面的javax.faces.component.UIInput.REQUIRED之外,還有以下的幾個:

訊息識別 預設訊息 用於
javax.faces.validator.NOT_IN_RANGE Validation Error: Specified attribute is not between the expected values of {0} and {1}. DoubleRangeValidator與 LongRangeValidator,{0}與{1}分別代表minimum與maximum所設定的屬性
javax.faces.validator.DoubleRangeValidator.MAXIMUM、 javax.faces.validator.LongRangeValidator.MAXIMUM Validation Error: Value is greater than allowable maximum of '{0}'. DoubleRangeValidator或 LongRangeValidator,{0}表示maximum屬性
javax.faces.validator.DoubleRangeValidator.MINIMUM、 javax.faces.validator.LongRangeValidator.MINIMUM Validation Error: Value is less than allowable minimum of '{0}'. DoubleRangeValidator或 LongRangeValidator,{0}代表minimum屬性
javax.faces.validator.DoubleRangeValidator.TYPE、 javax.faces.validator.LongRangeValidator.TYPE Validation Error: Value is not of the correct type. DoubleRangeValidator或 LongRangeValidator
javax.faces.validator.LengthValidator.MAXIMUM Validation Error: Value is greater than allowable maximum of ''{0}''. LengthValidator,{0}代表maximum
javax.faces.validator.LengthValidator.MINIMUM Validation Error: Value is less than allowable minimum of ''{0}''. LengthValidator,{0}代表minimum屬性

在您提供自訂訊息的時候,也可以提供{0}或{1}來設定顯示相對的屬性值,以提供詳細正確的錯誤提示訊息。

訊息的顯示有概述訊息與詳述訊息,如果是詳述訊息,則在識別上加上 "_detail",例如:

 javax.faces.component.UIInput.CONVERSION=Error.
 javax.faces.component.UIInput.CONVERSION_detail= Detail Error.
 .... 

除了在訊息資源檔中提供訊息,您也可以在程式中使用FacesMessage來提供訊息,例如在 自訂驗證器 中我們就這麼用過:

 ....
         if(password.length() < 6) {
            FacesMessage message = new FacesMessage(
                 FacesMessage.SEVERITY_ERROR,
                 "字元長度小於6",
                 "字元長度不得小於6");
            throw new ValidatorException(message);
        }
 ....
 

最好的方法是在訊息資源檔中提供訊息,這麼一來如果我們要修改訊息,就只要修改訊息資源檔的內容,而不用修改程式,來看一個簡單的例子,假設我們的訊息資源檔中有以下的內容: 

 onlyfun.caterpillar.message1=This is message1.
 onlyfun.caterpillar.message2=This is message2 with {0} and {1}.

 則我們可以在程式中取得訊息資源檔的內容,例如:

 package onlyfun.caterpillar;

 import java.util.Locale;
 import java.util.ResourceBundle;
 import javax.faces.context.FacesContext;
 improt javax.faces.component.UIComponent;
 import javax.faces.application.Application;
 import javax.faces.application.FacesMessage;
 
     ....
     public void xxxMethod(FacesContext context,
                          UIComponent component,
                          Object obj) {
         // 取得應用程式代表物件
         Application application = context.getApplication();
         // 取得訊息檔案主名稱
         String messageFileName =
                           application.getMessageBundle();
         // 取得當前 Locale 物件
         Locale locale = context.getViewRoot().getLocale();
         // 取得訊息綁定 ResourceBundle 物件
         ResourceBundle rsBundle =
           ResourceBundle.getBundle(messageFileName, locale);

         String message = rsBundle.getString(
                          "onlyfun.caterpillar.message1");
         FacesMessage facesMessage = new FacesMessage(
              FacesMessage.SEVERITY_FATAL, message, message);
         ....
     }
     ....
 ....


接下來您可以將FacesMessage物件填入ValidatorException或 ConverterException後再丟出,FacesMessage建構時所使用的三個參數是嚴重程度、概述訊息與詳述訊息,嚴重程度有 SEVERITY_FATAL、SEVERITY_ERROR、SEVERITY_WARN與SEVERITY_INFO四種。

如果需要在訊息資源檔中設定{0}、{1}等參數,則可以如下:

 ....
 String message = rsBundle.getString(
                      "onlyfun.caterpillar.message2");
 Object[] params = {"param1", "param2"};
 message = java.text.MessageFormat.format(message, params);

 FacesMessage facesMessage = new FacesMessage(
              FacesMessage.SEVERITY_FATAL, message, message);
....


如此一來,在顯示訊息時,onlyfun.caterpillar.message2的{0}與{1}的位置就會被"param1"與"param2"所取代。


6.JSF Gossip: 自訂轉換、驗證標籤

自訂驗證器 中,我們的驗證器只能驗證一種pattern(.+[0-9]+),我們希望可以在JSF頁面上自訂匹配的pattern,然而由於我們使用<f: validator>這個通用的驗證器標籤,爲了要能提供pattern屬性,我們可以使用<f:attribute>標籤來設置,例如:

 ....
  <h:inputSecret value="#{user.password}" required="true">
    <f:validator validatorId="onlyfun.caterpillar.Password"/>
    <f:attribute name="pattern" value=".+[0-9]+"/>
 </h:inputSecret><p>
 ....

 

使用<f:attribute>標籤來設定屬性,接着我們可以如下取得所設定的屬性:

 ....
 public void validate(FacesContext context,
                         UIComponent component,
                         Object obj)
            throws ValidatorException {
     ....
     String pattern = (String)
                  component.getAttributes().get("pattern");
     ....
 }
 ....

 
您也可以開發自己的一組驗證標籤,並提供相關屬性設定,這需要了解JSP Tag Library的撰寫,所以請您先參考 JSP/Servlet 中有關於JSP Tag Library的介紹。

要開發驗證器轉用標籤,您可以直接繼承javax.faces.webapp.ValidatorTag,這個類別可以幫您處理大部份的細節,您所需要的,就是重新定義它的createValidator()方法,我們以改寫 自訂驗證器 中的PasswordValidator爲例:

  • PasswordValidator.java
package onlyfun.caterpillar;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class PasswordValidator implements Validator {
private String pattern;

public void setPattern(String pattern) {
this.pattern = pattern;
}

public void validate(FacesContext context,
UIComponent component,
Object obj)
throws ValidatorException {
String password = (String) obj;

if(password.length() < 6) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"字元長度小於6", "字元長度不得小於6");
throw new ValidatorException(message);
}

if(pattern != null && !password.matches(pattern)) {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"密碼必須包括字元與數字",
"密碼必須是字元加數字所組成");
throw new ValidatorException(message);
}
}
}


主要的差別是我們提供了pattern屬性,在validate()方法中進行驗證時,是根據我們所設定的pattern屬性,接着我們繼承 javax.faces.webapp.ValidatorTag來撰寫自己的驗證標籤:

  • PasswordValidatorTag.java
package onlyfun.caterpillar;

import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.webapp.ValidatorTag;

public class PasswordValidatorTag extends ValidatorTag {
private String pattern;

public void setPattern(String pattern) {
this.pattern = pattern;
}

protected Validator createValidator() {
Application application =
FacesContext.getCurrentInstance().
getApplication();
PasswordValidator validator =
(PasswordValidator) application.createValidator(
"onlyfun.caterpillar.Password");
validator.setPattern(pattern);
return validator;
}
}


application.createValidator()方法建立驗證器物件時,是根據在faces-config.xml中註冊驗證器的識別(Validater ID):

  • faces-config.xml
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
....
<validator>
<validator-id>
onlyfun.caterpillar.Password
</validator-id>
<validator-class>
onlyfun.caterpillar.PasswordValidator
</validator-class>
</validator>
....
</faces-config>


剩下來的工作,就是佈署tld描述檔了,我們簡單的定義一下:

  • taglib.tld
<?xml version="1.0" encoding="UTF-8" ?> 

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
web-jsptaglibrary_2_0.xsd"
version="2.0">

<description>PasswordValidator Tag</description>
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>co</short-name>
<uri>http://caterpillar.onlyfun.net</uri>

<tag>
<description>PasswordValidator</description>
<name>passwordValidator</name>
<tag-class>
onlyfun.caterpillar.PasswordValidatorTag
</tag-class>
<body-content>empty</body-content>
<attribute>
<name>pattern</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>

</taglib>


而我們的index.jsp改寫如下:

  • index.jsp
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="/WEB-INF/taglib.tld" prefix="co" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>驗證器示範</title>
</head>
<body>
<f:view>
<h:messages layout="table" style="color:red"/>
<h:form>
<h3>請輸入您的名稱</h3>
<h:outputText value="#{user.errMessage}"/><p>
名稱: <h:inputText value="#{user.name}"
required="true"/><p>
密碼: <h:inputSecret value="#{user.password}"
required="true">
<co:passwordValidator pattern=".+[0-9]+"/>
</h:inputSecret> <p>
<h:commandButton value="送出"
action="#{user.verify}"/>
</h:form>
</f:view>
</body>
</html>


主要的差別是,我們使用了自己的驗證器標籤:

 <co:passwordValidator pattern=".+[0-9]+"/>

 
如果要自訂轉換器標籤,方法也是類似,您要作的是繼承javax.faces.webapp.ConverterTag,並重新定義其 createConverter()方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章