我有一些旧代码,使用以下代码将对象作为http session 属性:

MyObject object = new MyObject();
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("attrname", object);

旧的facelets使用以下代码访问代码
 @ManagedProperty("#{attrname}")
 private MyObject object;

有什么方法可以使用CDI(@Inject)将该 session 属性注入(inject)Bean?

在使用CDI的新代码中,更好的方法是创建和注入(inject)需要以受控方式创建的对象。

最佳答案

在具有getter上的 @Produces @Named的 session 范围内的受管bean中获取它。

@SessionScoped
public class MyObjectProducer implements Serializable {

    private MyObject myObject;

    @Produces
    @Named("attrname")
    public MyObject getMyObject() {
        return myObject;
    }

    public void setMyObject(MyObject myObject) {
        this.myObject = myObject;
    }

}

当您通过某种方式进行设置时myObjectProducer.setMyObject(myObject)在其他地方(或CDI @Observes 事件),然后可以使用@Inject @Named将其注入(inject)到任何地方。
@Inject
@Named("attrname")
private MyObject myObject;

是的,它仍然可以通过EL中的#{attrname}正常使用。不,它不会在未设置时自动创建,它将保留为null,直到您将其实际设置为生产者类的属性为止。

另外,如果您确实打算保留通过ExternalContext#getSessionMap()设置实例的旧方法(例如,因为它是第三方,因此您不能更改它),那么您也可以让生产者直接从 session 映射中返回它:
@SessionScoped
public class MyObjectProducer implements Serializable {

    @Produces
    @Named("attrname")
    public MyObject getMyObject() {
        return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname");
    }

}

但是,当注入(inject)非JSF工件(例如任意@WebServlet)时,不能保证此方法有效,因为FacesContext#getCurrentInstance()显然会返回null

10-07 13:11
查看更多