Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jsf 为什么渲染属性会多次调用getter?_Jsf_Jsf 2_Facelets_Getter - Fatal编程技术网

Jsf 为什么渲染属性会多次调用getter?

Jsf 为什么渲染属性会多次调用getter?,jsf,jsf-2,facelets,getter,Jsf,Jsf 2,Facelets,Getter,与前面的一个示例相关,我尝试在服务器上监视我的get/set方法(调用它们的时间和频率)。因此,我的实际情况是: @ManagedBean(name="selector") @RequestScoped public class Selector { @ManagedProperty(value="#{param.profilePage}") private String profilePage; public String getProfilePage() {

与前面的一个示例相关,我尝试在服务器上监视我的get/set方法(调用它们的时间和频率)。因此,我的实际情况是:

@ManagedBean(name="selector")
@RequestScoped
public class Selector {
    @ManagedProperty(value="#{param.profilePage}")
    private String profilePage;

    public String getProfilePage() {
        if(profilePage==null || profilePage.trim().isEmpty()) {
            this.profilePage="main";
        }

        System.out.println("GET "+profilePage);

        return profilePage;
    }
    public void setProfilePage(String profilePage) { 
        this.profilePage=profilePage; 
        System.out.println("SET "+profilePage); 
    }
}
唯一可以调用此方法的页面(它只在呈现时调用get方法)是:

什么?它调用了七次
getProfilePage()
方法?(还有1次
setProfilePage()
) 我想知道为什么会有这种行为:)

谢谢

添加了一个示例

豆子

profile.xhtml

<h:panelGroup layout="block" id="profileContent">
    <h:panelGroup layout="block" styleClass="content_title">
        Profilo Utente
    </h:panelGroup>

    <h:panelGroup rendered="#{selector.profilePage=='main'}">
        <ui:include src="/profile/profile_main.xhtml" />
    </h:panelGroup>

    <h:panelGroup rendered="#{selector.profilePage=='edit'}">
        <ui:include src="/profile/profile_edit.xhtml" />
    </h:panelGroup>
</h:panelGroup>

// profile_main.xhtml
<h:form id="formProfileMain" prependId="false">
    <h:panelGroup layout="block" styleClass="content_span">
        <h:outputScript name="jsf.js" library="javax.faces" target="head" />

        <h:panelGroup layout="block" styleClass="profilo_3">
            <h:commandButton value="EDIT">
                <f:setPropertyActionListener target="#{selector.profilePage}" value="edit" />
                <f:ajax event="action" render=":profileContent"/>
            </h:commandButton>
        </h:panelGroup>
    </h:panelGroup>
</h:form>

// profile_edit.xhtml
<h:form id="formProfileEdit" prependId="false">
    <h:panelGroup layout="block" styleClass="content_span">
        <h:outputScript name="jsf.js" library="javax.faces" target="head" />

        <h:panelGroup layout="block" styleClass="profilo_3">
            <h:commandButton value="Edit">
                <f:setPropertyActionListener target="#{selector.profilePage}" value="editProfile" />
                <f:ajax event="action" render=":profileContent"/>
            </h:commandButton>

            <h:commandButton value="Back">
                <f:setPropertyActionListener target="#{selector.profilePage}" value="main" />
                <f:ajax event="action" render=":profileContent"/>
            </h:commandButton>
        </h:panelGroup>
    </h:panelGroup>
</h:form>      

profilounte
//profile_main.xhtml
//profile_edit.xhtml
在本例中,我调用profile_main(默认);在(例如)我调用profile_edit(通过单击edit)之后;之后,单击“上一步”返回profile_main。现在,如果我想重新加载profile_edit(编辑),我需要多次单击该命令按钮。为什么?

EL(表达式语言,那些
{}
东西)不会缓存调用的结果。它只是直接访问bean中的数据。如果getter只返回数据,这通常不会造成损害

setter调用由
@ManagedProperty
完成。其基本功能如下:

selector.setProfilePage(request.getParameter("profilePage"));
getter调用都是在呈现响应阶段通过
rendered=“#{selector.profilePage=='some'}”
完成的。当它在中第一次计算
false
时,将不再执行任何调用。当它计算为
true
时,将按照以下顺序再重新计算六次:

  • -定位组件开头的渲染器
  • -呈现组件的开始
  • -为组件的子级查找渲染器
  • -呈现组件的子级
  • -定位组件末尾的渲染器
  • -渲染组件的结尾
  • 组件及其渲染器在每个步骤中验证是否允许渲染。在表单提交期间,如果输入或命令组件或其任何父组件具有
    呈现的
    属性,则在应用请求值阶段也将对其进行评估,作为防止篡改/黑客请求的一部分

    没错,这看起来既笨拙又低效。它被认为是JSF的致命伤。建议删除所有这些重复检查,并坚持在
    UIComponent\encodeAll()
    中完成的检查,或在每个阶段对
    isRendered()
    进行评估,很明显,问题的根源在于EL,而不是JSF,使用CDI可以大大提高性能。所以没有必要从JSF规范的角度来解决这个问题


    如果您担心托管属性在其设置为空或空后只检查一次,则考虑将其移动到一个用<代码> @ PrimeStudio注释的方法。这种方法将在bean的构造和所有依赖项注入之后直接调用

    @PostConstruct
    public void init() {
        if (profilePage == null || profilePage.trim().isEmpty()) {
            profilePage = "main";
        }
    }
    
    另见:

    您可以使用CDI方法。 它将被多次调用,但第一次调用的结果缓存在bean的作用域中,对于正在计算或初始化重对象的getter来说非常有效!
    请参阅,了解更多信息。

    可能重复了这个问题:我读了这篇文章,但它没有解释为什么多次调用getMethod。这使我现在在AJAX调用中遇到了一些问题(似乎是写/重写了一些bean属性)。是的,但是我如何指定,我只有一个
    {selector.profilePage}
    一个
    页面中。这就是我不理解的:)我没有仔细观察JSF2.0中的行为,因为它特别便宜,所以不值得进行微优化,但您可能需要添加一个
    Thread.dumpStack()
    给getter,让他知道这个调用是从哪里开始的,并从
    FacesContext.getCurrentInstance().getPhaseId()
    中选择一个sysout来了解它现在处于哪个阶段。嗯,好吧,理解这一点更复杂:)我想在jsf上编程时我不应该介意它(只是我想知道我是否做错了什么)。但似乎发生在所有人身上。好的,我在构造后初始化它:)添加了一个示例。如果这个主题将被关闭,或者这个问题是无关的,我将打开一个新的:)让我知道一个人:)因此,如果我使用
    @ManagedProperty
    (例如
    selector.setProfilePage(request.getParameter(“profilePage”);
    )并且我使用这个值只是为了获取param(不是我的情况),我可以删除
    public void setProfilePage(String profilePage){this.profilePage=profilePage;}
    (我不会这么做,这是一个bean,也许我将来会使用它)。现在很清楚为什么它多次调用getter方法:)我不明白的是为什么我的代码仍然不能正常工作:我必须多次单击按钮来设置profilePage属性(ajax调用启动,但bean似乎不会自我更新
    <h:panelGroup layout="block" id="profileContent">
        <h:panelGroup layout="block" styleClass="content_title">
            Profilo Utente
        </h:panelGroup>
    
        <h:panelGroup rendered="#{selector.profilePage=='main'}">
            <ui:include src="/profile/profile_main.xhtml" />
        </h:panelGroup>
    
        <h:panelGroup rendered="#{selector.profilePage=='edit'}">
            <ui:include src="/profile/profile_edit.xhtml" />
        </h:panelGroup>
    </h:panelGroup>
    
    // profile_main.xhtml
    <h:form id="formProfileMain" prependId="false">
        <h:panelGroup layout="block" styleClass="content_span">
            <h:outputScript name="jsf.js" library="javax.faces" target="head" />
    
            <h:panelGroup layout="block" styleClass="profilo_3">
                <h:commandButton value="EDIT">
                    <f:setPropertyActionListener target="#{selector.profilePage}" value="edit" />
                    <f:ajax event="action" render=":profileContent"/>
                </h:commandButton>
            </h:panelGroup>
        </h:panelGroup>
    </h:form>
    
    // profile_edit.xhtml
    <h:form id="formProfileEdit" prependId="false">
        <h:panelGroup layout="block" styleClass="content_span">
            <h:outputScript name="jsf.js" library="javax.faces" target="head" />
    
            <h:panelGroup layout="block" styleClass="profilo_3">
                <h:commandButton value="Edit">
                    <f:setPropertyActionListener target="#{selector.profilePage}" value="editProfile" />
                    <f:ajax event="action" render=":profileContent"/>
                </h:commandButton>
    
                <h:commandButton value="Back">
                    <f:setPropertyActionListener target="#{selector.profilePage}" value="main" />
                    <f:ajax event="action" render=":profileContent"/>
                </h:commandButton>
            </h:panelGroup>
        </h:panelGroup>
    </h:form>      
    
    selector.setProfilePage(request.getParameter("profilePage"));
    
    @PostConstruct
    public void init() {
        if (profilePage == null || profilePage.trim().isEmpty()) {
            profilePage = "main";
        }
    }