簡體   English   中英

PreRenderView逐步調用每個回發

[英]PreRenderView incrementally called on every postback

我對f:event type="preRenderView"的執行順序和執行次數有f:event type="preRenderView"

在這里我的搜索,我發現從BalusC在通常的回答這個這個職位涉及到我的問題-它仍然留下了兩個問題要問:

  1. 當我在模板文件中放置一個f:event type="preRenderView" (用於管理常見任務,例如關於適用於我所有視圖的用戶狀態的檢查)和每個視圖中的另一個f:event type="preRenderView" (用於處理)查看特定的初始化),我想知道為什么視圖中的偵聽器方法在模板之前被調用。

  2. 當我按照建議ui:define后整個<f:metadata><f:event [..] /></f:metadata> ,從登錄頁面重定向到該頁面后會調用兩次,但是當我在ui:composition之后把它放高一級ui:composition它只被調用一次。


更新:示例

以下示例演示了上述行為:

這是模板文件template_test.xhtml ,包含preRenderView事件的偵聽器,在所有視圖的處理程序中調用公共方法:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="de" lang="de" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <link rel="stylesheet" type="text/css" href="../resources/css/style.css" />
</h:head>
<h:body>
    <f:event type="preRenderView" listener="#{testHandler.initCommon()}" />
    <div id="content">
        <ui:insert name="content" />
    </div>
</h:body>
</html>

這是視圖文件test.xhtml ,還包含一個preRenderView事件的監聽器,用於調用處理程序中的視圖特定方法,以及通過處理程序方法重定向的命令按鈕:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    template="template_test.xhtml">
    <ui:define name="content">
        <f:metadata>
            <f:event type="preRenderView"
                listener="#{testHandler.initIndividual()}"></f:event>
        </f:metadata>
        <h:form>
            <h:commandButton value="Redirect" action="#{testHandler.redirect()}" />
        </h:form>
    </ui:define>
</ui:composition>

這是包含3種方法的處理程序類TestHandler.java

package test;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class TestHandler implements Serializable {

    private static final long serialVersionUID = -2785693292020668741L;

    public void initCommon() {
        System.out.println("Common init called.");
    }

    public void initIndividual() {
        System.out.println("Init for individual page called.");
    }

    public String redirect() {
        return "test/test.xhtml?faces-redirect=true";
    }
}

現在,這是我在tomcat日志中查看請求測試頁面時看到的內容:

Init for individual page called.
Common init called.
Init for individual page called.

這顯示沒有。 1,視圖中的事件處理程序在模板之前調用,而不是。 2,從視圖中調用事件處理程序兩次。

它還顯示了第三點(這就是為什么我包含一個重定向到同一頁面的按鈕的原因),顯示如果通過重定向請求頁面會發生什么 - 單個頁面被調用的次數更多:

Init for individual page called.
Common init called.
Init for individual page called.
Init for individual page called.

兩個都沒有。 通過將整個元數據部分放在ui:define之上或者通過向視圖的元數據部分添加虛擬參數(可以不包含在URL中),可以防止2和3:

<f:metadata>
    <f:viewParam name="dummyToDenySecondRedirect" />
    <f:event type="preRenderView"
        listener="#{testHandler.initIndividual()}"></f:event>
</f:metadata>

有人能告訴我這些案件的原因嗎?

我可以重現它。 這是由於/WEB-INF/beans.xml的存在以及CDI的隱含引起的。 當您在保留beans.xml文件的同時切換回標准JSF注釋時,甚至會發生這種情況。 這已經作為問題1771問題2162報告 然而,由於缺少具體的WAR文件來重現問題和低票,Mojarra開發人員並沒有費心去仔細研究它。

我再次將其作為問題2719報告 可以用一個較小的例子重現該問題:

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    <f:metadata>
        <f:event type="preRenderView" listener="#{bean.preRenderView}" />
    </f:metadata>
    <h:head>
        <title>preRenderView fail</title>
    </h:head>
    <h:body>
        <p>On initial request, you'll see the listener being invoked twice instead of only once.</p>
        <p>On every postback by the below button, you'll see the listener being invoked once more.</p>
        <h:form>
            <h:commandButton value="submit" />
        </h:form>
        <p>Note however that this increments every time you issue the postback.</p>
        <p>If you remove <code>/WEB-INF/beans.xml</code> and redeploy, then the issue will disappear.</p>
    </h:body>
</html>

package com.example;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Bean {

    public void preRenderView() {
        System.out.println("preRenderView called");
    }

}

丟失的資源也可能導致偵聽器被調用兩次。 我在這里使用MyFaces 2.2:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<f:metadata>
    <f:event type="preRenderView" listener="#{testController.update()}" />
</f:metadata>

<h:head>
    <script type="text/javascript" src="#{resource['/js/missing.js']}" />
    <title>Test</title>
</h:head>

<h:body>
    <p>TestController.update() is called twice.</p>
</h:body>

</html>

顯然,您不應該首先包含任何遺漏或過時的資源。 但是,假設您(錯誤地)並且您的聽眾被連續兩次調用,您沒有機會找到該問題的實際原因。 JSF不應該這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM