【问题标题】:Elegant handling of attributes without a session bean在没有会话 bean 的情况下优雅地处理属性
【发布时间】:2012-04-27 03:08:48
【问题描述】:

我正在开发一个使用 JSF 2.0 和 Richfaces 4 的应用程序,它包含许多显示元素的表格,当然还有常用的查看/编辑/删除选项。经过一些 SO 浏览和 Google 搜索后,我决定发布一个问题,因为我找到的答案并没有解决我的问题。

现在,直截了当,我的应用程序在处理存储在请求 bean 中的某些属性时遇到问题,并且在某些点上,由于连续请求而丢失。

例如,当我想编辑一个对象时,该对象被发送 (f:propertyActionListener) 到在表单上显示数据的请求 bean,然后在该请求结束时将其丢弃。保存时,会创建一个新对象并将表单上的属性设置为该对象,并且该项目被保存而不是更新,因为它没有 id (JPA + Hibernate)。

我已经调查了很多选项,这就是我到目前为止所做的事情和结果:

f:param + h:link 或 h:commandLink: 使用 @ManagedProperty 时,参数为空,我无法在 Context 上找到它以通过 JNDI 进行查找。

f:setPropertyActionListener + h:commandLink + Request Bean: 工作......但我丢失了一些数据。显示数据的表单有一些条件渲染的字段,我无法保存该信息,因此如果验证阶段发现无效数据,表单就会混乱。

f:viewParam + h:commandLink + 查看 Scoped Bean: 奇怪的东西在这里。这个不能直接工作,因为 bean 似乎在呈现表单之前就被丢弃了,因为表单是在没有任何信息的情况下呈现的,因为 bean 是干净的。

使用会话 bean: 就像一个魅力,但我不想仅仅因为我还在学习有关 JSF 生命周期的东西,就为每个表单制作一个会话 bean,我想以正确的方式去做。

如果我想保留请求会话方法,有没有办法存储参数(对象或纯字符串)并稍后在请求 bean 上获取?

不知道这是否有帮助,但我正在通过 ui:insert 和 ui:define 使用母版页。

【问题讨论】:

    标签: java jsf-2 richfaces


    【解决方案1】:

    使用视图范围的 bean。它应该工作。您在那里描述的问题表明您将其绑定到 JSTL 标记或 idbinding 属性。您不应该在视图范围的 bean 上这样做。另见@ViewScoped fails in tag handlers。另一个可能的原因是您使用 CDI 的 @Named 而不是 JSF 的 @ManagedBean 来管理 bean。这也可以解释为什么 @ManagedProperty 在您的一项尝试中不起作用,因为它还要求 bean 由 JSF 的 @ManagedBean 管理。

    对于主从页面方法,在表格页面中使用<h:link><f:param> 在主页面中创建查看/编辑链接。

    例如user/list.xhtml

    <h:dataTable value="#{userList.users}" var="user">
        <h:column>#{user.id}</h:column>
        <h:column>#{user.name}</h:column>
        <h:column>
            <h:link value="Edit" outcome="edit">
                <f:param name="id" value="#{user.id}" />
            </h:link>
        </h:column>
    </h:dataTable>
    

    bean 可以只是请求范围。

    然后,在默认页面(本例中为编辑页面)中,使用&lt;f:viewParam&gt; 进行转换、验证并将id 设置为User

    例如user/edit.xhtml

    <f:metadata>
        <f:viewParam name="id" value="#{userEdit.user}"
            converter="#{userConverter}" converterMessage="Bad request. Unknown user."
            required="true" requiredMessage="Bad request. Please use a link from within the system." />
    </f:metadata>
    
    <h:messages />
    <h:link value="Back to all users" outcome="users" />
    
    <h:form id="user" rendered="#{not empty userEdit.user}">
        <h:inputText value="#{userEdit.user.name}" required="true" />
        ...
    
        <h:commandButton value="Save" action="#{userEdit.save}">
            <f:ajax execute="@form" render="@form" />
        </h:commandButton>
    </h:form>
    

    使用@ViewScoped bean 来保存数据、服务和操作方法:

    @ManagedBean
    @ViewScoped
    public class UserEdit {
    
        private User user;
    
        @EJB
        private UserService service;
    
        public String save() {
            service.save(user);
            return "users";
        }
    
        // Getter+setter.
    }
    

    【讨论】:

    • 即使在这种情况下,@ViewScoped 真的是一个好的解决方案吗?虽然这需要更多的工作,但我通常倾向于@ConversationScoped 以避免使用后退按钮、多个选项卡/窗口和视图范围的数据过期等问题。我需要写一篇关于我的想法的适当博客文章,但现在我将引用我的 previous answer
    • 感谢您的帖子@BalusC!总是很高兴阅读您的答案。至于选项,我们没有对您博客上的链接所声明的特定标签进行任何绑定,也没有将标签直接绑定到 bean。问题可能是由在“渲染”属性上使用一些 EL 表达式引起的吗?我们这样做是为了根据情况调整表格。
    • @ViewScoped 在带有单个提交按钮的基本 hello world 页面上是否也会失败,其中操作方法返回 nullvoid
    • 是的,它也会丢失数据。调试 我发现第一次调用正确设置了 bean,然后第二次调用 bean 完全干净。我认为它会被丢弃然后重新实例化......我什至定义了一个导航规则,其中包含重定向指令和 true 的 include-view-params。
    • 此症状与@ManagedProperty 也失败以及您对@ConversationScoped 的支持相结合,表明您实际上根本没有使用JSF @ManagedBean 来管理bean,而是使用CDI @Named。这是真的? JSF 托管 bean 注释对 CDI 托管 bean 起作用。
    猜你喜欢
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 2012-04-16
    • 2012-09-21
    • 2017-10-28
    • 1970-01-01
    • 2010-11-19
    • 2013-07-02
    相关资源
    最近更新 更多