[英]JSF f:event preRenderView in template f:metadata, listener not being called on every page access
[英]PreRenderView incrementally called on every postback
我對f:event type="preRenderView"
的執行順序和執行次數有f:event type="preRenderView"
。
在這里我的搜索,我發現從BalusC在通常的回答這個和這個職位涉及到我的問題-它仍然留下了兩個問題要問:
當我在模板文件中放置一個f:event type="preRenderView"
(用於管理常見任務,例如關於適用於我所有視圖的用戶狀態的檢查)和每個視圖中的另一個f:event type="preRenderView"
(用於處理)查看特定的初始化),我想知道為什么視圖中的偵聽器方法在模板之前被調用。
當我按照建議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.