【问题标题】:JSF passing view parameters by reference - when object must be instantiatedJSF 通过引用传递视图参数 - 当必须实例化对象时
【发布时间】:2011-10-16 06:34:19
【问题描述】:

假设我有一个注册页面和一个注册确认页面。我输入用户 详细信息进入注册页面,导航到注册确认页面,其中 如果有任何错误,我可以返回注册页面。

我将使用视图参数来提供注册数据 从注册页面到确认页面,反之亦然。

假设有 20 项数据要从一个页面移动到另一个页面,那就是 很多视图参数和很多setPropertyActionListeners,尤其是 因为所有数据最终都会很好地打包在一个用户对象中。

所以我要做的就是将注册页面上的数据输入到 用户记录的属性并将对它的引用发送到寄存器 确认页面。让我想到的是 BalusC WeakHashMap 转换器。这是一个 JSF 转换器,它有一个静态的弱哈希映射和 生成一个 uuid 作为映射条目的值,并将对象引用作为 钥匙。因此,通过将其指定为 f:viewParam 您发送的转换器 查询字符串中的 uuid。

这很好用。我遇到的问题是在注册页面上我必须 使用 new 获取 User 类的实例。然后我可以这样做:

<h:inputText value="#{bean.user.firstname}"/>

(etc...),并将用户实例作为视图参数传递。它工作正常 注册到确认页面。问题是当我执行 反向,将用户引用从 确认页面我绝对不能阻止注册页面支持 bean 从重新实例化用户对象开始, setter 被调用之后 作为 view 参数的结果。

所以转换器完成了它的工作并从 哈希映射,在支持 bean 中调用 setUser(),然后我看到 User 类触发的构造函数。

我尝试在 @PostConstruct 中从 bean 构造函数调用 new User(), 在 preRenderView 中(也检查是否有 ajax 请求),但我没有尝试 如果 new 是,防止视图参数的工作被清除 涉及。我确定有一个简单的解决方案,但我就是看不出来 现在。

对于如何解决此问题的任何建议,我将不胜感激。

【问题讨论】:

    标签: jsf jsf-2


    【解决方案1】:

    我遇到的问题是,在注册页面上,我必须使用 new 获取 User 类的实例。

    那么,最初创建这个新用户实例的代码是什么?如果您在 preRenderView 处理程序中执行此操作,那么您可以简单地检查 null,不是吗?

    如果视图参数和转换器没有完成它们的工作,user 仍将为空,您将创建一个新实例。 bean 构造函数和@PostConstruct 在这里对你没有任何好处,因为它们都在视图参数执行它之前运行,但preRenderView 事件保证在它之后运行。

    @ManagedBean
    public class Bean {
    
        private User user;
    
        public void onPreRenderView() {
            if (user == null) {
                user = new User();
            }
        }
    }
    

    (需要额外考虑的是conversation scope 已经完全按照您在此处尝试执行的操作。这是 CDI 而非 JSF 的一部分,但如果您在 Java EE 6 Web Profile 中运行兼容的 AS(JBoss AS 6 或 7,Glassfish V3,Resin 4,...)你已经有了它。否则它只是一个额外的 jar。)

    【讨论】:

    • 嗨,Arjan,我试过了,可惜没用。我最近花了几天时间尝试使用 glassfish 3.1 进行焊接,但问题太多了,即使使用焊接 1.1.1 也是如此。我对 CDI 的最大问题是缺少视图范围,我想要走的路是 seam 3 @RenderScoped 或 Steven Verborgh 自定义视图范围。我现在几乎已经解决了这个问题,但现在是凌晨 3 点,我最好明天完成。感谢您的回复。
    • 关于 CDI 缺少 @ViewScoped,是的,这是一个大问题。但是Seam3 又添加了它。与 Seam2 不同,Seam3 包含许多小型便携式扩展,因此您只需将部分添加到您的应用程序中即可解决此问题,而不是添加所有内容。或者,如果您只需要会话范围,那么只有 1 个 bean 可以是 CDI 会话范围,而其他 bean 可以保持 JSF ManagedBeans(但这可能不是那么漂亮)。
    • 问题是 seam 3 与 glassfish 3.0.1/3.1 (seamframework.org/Seam3/Compatibility) 有很多兼容性问题我花了几天时间试图让 Verborgh 视图范围与 CDI 以及 Seam 一起工作3 @RenderScoped 两者都不适用于 glassfish。在对话范围内,我真的不知道何时结束对话,您如何处理浏览器后退按钮?我只是要使用会话映射。我最初的问题是,在视图之间,weakhashmap 中的数据被垃圾收集并且 jsf 不调用设置器。感谢您的 cmets。
    【解决方案2】:

    经过一年多的多次尝试,找到了可靠的长期解决方案 终于解决这个问题了!我找到了一个。解决方案的形式是 Apache Myfaces CDI 扩展项目,又名Myfaces CODI

    这提供了额外的范围,例如 @ViewAccessScoped,它确保 如果一个 bean 被一个页面引用,那么它可用于该页面。还 提供了对对话组的支持。在我想要的场景中 将对象引用从注册页面传递到注册确认页面, 确认页面可以在下一个请求时直接访问 registerView bean。 或者,您可以 @Inject 一个 bean 到另一个 bean 并在下一个访问它 请求,或使用源页面中的 f:setPropertyActionListener。

    Myfaces CODI 可与 Mojarra 以及 ajaxified 组件库一起正常工作 比如素面。这个概念类似于 Jboss Seam 提供的概念, 虽然我发现额外的范围支持需要更好地考虑,而且我已经 在 glassfish 3.1.1 上对此进行了测试,没有任何问题。

    如果您正在使用 javax.faces.bean 中的 @ManagedBean 和范围注释 打包在您的代码中,codi 拦截这些注释并使用它自己的 基于 CDI 的版本,因此您只需将 codi 添加为 依赖于您的项目,并且不更改任何代码。

    对我来说,这就像从黑白电视转向彩色电视,我希望我能 早点找到这个东西。

    CODI documentation

    【讨论】:

      猜你喜欢
      • 2021-05-02
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 2019-01-04
      • 1970-01-01
      • 2011-11-18
      • 2012-10-31
      相关资源
      最近更新 更多