【问题标题】:JSF 2.1 - Dynamic UIComponents and LinksJSF 2.1 - 动态 UIComponents 和链接
【发布时间】:2013-10-23 09:33:32
【问题描述】:

我在 Tomcat6 上使用 JSF 2.1 和 el2.2 库。

我创建了一个模板布局,其中包含所有页面通用的页眉、菜单栏和页脚,只是内容发生了变化。每个部分都在其自己的 div 标签中。一切正常,菜单栏链接使用 faces-config 导航规则正确导航到新页面。

我现在创建了一个包含动态创建的 UIComponents 的内容页面。当视图渲染时,带有一项的面板网格正确显示,但所有菜单项都不再起作用!

如果我从 xhtml 中删除 panelgrid 标记并刷新,则菜单项将再次正常工作。在这种情况下,生成的 HTML 的唯一区别是 panelgrid 的 table 标记的存在/不存在。

在以下示例中,我将其简化为带有单个子项的单个 HtmlPanelGrid。

我的 Bean:(BaseBean 所做的只是实现 Serializable)。

package org.gwl.chart;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.component.html.HtmlPanelGrid;

import com.praxism.iims.web.BaseBean;

@ManagedBean
@SessionScoped
public class DashBacker extends BaseBean {

    private static final long serialVersionUID = -894246439580172432L;

    HtmlPanelGrid _dash;

    public DashBacker() {
    }

    @PostConstruct
    public void init() {
        _dash = new HtmlPanelGrid();
        _dash.setColumns(3);
        _dash.setId("dashboard");

        HtmlOutputLabel label1 = new HtmlOutputLabel();
        label1.setId("label1");
        label1.setValue("Label 1");
        _dash.getChildren().add(label1);
    }

    public HtmlPanelGrid getDash() {
        return _dash;
    }
}

我的内容 xhtml

<?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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:iims-chart="http://java.sun.com/jsf/composite/components/chart">
    <ui:composition>    
        <h:outputText styleClass="h1" value="#{msgs_dash.heading}"/>
        <h:messages errorClass="errorMessage" infoClass="infoMessage" warnClass="warnMessage"/>
        <h:panelGrid binding="#{dashBacker.dash}" />
    </ui:composition>
</html>

我的菜单栏 xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
    <ui:composition>
        <h:form id="menuBarFrm" styleClass="my-menubar">
            <p:menubar>
                <p:menuitem rendered="#{request.isUserInRole('user')}" value="Home" action="home"/>
                <p:submenu rendered="#{request.isUserInRole('user')}" label="Help">
                    <p:menuitem rendered="#{request.isUserInRole('user')}" value="About" action="about"/>
                </p:submenu>
            </p:menubar>
        </h:form>
    </ui:composition>   
</html> 

最后,我的布局模板

<!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:f="http://java.sun.com/jsf/core"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title><ui:insert name="windowTitle">DEFAULT_TITLE</ui:insert></title>
    </h:head>
    <h:body>
        <div id="layout-header">
            <ui:insert name="header">No define for "header"!</ui:insert>
        </div>
        <div id="layout-menubar">
            <ui:insert name="menubar">No define for "menu"!</ui:insert>
        </div>
        <div id="layout-content">
            <div id="layout-scrollable">
                <div id="layout-margin">
                    <ui:insert name="content">No define for "content"!</ui:insert>
                </div>
            </div>
        </div>
        <h:messages/>
        <div id="layout-footer">
            <ui:insert name="footer">No define for "content"!</ui:insert>
        </div>
    </h:body>
</html> 

【问题讨论】:

  • 当你点击主页时,它是否正确重定向它,加载后菜单项是否工作
  • 如果我要通过显式 URL 浏览到帮助/关于页面,那么菜单项可以工作,我可以重新浏览到那里或浏览到主页。只有当 Home 被渲染时,菜单才会停止工作。 (它对鼠标悬停做出反应并弹出子菜单,但没有链接)

标签: jsf jsf-2 uicomponents


【解决方案1】:

您不能将组件存储在高于请求范围的任何位置。

【讨论】:

  • 我只迁移到 SessionScoped,因为我原来的 ViewScoped 导致 HtmlPanelGrid 出现 NonSerializableException。我从未考虑过缩小范围。 RequestScoped 有效。对它影响菜单栏链接的奇怪行为有何解释,特别是当生成的 HTML 相同时?
  • 这需要很多解释。可以说它被规范禁止(至少在 2.2 中),因此是未记录的行为。通过在会话中存储对 JSF 视图树中任何内容的引用,您还隐式地在会话中存储了对 ViewRoot 的引用(根据每个请求重新创建),从而导致内存泄漏和许多意外的副作用。为什么会有奇怪的行为?因为 JSF 无法在回发时正确恢复视图(正因为如此),所以如果不进行调试,很难判断到底出了什么问题。但是,错误的原因很明确。
猜你喜欢
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
相关资源
最近更新 更多