我是J(2)EE和Web应用程序开发世界的新手,但我很快就在我身边学习并学习了很多东西.每一天都是我新发现的奇妙之旅.
我目前正在开发一个项目,我在Glassfish v2上使用Visual JSF Woodstock.我对JSF也很陌生.
有时我需要在请求之间保存一些对象(例如MyObject).从我到目前为止所阅读和理解的内容来看,我需要使用会话来在不同请求之间保存这些对象.到现在为止还挺好.
究竟如何做到这一点是我担心的地方.我知道在JSP中你可以使用session.setAttribute("myObj", myObject)
使用cookie或url重写或隐藏的表单变量来保存客户端对象.
另一方面,在JSF中,我使用Session scoped bean,比如说SessionBean1,并将对象保存为SessionBean1属性(例如SessionBean1.setSomeOjb(myObj)
).这是正确的方法吗?
我猜这样做会导致服务器端的内存利用率增加,因为每个请求都会创建会话范围bean的新实例,SessionBean1加上SessionBean1中保存的myObject实例使用的内存.
我已经读过你可以使用FacesContext.getExternalContext().getSession/getSessionMap()
哪个会在客户端保存会话变量.
那么您建议我使用哪种方法 - 会话范围bean或会话映射来保存对象以便在会话请求之间进行访问?
谢谢.
通常,Java EE Web Apps往往不希望保存会话数据客户端.你担心服务器端的会话膨胀是正确的,常见的问题是会有巨大的会话占用空间,这可能会导致严重的资源和性能问题,特别是在集群环境中.
我想知道你在哪里看到
我已经读过你可以使用FacesContext.getExternalContext().getSession/getSessionMap()来保存客户端的会话变量.
我相信(在这一点上纠正我),这只是访问HttpSession对象,然后你可以使用它
session.setAttribute("myObj", myObject)
这本身并不将对象发送回客户端,它保存在服务器中并由一些会话标识符键入,通常在cookie中传递.
现在还有另外两种技术:您可以明确选择将数据放入您自己制造的cookie中 - 您可以从JSF或JSP访问的servlet API可以让您这样做,或者您可以在表单上使用隐藏字段,以及因此传递了aorund会话数据.
但考虑一下.我使用的App Server的经验法则是1k-4k量级的HttpSession不会成为问题.比那更大(我已经看到以兆字节为单位的会话)会给基础设施带来压力.如果您担心该大小的会话,您是否希望在每次请求时将cookie或隐藏字段中的兆字节数据发送回浏览器?即使1k-2k也可能有点大.
所以建议:
把事情简单化.使用Session API或其JSF表现形式.
保持会话中的数据量受到控制.
在回答有关群集的问题时添加:
通常,在集群环境中,我们具有会话关联,因此请求将发送回同一个集群成员.但是,当请求转到另一台服务器时,我们仍需要考虑这种情况(可能是一个集群成员失败).
一些App Server供应商通过直接的服务器间通信或通过将会话持久保存到数据库来提供会话复制 - 显然这里存在开销,因此有时候,对于低价值会话,我们只接受失败时的会话丢失.
有一种观点认为,如果会话数据具有较高的值,那么它应该由应用程序保留,它实际上是业务数据,应该这样处理.越来越多地使用NantQL数据库,例如Cloudant或MongoDb.在这种情况下,我们可以将HTTP会话视为一个缓存,知道在发生错误时可以检索会话数据.
所以我认为购物车可能对业务有相当大的价值; 它代表了客户对他们想要花钱的东西的深思熟虑的积累.因此它应该被持久化,而不是仅仅保留在会话中.一旦我们决定坚持下去,我们就会发现它会导致其他有趣的场景,例如跨多个客户端设备的整合体验.客户在台式PC上开始在家购物,但在线完成购买.
所以进一步的原则:
3).不要因为它在那里而过度使用HTTP会话.考虑数据的业务价值以及是否应该持久化.
我和同事一起在大学开展项目,像GoogleImage Labeler这样的网络.好吧,所以我们有一个UserController,它的方法是login,logout等...我们的会话范围如下:
@ManagedBean(name = "userController") @SessionScoped
好的,这就是NetBeans向导为您创建的内容.
我们创建和管理会话的方式是:
在register方法(我们在XHTML中使用表单的属性...)中,我们将用户保留在DB中,然后我们在会话中添加值:
FacesContext context = FacesContext.getCurrentInstance(); context.getExternalContext().getSessionMap().put("user", current);
"当前"是用户(当然是登录用户).我们在登录方法上也一样.
在注销方法中,我们有:
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
我希望这可以帮助你.