UI控件、轉(zhuǎn)換器和驗(yàn)證器實(shí)現(xiàn)了StateHolder接口表示組件具有了狀態(tài),可以保存一些組件自身的屬性。
下面我們來(lái)看一個(gè)簡(jiǎn)單的例子。
這是一個(gè)正則表達(dá)式驗(yàn)證器的例子:
public class RegexValidator implements Validator


{

/** *//**
* The message identifier of the Message to be created if
* the validation fails.
*/
public static final String REGEX_INVALID_MESSAGE_ID =
"validator.Regex_Invalid";
private String formatPatterns = null;

/** *//**
* 出錯(cuò)時(shí)的提示內(nèi)容名稱,例如郵編
*/
private String errorPatternDisplayName = null;

/** *//**
* 獲得樣式的配置文件
*/
private static final ResourceBundle bundle = ResourceBundle.getBundle(Const.BUNDLE_ROOT + ".RegexPattern");

/** *//**
* 資源配置文件中對(duì)應(yīng)的樣式名稱
*/
private String formatPatternName = null;
public RegexValidator()

{
super();
}
public RegexValidator(String formatPatternName)

{
setFormatPatternName(formatPatternName);
}
public void validate(FacesContext context, UIComponent component, Object toValidate)
throws ValidatorException

{
if(context == null || component == null)
throw new NullPointerException();
if(!(component instanceof UIOutput))
return;
if(formatPatterns == null || formatPatterns.length() == 0 || null == toValidate)
return;
String value = toValidate.toString();
Pattern p = Pattern.compile(this.formatPatterns);
Matcher m = p.matcher(value);
boolean b = m.matches();
if(!b)

{
FacesMessage errMsg = MessageFactory.getMessage(context,
this.REGEX_INVALID_MESSAGE_ID,

new Object[]
{errorPatternDisplayName});

throw new ValidatorException(errMsg);
}
}

public String getFormatPatternName()

{
return formatPatternName;
}

public void setFormatPatternName(String formatPatternName)

{
this.formatPatternName = formatPatternName;
this.errorPatternDisplayName = bundle.getString(formatPatternName);
this.formatPatterns = bundle.getString(formatPatternName+"_patterns");
}


}
它的Tag標(biāo)簽:
public class RegexValidatorTag extends ValidatorELTag


