2012-05-22 14 views
1

我使用HttpSession中像我可以使用HttpSession对象作为托管Bean中的实例变量。获得NotSerializableException异常

@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或其他作用域? 谢谢

回答

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}等。

+0

嗯感谢清除我在代码中做这样的事是不安全的:)。好的,如果我想从下一页的sessionMap中获取值,那么我再次在下一页的构造函数中获得像getExternalContext()。getSessionMap();这样的sessionMap,然后使用'sessionMap.get(“CountryDetailImageNames”)'获取来自地图的价值。我对吗?我起诉这个实例变量这么多地方....(担心)好吧,你的意思是,当我想在预览()方法中做的事情时,我总是使用sessionMap,正如你所建议的。好? – Basit

相关问题