Jsf 在每个请求上构造ViewScope bean。。。第99部

Jsf 在每个请求上构造ViewScope bean。。。第99部,jsf,jsf-2,lifecycle,view-scope,postconstruct,Jsf,Jsf 2,Lifecycle,View Scope,Postconstruct,啊。。。这似乎有一百个答案,我还没有找到一个适合我的,所以我想我会再问一遍。以下是我的设想: 从技术上讲,我的网站只有一个页面,其内容会被调出,而不是有多个页面供您导航。起点是这个区块: <?xml version="1.0" encoding="UTF-8"?> <f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://j

啊。。。这似乎有一百个答案,我还没有找到一个适合我的,所以我想我会再问一遍。以下是我的设想:

从技术上讲,我的网站只有一个页面,其内容会被调出,而不是有多个页面供您导航。起点是这个区块:

<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets">
  <h:head />
  <h:body>
    <ui:include src="resourceInclude.xhtml" />
    <ui:include src="main.xhtml" />
  </h:body>
</f:view>
第三个
h:panelGroup
是所有消息的页脚,用于调试出错的地方

无论如何,每次单击其中一个导航链接时,都会调用viewSelector bean的构造函数。这就是我的viewSelector bean的外观:

package org.mitre.asias.aires.controller;


import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;


import org.apache.log4j.Logger;


@ManagedBean( name="viewSelector" )
@ViewScoped
public class ViewSelector {
    protected static Logger log = Logger.getLogger( ViewSelector.class );
    private Mode mode = Mode.HOME;
    public static final String PORTLET_NAME = "Test";

    public static enum Mode {
        HOME(1, "home"),
        REPORTS(2, "reports"),
        SUPPORT(3, "support"),
        HELP(4, "help");

        private int value;
        private String name;

        private Mode( int value, String name ) {
            this.value = value;
            this.name = name;
        }

        public int getValue() {
            return value;
        }

        public String getName() {
            return name;
        }
    }

    public ViewSelector() {
        log.trace( "constructing new ViewSelector" );
    }

    public Mode getMode() {
        log.trace( "getting mode" );

        return mode;
    }

    public String getModeName() {
        log.debug( "in getmodename" );
        return getMode().getName();
    }

    public String getPortletName() {
        return PORTLET_NAME;
    }

    public boolean isModeReports() {
        return getMode() == Mode.REPORTS;
    }

    public void setMode( Mode mode ) {
        this.mode = mode;
    }

    public void setModeHelp() {
        setMode( Mode.HELP );
    }

    public void setModeHome() {
        setMode( mode = Mode.HOME );
    }

    public void setModeReports() {
        setMode( mode = Mode.REPORTS );
    }

    public void setModeSupport() {
        setMode( mode = Mode.SUPPORT );
    }
}
我知道我一定是做错事了,否则我就错过了JSF工作原理的核心部分。有任何输入吗?

中的EL导致该问题

如果根据禁用在
web.xml
中保存部分状态不是一个选项

<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>true</param-value>
</context-param>

javax.faces.PARTIAL_STATE_保存
真的
那么你需要换一个

<ui:include src="#{viewSelector.modeName}-view.xhtml" />

大概是

<h:panelGroup rendered="#{viewSelector.mode == 'HOME'}">
    <ui:include src="home-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'REPORTS'}">
    <ui:include src="reports-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'SUPPORT'}">
    <ui:include src="support-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'HELP'}">
    <ui:include src="help-view.xhtml" />
</h:panelGroup>

类似的问题以前至少被问过一次:)


再次感谢。你一定听腻了:)。是任何
ui
元素中的EL导致了这种情况,还是仅仅是
ui:include
?换句话说,如果我改为使用模板,我还会遇到这个问题吗?哦,我保证下次会做更多的搜索……虽然很难找到,但对我来说也是如此:)幸运的是,我回忆起了这个主题,这样我就可以更容易地找到它。至于这个问题,只有当您通过EL将任何标记处理程序的属性绑定到视图范围的bean时,才会发生这种情况。标记处理程序在视图生成时而不是视图渲染时运行。标记处理程序都是JSTL
标记,一些JSF
标记和一些Facelets
标记。在这个(相关的)博客中,你可以在一个漂亮的表格中找到它们:巧合的是,我上周正忙着写一篇“JSF2.0中的通信”的博客文章,这篇文章我一小时前刚刚发布。有一章更详细地处理了这个特定的问题:我用
h:panelGroup rendered=“#{el}”
切换到您的建议,但有一个问题。我有第二部分,也有4种模式,其中一种是主动模式。在这种情况下,第四种模式依赖于第三种模式中设置的变量,并且只能从第三种模式导航到第四种模式。但是,呈现的
似乎并不阻止
ui:include
包含页面。这是有意义的,因为
ui:include
会被处理以构建页面,而
rendered
只会在呈现期间被检查。有没有办法防止
ui:include
?这确实是一个棘手的鸡蛋问题的副作用:/禁用部分状态保存不是一个选项吗?理论上,这可以通过
@CustomScoped
解决,它将视图范围的bean直接保存在会话范围内,而不是视图状态。如果那天晚些时候我还有时间,我会用它做实验。
<context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>true</param-value>
</context-param>
<ui:include src="#{viewSelector.modeName}-view.xhtml" />
<h:panelGroup rendered="#{viewSelector.mode == 'HOME'}">
    <ui:include src="home-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'REPORTS'}">
    <ui:include src="reports-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'SUPPORT'}">
    <ui:include src="support-view.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{viewSelector.mode == 'HELP'}">
    <ui:include src="help-view.xhtml" />
</h:panelGroup>