如何使用CDI将http会话属性注入bean

时间:2015-03-04 12:57:25

标签: jsf session cdi managed-bean

我有一些遗留代码,使用以下代码将对象作为http会话属性放置:

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

旧的facelets使用

访问代码
 @ManagedProperty("#{attrname}")
 private MyObject object;

有没有办法使用CDI(@Inject)将此会话属性注入Bean?

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

2 个答案:

答案 0 :(得分:7)

在getter中使用@Produces @Named的会话作用域托管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
@Named("attrname")
private MyObject myObject;

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


或者,如果你真的打算保留通过ExternalContext#getSessionMap()设置实例的传统方式(例如因为它是第三方而你不能改变它),那么你也可以让生产者直接返回它从会议地图:

@SessionScoped
public class MyObjectProducer implements Serializable {

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

}

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

答案 1 :(得分:1)

这是非jsf和jsf工件的方法。

@Qualifier
@Retention(RUNTIME)
@Target({TYPE,METHOD,FIELD,PARAMETER});
public @interface SessionAttribute {

   @NonBinding
   String value() default "";
}

@ApplicationScope
public class SessionAttributeService {

  //Dont worry, this is a proxy, and CDI will ensure that the right one called at the right time.
  @Inject
  private HttpServletRequest servletRequest;

  @Produces
  @SessionAttribute
  @RequestScope
  public String sessionAttribute(final InjectionPoint ip){
     final SessionAttribute sa = ip.getAnnotated().getAnnotation(SessionAttribute.class);
     final HttpSession session = servletRequest.getSession();
     return session.getAttribute(sa.value());
  }
}

用例:

@RequestScope
public class MyServiceBean {

  @Inject
  @SessionAttribute("theAttribute")
  private String attribute;

}