我可以使用HttpSession对象作为Managed Bean中的实例变量。获取NotSerializableException异常

时间:2012-05-22 11:13:26

标签: jsf-2

我使用HttpSession作为实例变量,如

@ManagedBean
@ViewScoped
public class CountryPages_Detail {

    private HttpSession session;

    public CountryPages_Detail() {
        session = ConnectionUtil.getCurrentSession();
    } //end of constructor

    public String preview() {
        session.setAttribute("countryDetailImageNames", imageNames);
        session.setAttribute("countryDetailImages", images);
        session.setAttribute("countrySummary", countrySummary);        
        return "countryPages_View?faces-redirect=true";

    } //end of preview()
} //end of  class CountryPages_Detail

ConnectionUtl类:

 public static HttpSession getCurrentSession() {
     FacesContext facesContext = FacesContext.getCurrentInstance();
     ExternalContext externalContext = facesContext.getExternalContext();
     HttpServletRequest httpServletRequest = (HttpServletRequest) externalContext.getRequest();

     HttpSession currentSession = (HttpSession) externalContext.getSession(false);

     if (currentSession != null) {         
         return currentSession;
     } else {         
         return null;
     }
} //end of getCurrentSession()

我想问这是正确的方法吗?实际上我在我的web.xml中使用

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
</context-param>

但是当我把它更改为<param-value>client</param-value>时,首先我得到了一个异常,即我的一个类是不可序列化的,在使它可序列化之后我现在变得异常了

SEVERE: Error Rendering View[/index.xhtml]
java.io.NotSerializableException: org.apache.catalina.session.StandardSessionFacade
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
    ....

使用服务器时运行正常。为什么?我想问一下,当我们在param-value中服务器时,所有在viewScope(@ViewScoped)中的托管bean都驻留在服务器上,当我们将它更改为客户端时,我们所有的@ViewScoped托管bean都驻留在客户端上?另外如果我的bean不在@ViewScoped中,那么javax.faces.STATE_SAVING_METHOD元素是否会产生任何差异?意味着STATE_SAVING_METHOD选项仅涉及@ViewScoped,还是影响@RequestScope或@SessionScopr或其他范围? 感谢

1 个答案:

答案 0 :(得分:2)

你应该绝对不能将HttpSession之类的外部上下文资源作为实例变量。只需在threadlocal范围内检索它。您可以使用ExternalContext#sessionMap()管理会话属性映射,而无需在JSF代码中导入javax.servlet(这通常表明您做错了或笨拙的事情,从而你在不使用JSF的权力的情况下完全按照JSF的方式工作。

public String preview() {
    Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
    sessionMap.put("countryDetailImageNames", imageNames);
    sessionMap.put("countryDetailImages", images);
    sessionMap.put("countrySummary", countrySummary);        
    return "countryPages_View?faces-redirect=true";
}

但是,最好是创建一个会话范围的托管bean。你在那里就是一些奇怪的,而不是程序性的和非OO的设计。

@ManagedBean
@SessionScoped
public class Country {

     private List<Something> detailImageNames;
     private List<Something> images;
     private Something summary;

     // ...
}

您在CountryPagesDetail内使用以下内容:

@ManagedProperty("#{country}")
private Country country;

public String preview() {
    country.setDetailImageNames(imageNames);
    country.setDetailImages(images);
    country.setSummary(summary);        
    return "countryPages_View?faces-redirect=true";
}

#{country.detailImageNames}可以使用它等等。