【问题标题】:JSF: what is the "correct" way of doing this?JSF:这样做的“正确”方式是什么?
【发布时间】:2011-04-04 22:59:29
【问题描述】:

我使用 JSF 已经有一段时间了,但有些事情一直让我感到困惑。希望有人可以提供帮助。

简单的例子,有一个页面显示了一个“Person”表格,当您单击“Person”名称时,它会将您带到一个页面以查看“Person”的详细信息。

通常,我会这样实现 personSearch.jsf 页面:

<h:dataTable value="#{personHandler.persons}" var="person">

    <h:column>
        <h:commandLink action="#{personHandler.show( person.id )}" >
            <h:outputText value="#{person.name}" />
        </h:commandLink>
    </h:column>

</h:dataTable>

我实现了一个这样的 personView.jsf 页面:

<h:panelGrid columns="2">

    <h:outputText value="Person ID:" />
    <h:outputText value="#{personHandler.selectedPerson.id}" />

    <h:outputText value="Person Name:" />
    <h:outputText value="#{personHandler.selectedPerson.name}" />

</h:panelGrid>

PersonH​​andler.show(Integer personId) 设置 personH​​andler.selectedPerson 然后重定向到 personView 页面。

当 PersonH​​andler 是会话 bean 时,这一切都可以正常工作。但我更喜欢它是一个请求范围的 bean,因为用户可能打开了多个窗口,我不希望每个会话只有一个选定的人。

所以我的问题是,执行此 JSF 的“正确”方法是什么?我曾经能够在 personH​​andler 上使用 a4j:keepAlive 来获得我想要的东西,但这总是让人觉得很麻烦。再说一次,这是我对 JSF 从来没有理解过的地方。

非常感谢任何帮助! 抢

【问题讨论】:

    标签: jsf


    【解决方案1】:

    如果视图应该是可收藏的,请将人员 ID 作为 GET 请求参数而不是 POST 请求“参数”传递。

    <h:outputLink value="viewperson.xhtml">
        <f:param name="id" value="#{person.id}" />
    </h:outputLink>
    

    这样您可以使用两个@RequestScoped bean,一个用于列表,一个用于视图。您可以按如下方式预加载所选人员:

    @ManagedProperty(value="#{param.id}")
    private Long id;
    
    @PostConstruct
    public void init() {
        selectedPerson = personDAO.find(id);
    }
    

    如果它不应该是可收藏的,那么只需创建一个有条件地呈现视图状态的单个视图。

    <ui:fragment rendered="#{!personHandler.viewMode}">
        <h:form>
            <h:dataTable value="#{personHandler.persons}" var="person">
                <h:column>
                    <h:commandLink value="#{person.name}" action="#{personHandler.show(person)}" />
                </h:column>
            </h:dataTable>
        </h:form>
    </ui:fragment>
    <ui:fragment rendered="#{personHandler.viewMode}">
        <h:form>
            ...
            <h:commandLink value="Go back" action="#{personHandler.back}" />
        </h:form>
    </ui:fragment>
    

    (如有必要,您可以将两个片段的内容拆分到另一个 Facelet 文件中,&lt;ui:include&gt; 包含该文件)

    这样,您可以使用单个 @ViewScoped bean 和返回 voidnull 的操作方法。

    public void show(Person selectedPerson) {
        this.selectedPerson = selectedPerson;
    }
    
    public void back() {
        selectedPerson = null;
    }
    
    public boolean isViewMode() {
        return selectedPerson != null;
    }
    

    你甚至可以将整个视图包裹在一些

    <h:panelGroup id="container">
    

    并在两个命令链接中嵌套以下内容,让 Ajax 魔法发挥作用

    <f:ajax execute="@form" render=":container" />
    

    【讨论】:

    • 一如既往,一个了不起的答案!谢谢BalusC。不过,我当前的应用程序设计不同。我有三个单独的页面 personSearch.xhtml、personView.xhtml 和 personForm.xhtml(用于创建/编辑),因为每个页面的布局都非常不同。你会建议总是使用你的 GET 参数方法来导航吗?当我需要在移动到下一页之前点击一个方法进行一些处理时,h:outputLink 可以有一个指向方法的动作吗?或者,可以 h:commandLink 有参数吗?再次感谢(你应该写一本书!)
    • 对于不同的布局,你肯定有一个基本的主布局(所有页面都相同的页眉/页脚/菜单/css/js),是吗?至于在导航之前执行一个方法,那么使用命令链接/按钮结合重定向。是的,命令链接/按钮也可以有&lt;f:param&gt;,或者,通常更好,&lt;f:setPropertyActionListener&gt;
    • 有一个 facelets 模板,其中定义了“内容”和“菜单”部分,每个实体(搜索、视图和表单)的三个页面中的每一个都引用该模板并定义内容中的内容和菜单部分。你是这个意思吗?每个实体都有一个处理程序,例如 PersonH​​andler,具有 doSearch、showViewPerson(Integer id)、showModifyPerson(Integer id)、doCreate、doModify、doDelete 等方法。这是我的基本设计。所有的处理程序都是基于会话的,但我更希望它们是基于请求的。这种设计是错误的方法吗?我很感激你的任何建议。谢谢。
    • 另外,一般来说,每个“show”和“do”方法都返回一个用于导航目的的字符串。例如,创建后我转到创建的项目的视图页面,所以成功 personH​​andler.doCreate 返回“personView”等等。
    • 嗨 BalusC -- 我正在尝试像你说的那样做一个简单的 get param 示例,但我做错了。我发布了一个新问题,如果您能看一下,我将不胜感激! 抱歉,我的示例中有一个愚蠢的打字错误。现在明白了!谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多