好问题。 BalusC 的答案是 - 一如既往 - 完整且正确。
但是,如果您的目的是创建一个动态构建 gui 的应用程序,那么有一种方法可能会更好地为您服务(取决于您真正想要实现的目标)。
JSF 视图类似于 Swing 表单——它们只是一堆粘合在一起的 JavaBeans(tm)。最大的区别在于,当一个字段绑定到一个 EL 表达式时,您不使用标准访问器,而是使用特殊方法(setValueExpression)。
这意味着您可以以纯编程方式从对象(具体类可以在 javax.faces.component.html 中找到)构建您的 GUI,然后使用绑定属性在页面上显示它。比如:
<h:form>
<h:panelGrid binding="#{formBuilder.component}"/>
</h:form>
然后在托管的formBuilder bean中:
@PostConstruct
public void init() {
HtmlInputText hit = new HtmlInputText();
// properties are easy:
hol.setStyle("border: 2px solid red");
// binding is a bit harder:
hit.setValueExpression("value", expression("#{test.counter}", String.class));
HtmlOutcomeTargetLink hol = new HtmlOutcomeTargetLink();
hol.setValue("link leading to another view");
hol.setOutcome("whatever");
component = new UIPanel();
component.getChildren().add(hit);
component.getChildren().add(hol);
}
private ValueExpression expression(String s, Class c){
return FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
FacesContext.getCurrentInstance().getELContext(),
s, c
);
}
上面的示例构建了一个静态面板,但可以:
- 为您的 GUI 创建一个对象模型
- 将模型映射到数据库(使用 hibernate 或其他 orm)
- 编写某种适配器或桥接器以从您的对象模型构建 JSF 对象
- 制作一个托管 bean,它接收表单 ID,从数据库中获取相关表单,从中构建一个 JSF 面板并将其呈现为一个属性,准备好被绑定。
这样你就可以只拥有一个带有单个标签的静态 xhtml,并使用它来呈现任意数量的动态表单。
正如我所说,这种方法可能比仅存储文件更好,但不一定。如果您只是想省去重新部署的麻烦,这是一个巨大的矫枉过正(再说一遍,您不需要仅仅为了更改表单而重新部署 JSF 应用程序)。另一方面,如果您的目标是拥有用户定义和编辑的表单,那么拥有一个良好的对象模型并以适当的方式存储它可能是一个好主意。
前面的颠簸将是:
- 导航(也许自定义导航处理程序就足够了?)
- 生成纯 html 的问题
- 视图范围表单的生命周期可能存在一些问题