问题描述
我有以下托管bean:
I have the following managed beans :
@ApplicationScoped
public class ApplicationBean {
// ...
}
@SessionScoped
public class SessionBean implements Serializable {
@ManagedProperty("#{applicationBean}")
private ApplicationBean applicationBean;
// ...
}
这被部署到具有多个节点的服务器群集中.当HTTP会话在另一个节点上序列化时会发生什么?
This is deployed to a server cluster with several nodes. What will happen when the HTTP session will be serialized on another node?
ApplicationBean
未序列化,因为它未实现Serializable
.它会被@ManagedProperty
重新注入吗?还是实际上会以某种方式进行序列化?
ApplicationBean
is not serialized because it doesn't implement Serializable
. Will it be re-injected by @ManagedProperty
? Or will it actually be serialized somehow?
推荐答案
所有HTTP会话属性也将被序列化,包括会话范围内的JSF托管bean.任何不能序列化的bean属性都将被跳过.在另一个节点上反序列化期间,您将在所有无法序列化的bean属性上面对一个NotSerializableException
.标记属性transient
将解决该异常,但是反序列化后,该属性仍将保留null
.
All HTTP session attributes will be serialized as well, including session scoped JSF managed beans. Any bean properties which are not serializable will be skipped. During deserialization on another node, you will face a NotSerializableException
on all bean properties which are not serializable. Marking the property transient
will fix that exception, but the property will still remain null
after deserialization.
不.它不会被重新注入.在@ManagedProperty
的情况下,您必须手动进行此操作.
Nope. It won't be re-injected. You have to take care of this manually in case of @ManagedProperty
.
一种天真且容易出错的方法是摆脱@ManagedProperty
并在getter中执行延迟加载(因此,自己扮演代理的角色):
One somewhat naive and error-prone way is getting rid of @ManagedProperty
and performing lazy loading in the getter (thus, act like a proxy yourself):
private transient ApplicationBean applicationBean;
public ApplicationBean getApplicationBean() {
if (applicationBean == null) {
FacesContext context = FacesContext.getCurrentInstance();
applicationBean = context.getApplication().evaluateExpressionGet(context, "#{applicationBean}", ApplicationBean.class);
}
return applicationBean;
}
,并在整个代码中使用getter,而不是直接引用属性.
and use the getter throughout the code instead referencing the property directly.
更好的方法是使其成为EJB或CDI管理的bean.它们是完全透明创建的,并作为可序列化的代理注入,您无需担心对其进行序列化.
The better way is to make it an EJB or a CDI managed bean. They're fully transparently created and injected as serializable proxies and you never need to worry about serialization on them.
因此,要么将其设为EJB:
Thus, either make it an EJB:
import javax.ejb.Singleton;
@Singleton
public class ApplicationBean {
// ...
}
import javax.ejb.EJB;
import.javax.faces.bean.ManagedBean;
import.javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class SessionBean implements Serializable {
@EJB
private ApplicationBean applicationBean;
// ... (no setter/getter necessary!)
}
或者,使它们都成为CDI托管的bean:
Or, make them both CDI managed beans:
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
@Named
@ApplicationScoped
public class ApplicationBean {
// ...
}
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@SessionScoped
public class SessionBean implements Serializable {
@Inject
private ApplicationBean applicationBean;
// ... (also here, no setter/getter necessary!)
}
这篇关于将不可序列化的应用程序作用域的bean注入为集群中可序列化会话作用域的bean的托管属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!