完整的教材:
上一节教材中,我们的项目已经完成了一个HelloWorld示例。在讲保存状态与恢复状态之前,我先做一个错误的示例,以便让大家了解什么保存状态与恢复状态。
开发环境:
- Windows 7
- IntelliJ IDEA 12.1.2
- jboss-6.1.0.Final
- JSF 1.2
修改项目中的helloWorld.xhtml,这个例子没有实际的意义,只是期待点击“刷新”按钮的时候,重新刷新一下panelGroup区域。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:ida="http://www.regaltec.com/ida40" xmlns:h="http://java.sun.com/jsf/html" xmlns:a4j="http://richfaces.org/a4j">
<f:view>
<head>
<title>Hello World</title>
</head>
<body>
<a4j:form>
<a4j:commandButton value="刷新" reRender="out" />
</a4j:form>
<h:panelGroup id="out">
<ida:helloWorld name="世界" />
</h:panelGroup>
</body>
</f:view>
</html>
如果你启动jboss并打开这个示例,你会发现点击按钮后“你好世界”不显示了,跟期望只是刷新一下有出入。其实这个bug就跟保存状态、恢复状态有关系了。
使用JSF的同僚都知道,JSF有6个生命周期,在恢复视图阶段,倘若先前曾经调用过saveState()方法来存储状态信息,则在此阶段调用组件的restoreState()方法。明白了这个道理,我们重构代码就容易了,整个项目中,只需要重构UIHelloWorld这个类就可以了,具体就是重载UIHelloWorld组件的saveState和restoreState方法,完整的代码如下:
public class UIHelloWorld extends UIOutput {
private String name;
public String getName() {
if (StringUtils.isNotBlank(this.name)) {
return name;
}
ValueExpression _ve = getValueExpression("name");
if (_ve != null) {
return (String)_ve.getValue(getFacesContext().getELContext());
} else {
return null;
}
}
public void setName(String name) {
this.name = name;
}
@Override
public String getFamily() {
return "com.regaltec.faces.HelloWorld";
}
@Override
public Object saveState(FacesContext context) {
Object values[] = new Object[2];
values[0] = super.saveState(context);
values[1] = name;
return values;
}
@Override
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
name = (String) values[1];
}
}
注意:1、需要保存的状态次序与恢复状态的次序要保持一致;2、一般情况都不能丢掉父类的状态。
现在再启动jboss运行示例,helloWold.jsf页面点击按钮能正常工作了。