{
private String formatPatternName;
public RegexValidatorTag()

{
super();
}

/**//* (non-Javadoc)
* @see javax.faces.webapp.ValidatorELTag#createValidator()
*/
@Override
protected Validator createValidator() throws JspException

{
RegexValidator v = new RegexValidator();;
v.setFormatPatternName(formatPatternName);
return v;
}
public String getFormatPatternName()

{
return formatPatternName;
}
public void setFormatPatternName(String formatPatternName)

{
this.formatPatternName = formatPatternName;
}

}
這個(gè)驗(yàn)證標(biāo)簽接受一個(gè)名稱作為參數(shù),通過(guò)此名稱可以從相關(guān)配置文件中查找到相應(yīng)的正則表達(dá)式和其他一些配置信息。
但如果你使用這個(gè)驗(yàn)證器,你會(huì)發(fā)現(xiàn),每次都正確調(diào)用了,也都將參數(shù)傳進(jìn)去了,但是在調(diào)用validate方法的時(shí)候卻發(fā)現(xiàn)自定義的幾個(gè)驗(yàn)證器的屬性的值都為null。這是為什么呢?
因?yàn)槲覀兊谝淮握{(diào)用的時(shí)候初始化了一下,參數(shù)都進(jìn)去了,驗(yàn)證器也被實(shí)例化了,但是這個(gè)驗(yàn)證器卻是瞬時(shí)狀態(tài)的,剛被頁(yè)面實(shí)例化好就被釋放了。所以提交表單驗(yàn)證的時(shí)候會(huì)重新被初始化,但這時(shí)只是調(diào)用了默認(rèn)構(gòu)造函數(shù),沒(méi)有將我們的正則表達(dá)式樣式作為參數(shù)傳進(jìn)去。
如何保存驗(yàn)證器之前的狀態(tài)呢?或者說(shuō)如何讓驗(yàn)證器不是瞬時(shí)狀態(tài)呢。
這就需要實(shí)現(xiàn)StateHolder接口,并且實(shí)現(xiàn)幾個(gè)方法,讓JSF知道,這個(gè)驗(yàn)證器有自己的狀態(tài)需要保存。
新的代碼:
public class RegexValidator implements Validator, StateHolder


{

/** *//**
* The message identifier of the Message to be created if
* the validation fails.
*/
public static final String REGEX_INVALID_MESSAGE_ID =
"validator.Regex_Invalid";
private String formatPatterns = null;

/** *//**
* 出錯(cuò)時(shí)的提示內(nèi)容名稱,例如郵編
*/
private String errorPatternDisplayName = null;

/** *//**
* 獲得樣式的配置文件
*/
private static final ResourceBundle bundle = ResourceBundle.getBundle(Const.BUNDLE_ROOT + ".RegexPattern");

/** *//**
* 資源配置文件中對(duì)應(yīng)的樣式名稱
*/
private String formatPatternName = null;
public RegexValidator()

{
super();
}
public RegexValidator(String formatPatternName)

{
setFormatPatternName(formatPatternName);
}
public void validate(FacesContext context, UIComponent component, Object toValidate)
throws ValidatorException

{
if(context == null || component == null)
throw new NullPointerException();
if(!(component instanceof UIOutput))
return;
if(formatPatterns == null || formatPatterns.length() == 0 || null == toValidate)
return;
String value = toValidate.toString();
Pattern p = Pattern.compile(this.formatPatterns);
Matcher m = p.matcher(value);
boolean b = m.matches();
if(!b)

{
FacesMessage errMsg = MessageFactory.getMessage(context,
this.REGEX_INVALID_MESSAGE_ID,

new Object[]
{errorPatternDisplayName});

throw new ValidatorException(errMsg);
}
}

public String getFormatPatternName()

{
return formatPatternName;
}

public void setFormatPatternName(String formatPatternName)

{
this.formatPatternName = formatPatternName;
this.errorPatternDisplayName = bundle.getString(formatPatternName);
this.formatPatterns = bundle.getString(formatPatternName+"_patterns");
}

private boolean transientValue = false;
public void setTransient(boolean transientValue)

{
this.transientValue = transientValue;
}
public boolean isTransient()

{
return this.transientValue;
}

public void restoreState(FacesContext context, Object state)

{
Object values[] = (Object[]) state;
formatPatterns = (String) values[0];
errorPatternDisplayName = (String) values[1];
}

public Object saveState(FacesContext context)

{
Object[] values = new Object[2];
values[0] = formatPatterns;
values[1] = errorPatternDisplayName;
return values;
}

}
實(shí)現(xiàn)setTransient和isTransient兩個(gè)方法是為了標(biāo)明這個(gè)驗(yàn)證器不是瞬時(shí)狀態(tài),需要返回一個(gè)false。
實(shí)現(xiàn)saveState和restoreState兩個(gè)方法是為了保存和還原狀態(tài),大家可以看下代碼,saveState保存了當(dāng)前驗(yàn)證器需要的幾個(gè)屬性參數(shù),而restoreState將這些參數(shù)重新還原給了驗(yàn)證器,這樣,我們使用新代碼做驗(yàn)證的時(shí)候,就會(huì)發(fā)現(xiàn)它起作用了。
---------------------------------------------------------
專注移動(dòng)開(kāi)發(fā)
Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
posted on 2008-11-05 14:15
TiGERTiAN 閱讀(1662)
評(píng)論(2) 編輯 收藏 所屬分類(lèi):
Java 、
JSF