部分刷新重复控制和托管 Bean 运行 问题

Partial Refresh Repeat Control and Managed Bean running issue

我将 xPage 中的一个面板设置为在计时器上进行部分刷新。如时间字段所示,部分刷新面板外的页面不会刷新,但是,刷新面板外的重复控件中的托管 Bean 会在每个计时器事件上初始化。如果我用 ComputedField 替换 Repeat Control,则 Bean 不会 运行。这会在服务器上造成不必要的负载,因为托管 Bean 会收集大量数据。除了计时器之外,按钮事件也存在问题。

以下是我的测试页。感谢任何帮助。

<xp:this.beforeRenderResponse><![CDATA[#{javascript:var time = new Date(); 
 var timeString=     ("0" + time.getHours()).slice(-2)   + ":" + 
("0" + time.getMinutes()).slice(-2) + ":" + 
("0" + time.getSeconds()).slice(-2);
viewScope.put("time",timeString)}]]></xp:this.beforeRenderResponse>

<xp:scriptBlock
id="scriptBlockRefresh">
<xp:this.value>
        <![CDATA[
            setInterval(function() 
            {XSP.partialRefreshGet("#{id:refreshPanel}", {})},
             10 * 1000);]]>
</xp:this.value>
</xp:scriptBlock>

<xp:panel  id="refreshPanel">
    <xp:text escape="true" value="#{classABean.classAText}"></xp:text>
    <xp:text escape="true" value="#{viewScope.time}"></xp:text>
</xp:panel>

<xp:panel id="restOfPagePanel">
<xp:text escape="true" id="computedField4" value="#{classBBean.classBText}"></xp:text>
<xp:repeat id="repeat1" rows="30" value="#{classBBean.classBText}" var="rowData">
    <xp:text escape="true"  value="#{rowData}"></xp:text>
</xp:repeat>
<xp:text escape="true" value="#{viewScope.time}"></xp:text>
</xp:panel>

测试托管 Bean

import java.io.Serializable;
public class ClassA implements Serializable{
private static final long serialVersionUID = 1L;
private String classAText;
public String getClassAText() {
    System.out.println("Running Class A");
    classAText = "I am Class A";
    return classAText;}

B 类也是如此

FacesConfig

<managed-bean>
<managed-bean-name>classABean</managed-bean-name>
<managed-bean-class>uk.networkconnect.wallboardutils.ClassA</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>

 <managed-bean>
<managed-bean-name>classBBean</managed-bean-name>
<managed-bean-class>uk.networkconnect.wallboardutils.ClassB</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>

用于测试的按钮代码。

 <xp:button value="Refresh Panel A" id="button1">
<xp:eventHandler event="onclick" submit="false" >
    <xp:this.script><![CDATA[XSP.partialRefreshGet("#{id:refreshPanel}",{})
            ]]></xp:this.script>
</xp:eventHandler>
</xp:button>

您的代码应该可以工作,但有一个问题 - 我不能说您是否已经处理好它。事实上,使用 JSF 时,您必须确保仅在第一次加载数据,并对后续调用采取防御措施。事实上,引擎可能会在生命周期中两次调用相同的方法。

以您提供的模型为例,代码应如下所示:

public class ClassA implements Serializable {

    private static final long serialVersionUID = 1L;

    private String text;

    public String getClassText() {
        if (text == null) {
            String name = getClass().getName();

            System.out.println("Running class " + name);

            text = "I am class " + name;
        }

        return text;
    }
}

基本上,只有在计算结果为 null 时才设置文本。设置变量后,无论引擎对该方法进行多少次调用,代码都不会再进入块内。

XPage不需要修改。

<xp:scriptBlock
    value="
        setInterval(function() {
            XSP.partialRefreshGet('#{id:refreshPanel}');
        }, 10 * 1000)" />

<xp:panel id="refreshPanel" style="background-color: red">
    <xp:text escape="true" value="#{a.classText}" />
    <xp:text escape="true" value="#{viewScope.time}" />
</xp:panel>

<xp:panel id="restOfPagePanel" style="background-color: grey">
    <xp:text escape="true" id="computedField4" value="#{b.classText}" />

    <xp:repeat id="repeat1" rows="30" value="#{b.classText}"
        var="rowData">
        <xp:text escape="true" value="#{rowData}" />
    </xp:repeat>

    <xp:text escape="true" value="#{viewScope.time}" />
</xp:panel>

<xp:button value="Label" id="button1">
    <xp:eventHandler event="onclick" submit="true"
        execMode="partial" refreshMode="partial" refreshId="refreshPanel" />
</xp:button>

刷新到浏览器的内容与在服务器上处理的内容不同。 refreshId 涵盖 XPage 的哪些区域应该 HTML 传回给浏览器。但是 HTML 可能会有所不同,具体取决于用户在页面其他地方所做的更新。这就是 execId 的目的,它决定了 server 应该处理的区域。 exec 区组件的值 属性 仍然需要在生命周期中计算。如果您的 bean 的 getter 每次都只是 运行 代码,正如 Shillem 所说,延迟加载(如果为 null,则设置该值,否则使用该值)是一个很好的方法。与 Java.

中的 SSJS 方法和标准相比,这是一个显着的优势

如果 bean 中的值永远不变,另一种选择是将重复控件的值 属性 设置为在页面加载时计算 - ${b.classText} 而不是 #{b.classText}

重复控件还有其他设置,也可以设置为处理不变的内容。 repeatControls="true" 设置页面加载时重复的值,并在组件树中创建行组件的副本。默认情况下,将有一个抽象的组件行,每次刷新都会对其进行迭代。 removeRepeat="true" 将在所有组件集都加载到组件树中后删除重复控件。