假设我有一个注册页面&注册确认页面。我输入用户 详细信息进入注册页面,导航到注册确认页面 如果有任何错误,我可以返回注册页面。
我将使用视图参数来提供注册数据 从注册页面到确认页面,反之亦然。
假设有20项数据要在页面之间移动,那就是 很多视图参数和很多setPropertyActionListeners,尤其如此 因为所有数据最终都会很好地打包在User对象中。
所以我想要做的是将注册页面上的数据输入到 用户记录的属性并将其引用发送到寄存器 确认页面。给我一个想法的是看到BalusC WeakHashMap 转换器。这是一个JSF转换器,它有一个静态弱哈希映射和 生成一个uuid作为映射条目的值,并将对象引用生成为 钥匙。因此,通过将此指定为f:viewParam的转换器,您可以发送 查询字符串中的uuid。
这很好用。我遇到的问题是我必须在注册页面上 用new获取User类的实例。然后我可以做:
<h:inputText value="#{bean.user.firstname}"/>
(etc ...),并将用户实例作为视图参数传递。它工作得很好 注册到确认页面。问题是当我执行时 反向,将用户引用发送回寄存器页面 确认页面我绝对无法阻止注册页面支持bean 通过重新实例化用户对象, 之后调用了setter 作为view参数的结果。
所以转换器完成它的工作并从中检索User对象 哈希映射,在支持bean中调用setUser(),然后我看到了 User类触发的构造函数。
我试过在@PostConstruct中的bean构造函数中调用新的User(), 在preRenderView(也检查ajax请求),但我没有尝试 如果是新的,则阻止视图参数的工作被消除 参与其中。我确信这是一个简单的解决方案,但我看不出来 现在
如果有任何关于如何解决这个问题的建议,我将不胜感激。
答案 0 :(得分:3)
我遇到的问题是,在注册页面上,我必须使用new获取User类的实例。
那么最初创建这个新用户实例的代码是什么呢?如果你在preRenderView
处理程序中执行此操作,那么您可以只检查null,不是吗?
如果视图参数和转换器尚未完成其工作,user
仍为空,您将创建一个新实例。 bean构造函数和@PostConstruct
在这里对你没有任何好处,因为它们都在view参数执行之前运行,但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。)
答案 1 :(得分:1)
经过一年多的尝试,找到了可靠的长期解决方案 到了这个问题,终于来了!我找到了一个。解决方案的形式是 Apache Myfaces CDI扩展项目,又名Myfaces CODI。
这提供了额外的范围,例如@ViewAccessScoped,以确保这一点 如果页面引用了bean,那么它可用于该页面。也 提供的是对话组的支持。在我想要的场景中 将对象引用从寄存器页面传递到寄存器确认页面 确认页面可以直接在下一个请求中访问registerView bean。 或者,您可以@Inject一个bean到另一个bean并在下一个访问它 请求,或者从源页面使用f:setPropertyActionListener。
Myfaces CODI可以与Mojarra以及ajaxified组件库一起使用 如primefaces。这个概念类似于Jboss Seam提供的, 虽然我发现额外的范围支持需要更好地考虑,我已经 在glassfish 3.1.1上对此进行了测试,没有任何问题。
如果您正在使用来自javax.faces.bean的@ManagedBean和范围注释 在你的代码包中,codi拦截这些注释并使用它自己的注释 基于CDI的版本,因此只需添加codi即可转换为CDI 依赖于您的项目而不更改任何代码。
对我而言,这就像是从黑白电视转向彩电,我希望我能 很快发现了这个东西。