ViewScoped bean在每个请求上构建...第99部分

时间:2011-09-16 20:09:37

标签: jsf jsf-2 lifecycle view-scope postconstruct

ARGH ......这似乎有一百个答案,而我找不到一个适合我的答案,所以我想我会再次问它。这是我的情景:

我的网站在技术上有一个页面,其内容被换出,而不是导航到多个页面。起点是这个块:

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

resourceInclude.xhtml包含我的css文件:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets">
  <h:outputStylesheet library="css" name="test.css" target="head" />
</ui:composition>

而main.xhtml是视图:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html">
  <h:panelGroup styleClass="test-container" layout="block">
    <h:form id="main-form">
      <h:panelGroup styleClass="test-header" layout="block">
        <h:panelGroup styleClass="navigation" layout="block">
          <ul>
            <li><h:commandLink action="#{viewSelector.setModeHome}">
                <h:outputText value="Home" />
              </h:commandLink></li>
            <li><h:commandLink action="#{viewSelector.setModeReports}">
                <h:outputText value="ASAP Reports" />
              </h:commandLink></li>
            <li><h:commandLink action="#{viewSelector.setModeSupport}">
                <h:outputText value="Technical Support" />
              </h:commandLink></li>
            <li><h:commandLink action="#{viewSelector.setModeHelp}">
                <h:outputText value="Help" />
              </h:commandLink></li>
          </ul>
        </h:panelGroup>
      </h:panelGroup>
      <h:panelGroup styleClass="test-content" layout="block">
        <ui:include src="#{viewSelector.modeName}-view.xhtml" />
      </h:panelGroup>
      <h:panelGroup styleClass="test-footer" layout="block">
        <h:messages />
      </h:panelGroup>
    </h:form>
  </h:panelGroup>
</ui:composition>

它由三个h:panelGroup组成。第一个是一组四个常规导航链接,每个链接更改viewSelector.modeName值,该值用于包含第二个h:panelGroup中的内容<ui:include src="#{viewSelector.modeName}-view.xhtml" />。我已经删除了这个例子,所以每个视图基本上都是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html">
  <h:panelGroup styleClass="test-home-view">
    <p>home</p>
  </h:panelGroup>
</ui:composition>

第三个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如何工作的核心内容。任何输入?

1 个答案:

答案 0 :(得分:3)

<ui:include src>中的EL正在造成这种情况。

如果根据issue 1492禁用web.xml中的部分状态保存,则无法选择

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

至少有一个类似的问题曾经问过一次:)