从数据库访问和使用.jsf文件

使我的webapplication能够使用存储在数据库中的JSF文件的最佳方法是什么? 我希望能够动态地(在运行时)创建新的JSF页面,无需重新部署应用程序即可使用。

换句话说:我想将我的JSF页面的大部分存储在数据库中,并希望JSF将数据库用作获取JSF文件的数据源。

我一直在想解决方案,并找到了一些可行的方法。 但是,我无法实现其中任何一个。

  1. 每当必须添加/删除新页面时:操纵类路径中的文件(例如,删除或添加文件到.war文件)
  2. 扩展web应用程序的类路径,以便它能够从运行时定义的位置(即/ tmp或直接使用数据库连接)获取文件
  3. 为JSF提供一种以另一种方式查找资源的方法(这似乎不可能?)

我的环境:

  • Java SE 6
  • Jetty作为servlet容器
  • Mojarra作为jsf实现

现在,我的问题:

是否有人可以让JSF在默认类路径以外的位置查找页面,最好是数据库?

非常感谢任何回应!

1:每当必须添加/删除新页面时:操纵类路径中的文件(例如,删除或添加文件到.war文件)

如果扩展WAR,这肯定是可能的。 我不确定Jetty,但它适用于Tomcat 7和Glassfish 3上的Mojarra 2.x。只需将文件写入扩展的WAR文件夹,通常的Java IO方式就足够了。

File file = new File(servletContext.getRealPath("/foo.xhtml")); if (!file.exists()) { OutputStream output = new FileOutputStream(file); try { output.write(bytes); // Can be bytes from DB. } finally { output.close(); } } 

这需要在FacesServlet启动之前执行。 Filter是一个完美的地方。 另见相关答案:

  • 如何创建动态JSF表单字段

2:扩展web应用程序的类路径,以便能够从运行时定义的位置(即/ tmp或直接使用数据库连接)获取文件

您可以将Facelets文件打包到JAR文件中,并将其放在类路径中,并提供Facelets ResourceResolver ,当WAR中没有找到匹配项时,它会提供来自JAR的文件。 您可以在以下答案中找到完整的代码示例:

  • 如何在多次战争之间共享一个jsf错误页面
  • 如何创建模块化JSF 2.0应用程序?

3:为JSF提供一种以另一种方式查找资源的方法(这似乎不可能?)

您在自定义ResourceResolver有足够的游戏空间。

好问题。 BalusC的答案是 – 一如既往 – 完整正确。

但是,如果您的目的是创建一个动态构建gui的应用程序,那么有一种方法可以更好地为您服务(取决于您真正想要实现的目标)。

JSF视图类似于Swing表单 – 它们只是粘在一起的一堆JavaBeans(tm)。 最大的区别在于,当字段绑定到EL表达式时,不使用标准访问器,而是使用特殊方法(setValueExpression)。

这意味着您可以以纯编程方式从对象构建GUI(具体类可以在javax.faces.component.html中找到),然后使用绑定属性在页面上显示它。 就像是:

    

然后在托管的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对象
  • 创建一个接收表单id的托管bean,从数据库中获取相关表单,从中构建一个JSF面板并将其作为属性呈现,准备绑定。

这样,您可以只使用一个带有单个标记的静态xhtml,并使用它来呈现任意数量的动态表单。

正如我所说,这种方法可能比仅存储文件更好,但不一定。 如果你只是想省去重新部署的麻烦,这是一个巨大的过度杀伤(然后,你不需要重新部署JSF应用程序只是为了改变forms)。 另一方面,如果您的目标是拥有类似用户定义和编辑的表单,拥有一个好的对象模型并以适当的方式存储它可能是一个好主意。

前面的颠簸将是:

  • 导航(也许自定义导航处理程序就足够了?)
  • 生成普通html的问题
  • 可能是视图范围表单生命周期的一些问题