如何在JSF 2.0/2.1中用CDI替换@ManagedBean/@ViewScope

sta*_*ker 24 jsf cdi jsf-2 view-scope

我目前正在使用RichFaces评估Java EE 6/JSF 2.1.

声明为的bean

@ManagedBean
@ViewScoped
Run Code Online (Sandbox Code Playgroud)
  1. 获取ID集(以准备例如删除操作).
  2. 通过JSF显示确认弹出窗口.
  3. 如果用户确认,则调用delete方法并删除在步骤1中存储了ID的行.

由于CDI bean没有ViewScope,我试图将bean声明为:

@Named
@ConversationScoped
Run Code Online (Sandbox Code Playgroud)

现在,处理在步骤3中失败,因为步骤1中设置的值(已选中)不再可用.

我必须使用Conversation.begin()和Conversation.end()方法吗?

如果是这样,哪里可以调用它们的好地方?

Bal*_*usC 52

如果您可以升级到JSF 2.2,请立即执行.它@ViewScoped为CDI 提供原生注释.

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

或者,安装OmniFaces,它将自己的CDI兼容@ViewScoped,包括工作@PreDestroy(在JSF上打破@ViewScoped).

import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是安装MyFaces CODI,它将JSF 2.0/2.1透明地连接@ViewScoped到CDI.这只会向URL添加一个自动生成的请求参数(就像@ConversationScoped那样).

import javax.faces.bean.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果你真的需要使用@ConversationScoped,那么你确实需要开始和结束它.你需要@Inject一个Conversation和调用begin()的@PostConstruct,并end()在交谈中,通常会被重定向到一个新的视图操作方法的最新举措.

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;

@Named
@ConversationScoped
public class Bean implements Serializable {

    @Inject
    private Conversation conversation;

    // ...

    @PostConstruct
    public void init() {
        conversation.begin();
    }

    public String submit() {
        // ...

        conversation.end();
        return "some.xhtml?faces-redirect=true";
    }

}
Run Code Online (Sandbox Code Playgroud)

也可以看看:


小智 6

我认为您可以从CDI扩展中受益,以创建自己的范围,以便您可以实现上下文并使用@NormalScope.

  • AfterBeanDiscovery每次bean调用后,CDI都会触发一个事件
  • 您可以@Observes对此事件使用CDI扩展并添加上下文实现
  • 在您的范围实现中,您可以:
    1. 用于Contextual从名称中获取bean,FacesContext ViewRoot Map并在每次ajax回调后返回它
    2. 使用CreationalContext如果从第一步bean的名字没有找到在创建它FacesContext ViewRoot Map

有关更深入的解释,我建议此链接:http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/