【问题标题】:JSF ui:fragment rendered performanceJSF ui:fragment 渲染性能
【发布时间】:2011-08-26 07:33:34
【问题描述】:

我有一组 jsf 组件,它们是从一组 excel 文件中静态生成的(它们由业务人员更新)。每个生成的文件代表一个业务对象,其数据略有不同,并且都属于同一个类。

为了动态渲染,我找到的唯一解决方案是设置一堆ui:fragment 并在运行时调度到正确的组件:

<!-- IMPLEMENTATION -->          
<composite:implementation> 
    <ui:fragment rendered="#{cc.attrs.type eq 'cartcred'}">
        <limites:limites-cartcred  limite="#{cc.attrs.limite}"/>
    </ui:fragment>
    <ui:fragment rendered="#{cc.attrs.type eq 'cdcp'}">
        <limites:limites-cdcp limite="#{cc.attrs.limite}"/>
    </ui:fragment>
    <ui:fragment rendered="#{cc.attrs.type eq 'cheqpredatado'}">
        <limites:limites-cheqpredatado limite="#{cc.attrs.limite}"/>
    </ui:fragment>
    <ui:fragment rendered="#{cc.attrs.type eq 'confirming'}">
        <limites:limites-confirming limite="#{cc.attrs.limite}"/>
    </ui:fragment>
   <!-- many more lines -->
   <!-- many more lines -->
   <!-- many more lines -->
    <ui:fragment rendered="#{cc.attrs.type eq 'contacorr'}">
        <limites:limites-contacorr limite="#{cc.attrs.limite}"/>
    </ui:fragment>

但我发现它的性能很糟糕。我坚持认为 JSF 只会渲染单个组件,但似乎它正在渲染所有它们并在运行时“隐藏”其他组件。

有没有更有效的方法来实现我的目标?我想根据有关业务类的运行时信息(很像 if-then-else)呈现单个组件,但我只能确定要在运行时呈现的组件是什么。


说明: 发生的情况是limites:limites* 引用的每个组件都是一个巨大的复杂页面,其中包含许多其他组件。在运行时,名为 type' will decide what component to render. But my tests show that if I only render one component, but leave the otherui:fragments 的参数(即使知道它们不会被渲染),它的渲染速度会比我移除组件时慢得多。

所以如果我的页面是这样的:

<composite:interface>
    <composite:attribute name="type" required="true" />
    <composite:attribute name="limite" required="true" />
</composite:interface>         
<composite:implementation> 
    <ui:fragment rendered="#{cc.attrs.type eq 'cartcred'}">
        <limites:limites-cartcred  limite="#{cc.attrs.limite}"/>
    </ui:fragment>
</composite:implementation>

即使参数相同,它的渲染速度也会比初始版本快很多(大约 10 倍)。我怀疑 JSF 会创建整个组件树,并且只有在运行时才会决定(取决于提供的参数)是否会相互渲染。


编辑

差不多了。我只需要包含我的复合组件 动态。我尝试评估一个 ELExpression,但没有奏效。我需要的是一种在组件创建中访问当前范围的方法,并使用它来生成正确的文件名:

//obviously, ELExpressions don't work here
Resource resource = application.getResourceHandler().createResource("file-#{varStatus.loop}.xhtml", "components/dynamicfaces");

【问题讨论】:

    标签: java performance jsf components


    【解决方案1】:

    一种可能是使用binding 属性来访问容器 从托管 bean 内部构建组件树,并从 java端。这样你就可以只包含需要的组件,不需要 组件根本不会被评估。

    JSP:

    <h:panelGroup binding="#{managedBean.panel}"/>
    

    托管 Bean:

    private UIPanel panel;
    
    // getter and setter
    
    
    // Action method, might also work in a @PostConstruct
    public String showComponent() {
        if (showComponent1) {
            UIOutput component1 = new HtmlOutputText();
            component1.setValue("Hello world!");
    
            getPanel().getChildren().add(component1);
        }
    
        return "viewId";
    }
    

    我还没有将它与复合组件一起使用,this question 似乎有更多细节和一个example application 关于将它与复合组件一起使用。

    编辑:关于您的编辑,您还可以像这样评估托管 bean 中的 EL 表达式:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ELContext elContext = facesContext.getELContext();
    ExpressionFactory exprFactory = facesContext.getApplication().getExpressionFactory();
    ValueExpression expr = exprFactory.createValueExpression(elContext, "#{expr}", String.class);
    String value = (String) expr.getValue(elContext);
    

    【讨论】:

    • 这行得通,虽然它没有解决我的特定问题,但我认为这是一个正确的答案。
    • @Miguel,谢谢,请参阅我的更新以获取有关如何在 java 代码中使用 el 表达式的示例。
    • 呵呵,谢谢,我已经尝试在 bean 上评估 ELExpression,但由于某种原因它没有正确评估;它可能无法解析我在调用 setComponent 时尝试访问的变量。有时你只需要继续前进。
    【解决方案2】:

    是的,rendered 属性在渲染期间进行评估,而不是在构建期间。是的,这是比较可怕的。想象一个这样的条件需要 1 毫秒,评估其中的 10 个总共需要 10 倍的时间,即 10 毫秒。如果您在分页表中依次有十个这样的组件,则 web 应用程序加载时间将多花 0.1 秒。眨眼时间长了大约一倍。但是,如果您不分页和/或使用 MSIE 作为参考浏览器,则需要更长的时间。您是否在适当的浏览器中对数据进行分页和测试?

    您可以做的最好的事情是将&lt;ui:fragment&gt; 替换为&lt;c:if&gt;/&lt;c:choose&gt; 之类的JSTL 标签,以便它在构建期间而不是在渲染期间进行评估。或者,或者,在支持 bean 构造函数中而不是在视图中构建组件树。

    【讨论】:

    • 我无法分页,因为生成的页面正用于打印目的。由于上面的页面也是从 xls 元数据生成的,所以我真正想知道的是,如果渲染条件评估为 true,我怎样才能确保 fragment 内容仅被“处理”。另外,我的参考浏览器是MSIE6。我可能应该再找一份工作......
    • MSIE 的 HTML 表格渲染性能极差。我怀疑你的问题是否真的是由 EL 引起的。它非常快。尝试在其他浏览器中测试相同的页面,例如Firefox 或 Chrome - 仅供您自己参考。
    • JSTL 没有按我的预期工作。我的真实案例比我发布的示例更做作,但无论如何谢谢。
    猜你喜欢
    • 2012-01-31
    • 1970-01-01
    • 2011-12-08
    • 2011-09-09
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    相关资源
    最近更新 更多