查看 Scoped Bean preRenderView 方法被多次调用

Posted

技术标签:

【中文标题】查看 Scoped Bean preRenderView 方法被多次调用【英文标题】:View Scoped Bean preRenderView method being called multiple times 【发布时间】:2012-12-18 16:47:52 【问题描述】:

我的 Mojarra 2.1.6 Web 应用程序有问题,我正在使用 @ViewScoped 托管 bean 开发它,并且每个 bean 都附加到一个 xhtml 页面。这个页面正在接收一些 view params 并且在以这种方式初始化 bean 之后:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
template="/templates/general_template.xhtml">

<ui:define name="metadata">
    <f:metadata>
        <f:viewParam id="user" name="user"
            value="#navegableUserData._ParamUser" />

        <f:viewParam id="NavIndex" name="NavIndex"
            value="#navegableUserData._QueueIndex" />
        <f:event type="preRenderView"
            listener="#navegableUserData.initialize" />
    </f:metadata>
    <h:message for="user" />
</ui:define>

<ui:define name="general_content">
    <p:outputPanel autoUpdate="false" id="Datos_Loged" name="Datos_Loged"
        layout="block">
        <h:form id="SystemUserForm">
            <ui:include
                src="/system/manage_user/content/edit_user/system_user_data/system_user.xhtml">
                <ui:param name="manager" value="#navegableUserData" />
            </ui:include>
        </h:form>
    </p:outputPanel>
</ui:define>

如您所见,我的页面嵌套在一个通用模板中,如下所示:

<?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">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">


<h:head>
    <meta http-equiv="Pragma" CONTENT="no-cache"></meta>
    <meta http-equiv="cache-control" content="no-cache"></meta>
    <meta http-equiv="Expires" CONTENT="-1"></meta>
    <meta http-equiv="Content-Type"
        content="text/html; charset=ISO-8859-15" />
    <h:outputStylesheet library="css" name="prime_styles.css" />
    <h:outputScript library="js" name="prime_translations.js" />
</h:head>

<h:body>
    <ui:insert name="metadata" />
    <o:importConstants
        type="com.company.system.view.beans.NavigationResults" />

<!-- More stuff -->

当我发出 ajax 请求(例如 Primefaces 表过滤)时,问题就来了。虽然没有再次创建我的支持 bean,但再次调用了 &lt;f:event type="preRenderView" listener="#navegableUserData.initialize" /&gt;

我正在基于视图参数进行数据加载,并且仅在第一次呈现页面时才需要执行该方法。我一直非常小心地使用&lt;c:xxx&gt; 标签并认为这不是问题,因为我只在一般模板中使用它们并且我的视图bean 属性没有附加到它们。我的所有页面也有这个问题,所以我认为这不是特定支持 bean 的问题。

【问题讨论】:

primefaces 的哪个版本?问题可能就在那里。确保您拥有最新版本。您还应该尝试升级到 Mojarra 2.1.14(2.1.15/16 与 Primefaces 结合存在问题,所以我不推荐它),只是为了排除它是由已经存在的错误引起的固定。 用 Prime 3.4.2 和 Mojarra 2.1.14 试过了,我仍然有同样的问题。 Ajax请求不是我自己专门做的,而是PF dataTable过滤器做的。 相关:***.com/questions/6377798/… 【参考方案1】:

如果这仅在 ajax 请求期间发生,请尝试以下操作:

public void initialize() 
    if (!FacesContext.getCurrentInstance().isPostback()) 
        // -----------
        // -----------
    

BalusC 建议的相关:

What can f:metadata and f:viewParam be used for?

【讨论】:

【参考方案2】:

为了完整起见,除了@jonhy 提到的方法之外,如果使用 JSF 2.2,还有一个更简洁的选择:使用 f:viewAction 而不是 f:event

<f:viewAction action="#navegableUserData.initialize" />

这样,就没有必要用if (!FacesContext.getCurrentInstance().isPostback()) 包装您的服务器代码,因为基本上不会调用该方法本身,因为默认情况下,此操作不会在回发时执行。

您也可以将它们设置为,这与使用原始 f:event 的行为相同:

<f:viewAction action="#navegableUserData.initialize" onPostback="true" />

另请参阅:

New JavaServer Faces 2.2 Feature: The viewAction Component

【讨论】:

@ChRoNoN 它将在模板客户端中(ui:define 发生的地方)。在模板本身中使用它没有多大意义,因为它旨在初始化一个具体的 bean,通常是 @ViewScoped 我的意思是每次调用页面时执行一些东西(登录检查?访问控制?)如果你把它放在主模板中它不会起作用,你需要把它放在每个文件中使用主模板。我相信 viewAction 主要是在渲染页面的同时在特定的地方执行一些东西。 Bean 初始化支持使用@PostConstruct 安全检查最好放置在 web 过滤器中而不是视图本身中。视图操作和 post 构造之间的区别在于 JSF 确实在第一次发生之前调用设置器(这对于拥有 url 是有效的参数等),而第二个在构造函数之后立即被调用。所以第一个更方便使用要显示的值来初始化 bean。

以上是关于查看 Scoped Bean preRenderView 方法被多次调用的主要内容,如果未能解决你的问题,请参考以下文章

Spring-AOP标签scoped-proxy

命名 CDI bean 的默认范围是啥?

Facebook - 通过 app_scoped_user_id 打开个人资料

Vue中的scoped属性

智能指针scoped_ptr

sassless中的scoped属性