即使 bean 是 @ViewScoped,为什么每次都会触发 @PostConstruct 回调?JSF [英] Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

查看:30
本文介绍了即使 bean 是 @ViewScoped,为什么每次都会触发 @PostConstruct 回调?JSF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在页面上使用数据表并使用绑定属性将其绑定到我的支持 bean.这是我的代码:-

I am using datatable on page and using binding attribute to bind it to my backing bean. This is my code :-

<?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 xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
            <h:form prependId="false">

                <h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
                    <h:column>
                        <h:outputText value="#{item}"/>
                    </h:column>
                    <h:column>
                        <h:commandButton value="Click" actionListener="#{testBean.action}"/>
                    </h:column>
                </h:dataTable>

            </h:form>

    </h:body>
</html>

这是我的豆子:-

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;

@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {

    private List<String> stringCollection;

    public List<String> getStringCollection() {
        return stringCollection;
    }

    public void setStringCollection(List<String> stringCollection) {
        this.stringCollection = stringCollection;
    }

    private HtmlDataTable dataTable;

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!!");
        stringCollection = new ArrayList<String>();
        stringCollection.add("a");
        stringCollection.add("b");
        stringCollection.add("c");

    }

    public void action(){
        System.out.println("Clicked!!");

    }
}

请告诉我为什么每次单击按钮时@PostConstruct 都会触发?只要我在同一页面上,它就应该只触发一次,因为我的 bean 是 @ViewScoped.此外,如果我删除绑定属性,那么一切正常,@PostConstruct 回调只触发一次.那为什么每次我使用绑定属性时?我需要绑定属性,并且只想执行一次初始化任务,例如从 web 服务中获取数据等.我该怎么办?我应该在哪里写我的初始化任务?

Please tell me why is the @PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is @ViewScoped. Further, if i remove the binding attribute then everything works fine and @PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?

推荐答案

有趣的是,当您在视图作用域 bean 上使用组件绑定时,视图作用域会中断.

Interesting, when you're using component binding on a view scoped bean, the view scope breaks.

我不确定这是否是 JSF2 中的错误,我必须先阅读整个 JSF2 规范.到目前为止,您最好的办法是暂时放弃组件绑定并通过新的 EL 2.2 方法参数语法传递所选项目:

I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and pass the selected item via new EL 2.2 method argument syntax:

<h:dataTable var="item" value="#{testBean.stringCollection}">
    <h:column>
        <h:outputText value="#{item}"/>
    </h:column>
    <h:column>
        <h:commandButton value="Click" action="#{testBean.action(item)}"/>
    </h:column>
</h:dataTable>

另见:

  • 如何通过选择行到 dataTable 内的 commandLink?
  • 调用直接方法或带参数的方法/变量/EL中的参数
  • @ViewScoped 的好处和缺陷
  • 更新(2012 年 12 月):这确实是 JSF2 中的一个错误.这是一个先有鸡还是先有蛋的问题.视图范围的 bean 存储在 JSF 视图状态中.因此,视图范围的 bean 仅在恢复视图阶段之后可用.但是,binding 属性在恢复视图阶段运行,而视图范围的 bean 尚不可用.这会导致创建一个全新的视图作用域 bean 实例,该实例随后被存储在恢复的 JSF 视图状态中的真实视图作用域 bean 替换.

    Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the binding attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.

    这被报告为 JSF 问题 1492JSF 规范问题 787 将在 JSF 2.2 中修复.在那之前,最好的办法是专门对请求范围的 bean 使用 binding,或者为特定的功能需求寻找替代方法.

    This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use binding on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.

    更新(2015 年 3 月):JSF 2.2 修复已向后移植到 Mojarra 2.1.18.因此,如果您仍在使用 JSF 2.0/2.1,则最好至少升级到该版本.另见 a.o.什么是JSF 中的组件绑定?何时首选使用?JSF2 Facelets 中的 JSTL...有道理吗?

    Update (Mar 2015): The JSF 2.2 fix was backported to Mojarra 2.1.18. So if you're still using JSF 2.0/2.1, you'd best upgrade to at least that version. See also a.o. What is component binding in JSF? When it is preferred to be used? and JSTL in JSF2 Facelets... makes sense?

    这篇关于即使 bean 是 @ViewScoped,为什么每次都会触发 @PostConstruct 回调?JSF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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