PreRenderView逐步调用每个回发

Ale*_*ühl 6 cdi jsf-2 prerenderview

我对执行的顺序和执行次数有疑问f:event type="preRenderView".

在这里我的搜索,我发现从BalusC在通常的回答这个这个职位涉及到我的问题-它仍然留下了两个问题要问:

  1. 当我f:event type="preRenderView"在模板文件中放置一个(用于管理常见任务,例如关于适用于我所有视图的用户状态的检查)和f:event type="preRenderView"每个视图中的另一个(用于处理视图特定的初始化)时,我想知道为什么调用视图中的监听器方法在模板之前.

  2. 当我把所有内容按照建议放在<f:metadata><f:event [..] /></f:metadata>后面时ui:define,它会在从登录页面重定向到该页面后被调用两次,但是当我将它调高一级后才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>
Run Code Online (Sandbox Code Playgroud)

这是视图文件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>
Run Code Online (Sandbox Code Playgroud)

这是TestHandler.java包含3种方法的处理程序类:

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";
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,这是我在tomcat日志中查看请求测试页面时看到的内容:

Init for individual page called.
Common init called.
Init for individual page called.
Run Code Online (Sandbox Code Playgroud)

这显示没有.1,视图中的事件处理程序在模板之前调用,而不是.2,从视图中调用事件处理程序两次.

它还显示了第三点(这就是为什么我包含一个重定向到同一页面的按钮的原因),显示如果通过重定向请求页面会发生什么 - 单个页面被调用的次数更多:

Init for individual page called.
Common init called.
Init for individual page called.
Init for individual page called.
Run Code Online (Sandbox Code Playgroud)

两个都没有.通过将整个元数据部分放在上面,ui:define或者通过向视图的元数据部分添加虚拟参数(可以不包含在URL中),可以防止2和3 :

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

有人能告诉我这些案件的原因吗?

Bal*_*usC 5

我可以重现它.这是由/WEB-INF/beans.xmlCDI 的存在和隐含因此引起的.甚至在保留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>
Run Code Online (Sandbox Code Playgroud)

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");
    }

}
Run Code Online (Sandbox Code Playgroud)