Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jsf 如何使用CDI向bean注入http会话属性_Jsf_Session_Cdi_Managed Bean - Fatal编程技术网

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

Jsf 如何使用CDI向bean注入http会话属性,jsf,session,cdi,managed-bean,Jsf,Session,Cdi,Managed Bean,我有一些遗留代码,使用如下代码将对象作为http会话属性: MyObject object = new MyObject(); Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap(); sessionMap.put("attrname", object); 是否有任何方法可以使用CDI(@Inject)将此会话属性注入Bean 在使

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

MyObject object = new MyObject();
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("attrname", object);
是否有任何方法可以使用CDI(
@Inject
)将此会话属性注入Bean


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

在会话范围的托管bean中使用getter上名为
@的
获取它

@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;
    }

}
当您以某种方式通过其他地方(或者可能是CDI事件)设置它时,您可以使用
@inject@Named
将其注入任何地方,例如
myObjectProducer.setMyObject(myObject)

@Inject
@Named("attrname")
private MyObject myObject;
是的,它仍然可以通过EL以通常的方式通过
{attrname}
获得。不,它不会在未设置时自动创建,它将保持
null
,直到您实际将其设置为producer类的属性


或者,如果您确实希望保留通过
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

,对于非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;

}

感谢@BalusC提供了快速而完整的答案。也许答案可以更完整地说,对于从非托管代码访问生产者,可以使用此代码
CDI.current().select(MyObjectProducer.class).get()
。这不能像OP要求的那样注入非字符串值。一般来说,对于“会话属性”,我绝对不会称之为“要走的路”。真的@BalusC我只是给出了一个使用字符串的示例,他可以简单地将类型更改为他想要的任何类型???
@RequestScope
public class MyServiceBean {

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

}