使用jsf会话范围的托管bean来表示静态分层数据

sku*_*sel 5 jsf-2 managed-bean

这可能是一种架构问题,但它仍然必须有一个"最佳实践解决方案"或一个公认的标准.

我在谈论需要在网站上显示的某种静态数据,例如产品目录,菜单和菜单项列表,面包屑块列表等.我想这个选项在使用任何标准CMS时都可用.

但是我想在这个问题上使用纯JSF解决方案.

所以,回到这个问题,我的阐述源于以下原则:

  1. 数据不应该在facelets中进行硬编码,因此我使用数据库来保存值,就像在下面的db脚本中一样(在我的例子中是MYSQL):

    CREATE TABLE CatalogueGroup (
        CatalogueGroupName VARCHAR(100) NOT NULL PRIMARY KEY,
        URLPath VARCHAR(200) NOT NULL,
        ParentGroupName VARCHAR(100) DEFAULT NULL,
        FOREIGN KEY (ParentGroupName) REFERENCES CatalogueGroup(CatalogueGroupName) ON UPDATE CASCADE ON DELETE SET NULL
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后我想使用实体类保存在@ManagedBean中并将其显示在视图中,如

    public class CatalogueGroup implements Serializable {
        private String catalogueGroupName;
        private List<CatalogueGroup> children = new ArrayList<CatalogueGroup>();
        private CatalogueGroup parentGroup;
        //other stuff of this bean
    }
    
    @ManagedBean
    @SessionScoped
    public class CatalogueBean implements Serializable {
        private CatalogueGroup catalogue;//loaded via CatalogueGroupDAO with condition parentGroup == null
        //other stuff of this bean
    }
    
    //snippet of xhtml view for a two-level catalogue
    <ul><h:outputText value="#{catalogueBean.catalogue.catalogueGroupName}" />
        <ui:rereat value="#{catalogueBean.catalogue.children}" var="group">
            <li><h:outputText value="#{group.catalogueGroupName}" /></li>
        </ui:repeat>
    </ul>
    
    Run Code Online (Sandbox Code Playgroud)

上述设置有效,但感觉它是一个尴尬的.所以,我想向jsf社区提出以下开放的"最佳实践"问题:

  1. 设置这样的目录bean的正确方法是什么:
    • 一个@SessionScope将被加载一次并重新显示在每个视图或豆
    • 一个@RequestScoped豆,将每一页显示数据库的访问.
  2. 有没有办法在facelet视图中设置递归函数,或者我应该将目录嵌套级别限制为2或3.
  3. 我想显示某种修改的目录,向登录用户公开更多组,具体取决于他的角色(在数据库表中添加的列),并在没有用户登录时显示基本目录.另外,我想偶尔插入目录中的一些新组并且不强制用户重新登录,而是立即重新显示正确的数据:
    • 我应该在业务层中过滤组并将过滤后的CatalogueGroup暴露给bean,否则我将加载整个目录并使用rendered = false限制其子视图;
    • 在会议中曝光整个目录是否适当;
    • 是否有可能在向服务器上活动的所有当前CatalogueBean添加新数据库条目时发送修改事件,强制刷新其属性(CatalogueGroup)或实现此功能我@RequestScoped只需要使用bean;
    • 如果使用请求范围的bean是唯一的替代方案,那么访问数据库以获取数据通常很少改变或者有更聪明的做事方式是明智的.
    • 当用户登录(并注销)时,已经存在会话作用域目录的实例,如何刷新它:我是否需要在操作/动作侦听器中手动执行此操作,或者我需要使会话无效或执行更适合该情况的操作.

Xtr*_*ica 1

非常有趣,但也许是一个开放领域的问题。

首先,范围取决于您为目录提供的实用程序。@ViewScoped如果您想将数据链接到特定视图或者@SessionScoped您的目标是实现购物篮之类的东西,我建议您仔细阅读。

对于递归函数,我认为您应该避免在纯视图( xhtml )层中进行这种做法,并使用像PrimefacesRichfaces这样的库,它们具有用于您想要执行的操作的内置组件。使用它们时,您只需在托管支持 bean 内以编程方式处理它们的逻辑结构。

最后,对于目录限制,我建议您仅加载要从数据库中使用的内容。这样,服务器-数据库服务器-客户端连接就不会过载。您可以有一个@SessionScopedbean 来管理当前登录用户的会话,并且根据该 bean,您可以向数据库询问某些值或其他值。

另外,您还必须关心您的目录,如果您在会话期间对其进行大量修改,也许@ViewScopedbean 是更好的选择,因为每次请求视图时都会重新加载它。如果您@SessionScoped为此使用 bean,则必须手动添加每个更改,以便在会话期间保持其更新。

"load the whole catalogue and limit its children in views with rendered=false"

如果你按照我说的方式去做,那是一项你不必做的工作。如果您正在管理复杂的树并向视图中引入更多逻辑,则有条件地评估每个树节点可能会很困难。当然,您应该尽可能避免这种情况。

即使你已经找到了解决方案,这就是我的主要想法。