JSF通过引用传递视图参数——当对象必须实例化时



假设我有一个注册页面&注册确认页面。输入user详细信息进入注册页面,导航到注册确认页面如果有错误,我可以返回到寄存器页。

我将使用视图参数使注册数据可用从注册页到确认页,反之亦然

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

所以我要做的是将寄存器页上的数据输入到属性,并将对该记录的引用发送到寄存器确认页面。什么给了我一个想法是看到BalusC WeakHashMap转换器。这是一个JSF转换器,它具有静态弱散列映射和生成一个uid作为映射项的值,并将对象引用作为关键。通过指定这个作为f:viewParam的转换器查询字符串中的uid。

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

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

(等等…),并将用户实例作为视图参数传递。它工作得很好注册到确认页面。问题是,当我执行将用户引用发送回寄存器页确认页我绝对不能阻止注册页背靠bean从重新实例化用户对象开始,在 setter被调用之后作为view参数的结果。

因此转换器完成它的工作并从哈希映射,调用后台bean中的setUser(),然后我看到User类的构造函数。

我已经尝试调用新的用户()从bean构造器,在@PostConstruct,在preenderview(也检查如果ajax请求),但没有我尝试如果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)

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

这提供了额外的作用域,例如@ViewAccessScoped,它可以确保如果一个bean被一个页面引用,那么它对于那个页面是可用的。也提供了对会话组的支持。在我想要将对象引用从寄存器页传递到寄存器确认页在下一次请求时,confirm页面只能直接访问registerView bean。或者,您可以@Inject一个bean到另一个bean中,并在下一个bean中访问它请求,或者从源页面使用f:setPropertyActionListener。

Myfaces CODI可以很好地与Mojarra和ajax组件库一起工作比如质面。这个概念类似于Jboss Seam所提供的,尽管我发现额外的作用域支持需要更好的考虑,我已经在glassfish 3.1.1上进行了测试,没有问题。

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

对我来说,这就像从黑白电视转到彩色电视,我希望我能

CODI文档

最新更新