【问题标题】:Reducing the JSF component tree/state by an alternate approach. Is it Okay?通过替代方法减少 JSF 组件树/状态。可以吗?
【发布时间】:2012-03-31 20:28:03
【问题描述】:

不幸的是,我错误地将 JSF 选择用于面向 Internet 的高流量应用程序,现在我想知道如何提高这个 JSF webapp 的可扩展性。

我有一个 JSF 页面,其中显示了大量项目,每个项目都可以评论。 为了减少状态并提高性能,我正在尝试减少页面上forms /commandButtons 的数量。

1. 通过什么方式可以减少JSF的组件树/状态?纯 html 元素(混合在 jsf 标签之间)是否也构成组件树的一部分?我不知道组件状态保存对我的应用程序有什么帮助,因为我在设计我的应用程序时一直遵循简单的请求/响应模型,(可能只是对 JSF 的内部需求有帮助)!?

2. 我正在考虑一种方法,而不是为每个项目创建一个单独的<h:form>(每个都有一个单独的commandButton),如下所示,

(通常的方法)

<h:form> <!-- for each item a separately -->
      <h:outputText value="Add comment"/>
      <h:inputTextarea value="#{itemController.comment}"  required="true"/>

      <p:commandButton actionListener="#{itemController.addUserComment(123)}" value="Add" />
</h:form>

(替代方法)

我试图通过为所有项目放置一个 remoteCommand 并将所需的参数传递给这个 remoteCommand 来使上述情况变得更好。

<form>
   <input id="item1_comment"/>
   <button onclick="addComment(123, 'item1_comment');"/>  
</form>    

<script type="text/javascript">
    function addComment(itemId, id) {
        $('#comment_in').attr('value', $('#'+id).attr('value'));
        $('#forItem_in').attr('value', itemId);
        addComment_RC(); // call remoteCommand to show the content in dialog
    }
</script>

<h:form prependId="false" >  <!-- for all items, just single remoteCOmmand -->
    <h:inputHidden id="comment_in" value="#{itemController.comment}"/>
    <h:inputHidden id="forItem_in" value="#{itemController.forItem}"/>
    <p:remoteCommand name="addComment_RC" process="@form" actionListener="#{itemController.addComment()}" />
</h:form>

这样做更好吗(或者这种方法有什么问题)?

【问题讨论】:

  • 如果您使用 ajax,为什么不对所有元素使用一种形式?
  • 这会减少状态吗? & 将不应该一次性处理的所有数据保存在一个表单中是否更有意义?
  • 是的,它会降低复杂性,您可以使用f:ajaxexecute 属性指示jsf 仅处理您感兴趣的表单元素
  • 是的,这种替代方法的复杂性可以避免,但由于命令按钮的数量保持不变,如何减少状态?
  • 我强烈建议您对应用程序进行堆转储,并检查它以确定究竟是什么在使用内存。如果您跳过该部分,您可能正在优化程序的错误部分。

标签: java jsf jsf-2 primefaces


【解决方案1】:

你描述的情况下的性能问题通常是由大量的EL表达式引起的,给服务器带来了负担。

解决此问题的一种方法是在客户端计算 cmets,然后将它们一次全部传递给服务器。从而减少评论EL表达式的数量到一个或没有,并且只使用一个按钮。

将所有元素放在一个表单中。 cmets 字段未绑定。

  <h:form>

       // first element 
       <h:outputText value=#{first element}
       // first comment 
       <h:inputTextarea id="comment1"/> <-- notice there is no EL expression 
                                            But we use a unique id for each comment 

       // second element 
       <h:outputText value=#{second element}
       // second comment 
       <h:inputTextarea id="comment2"/> 
       .
       .
       .



</h:form>

从这里你可以

1. 在任何评论字段中的每个模糊事件之后,ajax 服务器并作为参数传递 commentid 进行 ajax 调用的评论。在服务器上相应地更新您的模型

或者你也可以在客户端收集所有的cmet,一次性发送到服务器。

2. 当用户按下提交按钮时,调用一个 js 函数将所有 cmets 聚合到一个结构中,您将能够在服务器端轻松解析 (即"{c1,comment a};{c2,comment b};{c5=,comment e}...")。 将该字符串传递给服务器,对其进行解析并相应地更新您的模型。

3.在任何评论字段中的每个模糊事件之后,调用一个更新隐藏字段的js函数。

<h:inputHidden value="{myClass.allComments}" />

当用户提交表单时,解析 allComments 并相应地更新您的模型。

编辑:

为了解决一般性能问题,我从一篇文章中添加了一些建议,我发现该文章对 speed up part 1Speed up part 2 很有帮助。

希望对你有帮助

顺便说一句,我会推荐第一种方法而不是最后两种。

【讨论】:

  • 我猜你在第 1 点的建议与我的替代方法(如上所述)几乎相似,唯一的区别是我使用的是非 jsf html button,而不是模糊事件,触发提交到隐藏输入然后触发服务器上的更新。
  • @user 是的,我采用了相同的方法,并实现了以下原则 1.使用一种形式(在这种情况下不需要更多,只会使事情复杂化) 2.重要 - 使用 而不是
  • 谢谢,您能否澄清一下使用 而不是
  • @user 你是对的。在某些情况下可能会导致问题。例如使用 jsf coderanch.com/t/545977/JSF/java/JSF-div-tags (stackoverflow.com/questions/951593/…) 创建 div 并将库 div 用作战斧。一种方法是始终让 jsf 决定如何呈现元素。你有大量的项目要渲染,所以我会从使用标记的 div 和输入元素开始,只有在检查功能后才考虑删除它们
猜你喜欢
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 2020-08-26
  • 2021-12-27
  • 2021-10-22
相关资源
最近更新 更多