有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

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

我想了很久,找到了一些可能的解决办法。然而,我没有能够实现它们中的任何一个

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

我的环境:

  • JavaSE6
  • Jetty作为servlet容器
  • Mojara作为jsf实现

现在,我的问题是:

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

非常感谢您的回复


共 (2) 个答案

  1. # 1 楼答案

    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)

    如果战争扩大,这绝对是可能的。我不确定Jetty,但它对我来说适用于Mojarra 2。Tomcat 7和Glassfish 3上的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开始之前执行。AFilter是个完美的地方。另请参见以下相关答案:


    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)

    您可以将Facelets文件打包到JAR文件中,并将其放在类路径中,并提供一个Facelets ^{},当在WAR中找不到匹配项时,它将从JAR提供文件。您可以在以下答案中找到完整的代码示例:


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

    你在定制的ResourceResolver中有足够的游戏空间

  2. # 2 楼答案

    问得好。巴卢斯的回答一如既往地完整而正确

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

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

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

    <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的问题
    • 视图范围表单的生命周期可能存在一些问题