[英]JSF ui:fragment rendered performance
我有一组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*
引用的每个组件limites:limites*
是一个包含许多其他组件的巨大复杂页面。 在运行时,名为type' will decide what component to render. But my tests show that if I only render one component, but leave the other
的参数type' will decide what component to render. But my tests show that if I only render one component, but leave the other
type' will decide what component to render. But my tests show that if I only render one component, but leave the other
UI: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");
是的, rendered
属性在渲染时评估,而不是在构建时。 是的,这是相对可怕的。 想象一下这样一个条件花费1毫秒,评估其中十个将总共花费10倍,10毫秒。 如果您在分页表中依次拥有10个组件,则webapp加载时间将延长0.1秒。 关于一个眨眼更长。 但是如果你没有分页和/或使用MSIE作为参考浏览器,那么它需要更长的时间。 您是否在适当的浏览器中对数据进行分页并进行测试?
最好的方法是用<c:if>
/ <c:choose>
等JSTL标签替换<ui:fragment>
,使其在构建期间而不是在渲染时评估。 或者,或者,在支持bean构造函数中而不是在视图中构建组件树。
一种可能性是使用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";
}
我还没有将它与复合组件一起使用, 这个问题似乎有更多的细节和一个关于将它与复合组件一起使用的示例应用程序 。
编辑:关于您的编辑,您还可以在托管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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.