如何使用 CDI 将 http 会话属性注入 bean
How to inject a http session attribute to a bean using CDI
我有一些旧代码使用如下代码将对象作为 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 的新代码中,创建和注入需要以受控方式创建的对象的更好方法是什么。
在 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
直到您将其实际设置为制作人 class.
的 属性
或者,如果您真的打算保留通过 ExternalContext#getSessionMap()
设置实例的传统方式(例如,因为它是第三方,因此您无法更改它),那么您也可以让生产者 return 它直接来自会话映射:
@SessionScoped
public class MyObjectProducer implements Serializable {
@Produces
@Named("attrname")
public MyObject getMyObject() {
return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname");
}
}
然而,当注入到非 JSF 工件中时,这不能保证工作,例如任意 @WebServlet
,因为 FacesContext#getCurrentInstance()
显然会 return 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;
}
我有一些旧代码使用如下代码将对象作为 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 的新代码中,创建和注入需要以受控方式创建的对象的更好方法是什么。
在 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
直到您将其实际设置为制作人 class.
或者,如果您真的打算保留通过 ExternalContext#getSessionMap()
设置实例的传统方式(例如,因为它是第三方,因此您无法更改它),那么您也可以让生产者 return 它直接来自会话映射:
@SessionScoped
public class MyObjectProducer implements Serializable {
@Produces
@Named("attrname")
public MyObject getMyObject() {
return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname");
}
}
然而,当注入到非 JSF 工件中时,这不能保证工作,例如任意 @WebServlet
,因为 FacesContext#getCurrentInstance()
显然会 return 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;
}