PreRenderView在每次回发中增量调用 [英] PreRenderView incrementally called on every postback

查看:82
本文介绍了PreRenderView在每次回发中增量调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an issue with the order and number of executions of an f:event type="preRenderView".

在这里进行搜索时,我通常在帖子与我的问题有关-仍然给我留下了两个问题:

During my search here I found as usual answers from BalusC in this and this post related to my problem - still it leaves two questions for me:

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

  1. When I put one f:event type="preRenderView" in the template file (for managing common tasks like checks about the user state which applies for all my views) and another f:event type="preRenderView" in each view (for handling view specific initializations), I wonder why the listener method from the view is called before the one from the template.

当我按照建议将整个<f:metadata><f:event [..] /></f:metadata>放在ui:define之后时,从登录页面重定向到该页面后,它会被调用两次,但是当我将其放置在ui:composition之后的更高一级时,它只会得到叫过一次.

When I put the whole <f:metadata><f:event [..] /></f:metadata> after ui:define as suggested, it gets called twice after redirecting to that page from the login page, but when I put it one level higher after ui:composition it only gets called once.


更新:示例

下面的示例演示了上面的行为:

The following example demonstrates the behaviour above:

这是模板文件template_test.xhtml,包含用于preRenderView事件的侦听器,该侦听器在处理程序中为所有视图调用通用方法:

This is the template file template_test.xhtml, containing a listener for preRenderViewevent calling a common method in a handler for all views:

<?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事件的侦听器,该事件在处理程序中调用视图特定的方法,并通过处理程序方法重定向命令按钮:

This is the view file test.xhtml, containing also a listener for preRenderViewevent calling a view specific method in a handler and a command button redirecting via a handler method:

<?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:

This is the handler class TestHandler.java containing the 3 methods:

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日志中看到的内容:

Now, this is what I see in my tomcat log when requesting the test page:

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

显示否. 1,视图中的事件处理程序在模板中的事件处理程序之前调用,否. 2,视图中的事件处理程序被调用了两次.

This shows no. 1, that the event handler from the view is called before the one from the template and no. 2, that the event handler from the view is called twice.

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

It also shows a 3rd point (that's why I included a button with a redirect to the same page) showing what happens if the page gets requested by redirect - the individual page gets called even more times:

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

两者都不是.可以通过将整个元数据部分放在ui:define上方或向该视图的元数据部分添加一个不包含在URL中的伪参数来防止出现图2和3:

Both no. 2 and 3 can be prevented by either putting the whole metadata section above the ui:define or by adding a dummy parameter to the view's metadata section which is not included in the URL:

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

有人可以告诉我这些情况的原因吗?

Can someone tell me the reason for those cases?

推荐答案

我可以复制它.这是由/WEB-INF/beans.xml的存在引起的,因此也暗含CDI.当您在保留beans.xml文件的同时切换回标准JSF批注时,甚至会发生这种情况.这已经作为 issue 1771

I can reproduce it. This is caused by the presence of /WEB-INF/beans.xml and implicitly thus CDI. It even occurs when you switch back to standard JSF annotations while keeping the beans.xml file. This is already reported as both issue 1771 and issue 2162. However, due to absence of a concrete WAR file reproducing the issue and low votes, the Mojarra developers didn't bother to look closer at it.

我再次将其报告为 issue 2719 .可以用一个较小的示例重现该问题:

I have reported it once again as issue 2719. The problem can be reproduced with a smaller example:

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

}

这篇关于PreRenderView在每次回发中增量调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