我正在使用 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)。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!