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

发布于 2024-11-13 05:59:38 字数 562 浏览 1 评论 0原文

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

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

我思考了很长时间的解决方案并找到了一些可能的方法。然而,我还没有能够实现它们中的任何一个。

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

我的环境:

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

现在,我的问题:

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

非常感谢您的任何回复!

What is the best way to enable my webapplication to use JSF files stored in the database?
I'd like to be able to dynamically (during runtime) create new JSF pages which will be made available without having to redeploy the application.

So in other words: I would like to store the bigger part of my JSF pages in the database and would like JSF to use the database as a datasource for getting JSF files.

I've thought long about a solution and found some possible ways. However, I haven't been able to implement either of them.

  1. Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)
  2. Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)
  3. Provide JSF with a way to find resources another way ( this doesn't seem possible? )

My environment:

  • Java SE 6
  • Jetty as servlet container
  • Mojarra as jsf implementation

Now, my question:

Is it possible for someone to let JSF find pages at a location other than the default classpath, preferably the database?

Any response is greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨与橙与城 2024-11-20 05:59:38

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

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

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 是一个完美的地方。另请参阅此相关答案:


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

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


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

在自定义 ResourceResolver 中您有足够的发挥空间。

1: Whenever a new page has to be added/removed: manipulate the files in the classpath (e.g. remove or add a file to the .war file)

This is definitely possible if the WAR is expanded. I am not sure about Jetty, but it works for me with Mojarra 2.x on Tomcat 7 and Glassfish 3. Just writing the file to the expanded WAR folder the usual Java IO way suffices.

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();
    }
}

This needs to be executed before the FacesServlet kicks in. A Filter is a perfect place. See also this related answer:


2: Extending the classpath of the webapplication so it will be able to get files from an at runtime defined location (i.e. /tmp or directly using a database connection)

You can package Facelets files in a JAR file and put it in the classpath and provide a Facelets ResourceResolver which serves the files from the JAR on when no match is found in WAR. You can find complete code examples in the following answers:


3: Provide JSF with a way to find resources another way ( this doesn't seem possible? )

You've plenty of play room in the custom ResourceResolver.

眼趣 2024-11-20 05:59:38

好问题。 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 的问题
  • 可能是视图范围表单的生命周期问题

Nice question. BalusC's answer is - as always - complete and right.

However, if your point is to create an application where gui is built dynamically, there is a way that might serve you better (depending on what you really want to achieve).

JSF views are similar to Swing forms - they are just a bunch of JavaBeans(tm) glued together. The big difference is that when a field is bound to an EL expression, you do not use standard accessors, but rather a special method (setValueExpression).

This means you can build your GUI from objects (the concrete classes can be found in javax.faces.component.html) in a pure programmatic way and then use binding attribute to show it on page. Something like:

<h:form>
    <h:panelGrid binding="#{formBuilder.component}"/>
</h:form>

And then in the managed 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
    );
}

The example above builds a static panel, but it would be possible to:

  • create an object model of your GUI
  • map the model to database (with hibernate or another orm)
  • write some kind of adapter or bridge to build JSF objects from your object model
  • make a managed bean that receives the form id, grabs the relevant form from database, builds a JSF panel out of it and presents it as a property, ready to be bound.

This way you could have just one static xhtml with a single tag and use it to present any number of dynamic forms.

As I said, this method could be better than just storing files, but not necessarily. If you just want to save yourself the hassle of redeployment, this is a huge overkill (then again, you do NOT need to redeploy JSF applications just to change forms). If on the other hand your goal is to have something like user-defined and edited forms, having a good object model and storing it in a proper way could be a good idea.

The bumps ahead would be:

  • navigation (perhaps a custom navigation handler would suffice?)
  • problems with generating plain html
  • possibly some problems with lifecycle of view scoped forms
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文