我正在使用 Spring 和 JSF 2 创建一个 Web 应用程序。
业务对象保存在 Spring 容器中,我使用 @ManagedProperty 将它们注入(inject)托管 Bean,如下所示:
@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
@Getter @Setter
@ManagedProperty("#{someService}")
private SomeService someService;
// ...
问题是,我不断收到
NotSerializableException
对于 SomeService bean 正在使用的 Spring (ServiceLocatorFactoryBean) 类。
如果我成功了
transient
,我怎么能在反序列化后重新注入(inject)它?
或者,还有什么其他方法可以解决这个问题?
我一直在阅读其他几个类似的问题,但找不到任何与此问题完全相关的问题。
请您参考如下方法:
而不是通过 @ManagedProperty
中的 EL 注入(inject) Spring bean注解(在 ManagedBean 初始化时执行),获取在运行时评估 EL 的 bean。
使用这种方法,JSF bean 应该是这样的:
@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return SpringJSFUtil.getBean("someService");
}
// ...
以及通过 EL 获取 bean 的实用程序类 SpringJSFUtil.java:
import javax.faces.context.FacesContext;
public class SpringJSFUtil {
public static <T> T getBean(String beanName) {
if (beanName == null) {
return null;
}
return getValue("#{" + beanName + "}");
}
@SuppressWarnings("unchecked")
private static <T> T getValue(String expression) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context,
expression, Object.class);
}
}
这消除了 Spring bean 属性(以进行更多 EL 评估为代价),从而避免了首先拥有该属性的所有序列化问题。
同样的方法,使用 OmniFaces :
在我的实际代码中,我使用
evaluateExpressionGet(String expression)
utility class 的方法可从
OmniFaces 获得.所以,对于那些也使用它的人来说,这就是我的代码的真实样子:
import static org.omnifaces.util.Faces.evaluateExpressionGet;
@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
private static SomeService someService() {
return evaluateExpressionGet("#{someService}");
}
// ...
请注意,这里的方法获取完整的 EL(“#{expression}”),而不仅仅是 Spring bean 名称(或者您会得到 ClassCastException)。