JSF / Richfaces迭代中的迭代范围变量?

时间:2011-01-27 13:44:11

标签: optimization jsf richfaces seam

好吧,我认为这应该是一个有趣的。我想最小化迭代内我的Seam组件的调用次数。我使用的是Seam 2.2.1.CR1,Richfaces 3.3.3.Final,JSF 1.2和Facelets。

请查看以下Facelet代码段:

<rich:datatable value="#{myBean.products}" var="prod">

<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
    #{prod.name}
</rich:column>

<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
    #{prod.number}
</rich:column>

...

<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
    #{prod.somethingElse1}
</rich:column>

<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
    #{prod.somethingElse2}
</rich:column>

...

<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
    #{prod.somethingElse3}
</rich:column>

</rich:datatable>

在上面的代码中,我通过计算EL表达式来计算一个属性(这里是rowspan,但这并不重要,它可以是任何属性或值,所以请不要关注它)。如您所见,计算该值的方法将当前prod作为参数。

我在rowspan Seam组件中进行了内部优化,并在HashMap中保留了所有已计算的产品值。因此,当在第二个rich:column计算EL表达式时,rowspan首先在HashMap中查找已经计算的值,并返回该值,而不是重新计算。

虽然再次重新计算更好,但我仍然需要调用Seam组件。有没有办法以某种方式只调用一次Seam组件,并以某种方式保留当前迭代的计算值?

类似于Java,就是在每次迭代时在循环内定义一个变量,并在整个迭代过程中重用它。

注意:我已经进行了其他面向Seam的优化,例如@BypassInterceptors,Seam组件位于EVENT范围内,因此不会发生分层查找等。

1 个答案:

答案 0 :(得分:1)

  

有没有办法以某种方式只调用一次Seam组件,并以某种方式保留当前迭代的计算值?

当然,理论上。

但我不确定我完全理解你的问题。你在谈论哪个缝线组件? rowspan

如果是这样的话,那么是的,每当你调用它时它会被调用,这是有道理的。您正在遍历dataTable,并为您调用它的每一行。

如果不了解有关您要做的事情的更多细节,很难提出答案。代码慢吗?这就是你需要进一步优化的原因吗?

<强>更新

试试这个,虽然我不确定它是否有效

<rich:dataTable value="#{myBean.products}" var="prod">
   <ui:param name="myrowspan" value="#{rowspan.calcHomePageProductRowspan(prod)}"/>
   <rich:column rowspan="#{myrowspan}">
     #{prod.name}
   </rich:column>
</rich:dataTable>

第二次更新

因此,如果您不将代码更改为@ Out,@ Factory,@ Unwrap或类似代码,则每次运行时都会对其进行评估。这就是JSF的工作原理。
这就是为什么他们说你应该在你的getter中这样做,因为JSF会为每个JSF阶段调用它。

public List<Foo> getFoo() {
  if(this.field != null) { 
    field = (List)entityManager.createQuery("from Foo").getResultList();
  } 
  return this.field; 
}

如果您没有缓存列表并检查null,那么JSF会在每个阶段和数据表中的每一行中访问数据库。

因此,这只是你必须忍受的事情。