将数据保存到 JSF 中的会话

发布于 2024-08-01 21:58:20 字数 821 浏览 4 评论 0原文

我是 J(2)EE 和 Web 应用程序开发领域的新手,但我很快就熟悉了它并学到了很多东西。 对我来说,每一天都是新发现的奇妙旅程。

我目前正在开发一个项目,在该项目中我在 Glassfish v2 上使用 Visual JSF Woodstock。 我对 JSF 也很陌生。

有时我需要在请求之间保存一些对象(例如 MyObject)。 根据到目前为止我所阅读和理解的内容,我需要使用会话在不同请求之间保存这些对象。 到目前为止,一切都很好。

具体如何做到这一点是我关心的地方。 我知道在 JSP 中您可以使用 session.setAttribute("myObj", myObject) ,它会使用 cookie 或 url 重写或隐藏表单变量在客户端保存对象。

另一方面,在 JSF 中,我使用会话作用域 bean,例如 SessionBean1,并将对象保存为 SessionBean1 属性(例如 SessionBean1.setSomeOjb(myObj))。 这是正确的处理方式吗?

我猜测这样做会导致服务器端的内存利用率增加,因为每个请求都会创建会话作用域 bean 的新实例 SessionBean1 加上 SessionBean1 中保存的 myObject 实例所使用的内存。

我读到您可以使用 FacesContext.getExternalContext().getSession/getSessionMap() 来在客户端保存会话变量。

那么您建议我使用哪种方法 - 会话作用域 bean 或 sessionmap 来保存对象以便在会话请求之间进行访问?

谢谢。

I am new to the world of J(2)EE and web app development but am quickly navigating my way around it and learning a lot. Every day is a fantastic voyage of new discovery for me.

I am currently working on a project in which I am using Visual JSF Woodstock on Glassfish v2. I am pretty new to JSF also.

There are times when I need to save some objects (say MyObject for instance) between requests. And from what I have read and understood so far, I need to be using sessions to save these objects between different requests. So far so good.

Exactly how to do this is where my concern lies. I know that in JSP you can use the session.setAttribute("myObj", myObject) which would save the object at client side using cookies or url rewrites or hidden form variables.

On the other hand, in JSF I use Session scoped beans, say SessionBean1 for e.g., and save objects as SessionBean1 properties (e.g. SessionBean1.setSomeOjb(myObj)). Is this the right way to go about with this?

I am guessing that doing it this way will result in increased memory utilization at the server end since each request will create a new instance of the session scoped bean, SessionBean1 plus the memory utilized by the saved myObject instances in SessionBean1.

I have read that you can use FacesContext.getExternalContext().getSession/getSessionMap() which would save session variables at client side.

So which method would you suggest that I use - the session scoped bean or the sessionmap to save objects for access between requests for a session?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

顾挽 2024-08-08 21:58:20

一般来说,Java EE Web 应用程序往往不希望在客户端保存会话数据。 您对服务器端会话膨胀的担忧是正确的,一个常见的问题是会话占用空间巨大,这可能会导致严重的资源和性能问题,尤其是在集群环境中。

我想知道你在哪里看到的

我读到您可以使用 FacesContext.getExternalContext().getSession/getSessionMap() ,它将在客户端保存会话变量。

我相信(在这一点上纠正我)这只是提供对 HttpSession 对象的访问,然后您可以在该对象上使用相同的对象,

 session.setAttribute("myObj", myObject)

它本身并不将对象发送回客户端,它保存在服务器中并由某个会话键入标识符,通常在 cookie 中传递。

现在还有另外两种技术:您可以明确选择将数据放入您自己制造的 cookie 中 - 您可以从 JSF 或 JSP 访问的 servlet API 可以让您这样做,或者您可以在表单上使用隐藏字段,以及因此传递 aorund 会话数据。

但考虑一下这一点。 根据我使用的应用程序服务器的经验,1k-4k 数量级的 HttpSession 往往不会出现问题。 大于此值(我见过以兆字节为单位的会话)确实会给基础设施带来压力。 如果您担心这种大小的会话,您是否希望在每次请求时将 Cookie 或隐藏字段中的兆字节数据发送回浏览器? 即使1k-2k也可能有点大了。

所以建议:

  1. 保持简单。 使用 Session API 或其 JSF 表现形式。

  2. 控制会话中的数据量。

为响应有关集群的问题而添加:

通常,在集群环境中,我们具有会话关联性,以便请求被发送回同一集群成员。 但是,我们仍然需要考虑请求发送到不同服务器时的情况(也许集群成员发生故障)。

一些应用程序服务器供应商提供会话复制,或者通过直接服务器间通信,或者通过将会话保存到数据库 - 显然这里存在开销,因此有时,对于低价值会话,我们只是接受在发生故障时会话丢失。

有一种观点认为,如果会话数据具有很高的价值,那么它应该由应用程序保留,它实际上是业务数据,应该这样对待。 Cloudant 或 MongoDb 等 NOSQL 数据库越来越多地用于此目的。 在这种情况下,我们可以将 HTTP 会话视为缓存,因为我们知道在发生错误时可以检索会话数据。

因此,我认为购物车很可能对企业具有相当大的价值; 它代表了顾客对他们想花钱买的东西的深思熟虑的积累。 所以它应该被持久化,而不是仅仅保留在会话中。 一旦我们决定坚持它,我们就会发现它会带来其他有趣的场景,例如跨许多客户端设备的整合体验。 客户开始在家中使用台式电脑购物,但在线完成购买。

所以还有一个原则:

3)。 不要仅仅因为 HTTP 会话存在就过度使用它。 考虑数据的商业价值以及是否应该持久化。

In general Java EE Web Apps tend not to expect to save session data client side. You're right to be concerned about session bloat on the server side, a common problem seen is to have huge session footprints which can cause significant resource and performance issues, and can be especially in clustered environments.

I'd like to know where you see

I have read that you can use FacesContext.getExternalContext().getSession/getSessionMap() which would save session variables at client side.

I believe (correct me on this point) that this simply gives access to the HttpSession object, on which you can then use the same

 session.setAttribute("myObj", myObject)

this does not in itself send the object back to the client, it's held in the server and keyed by some session identifier, usually passed in a cookie.

Now there are two other techniques: you could explicitly choose to put data into a cookie of your own manufacture - the servlet APIs that you can access from JSF or JSP would let you do that, or you can use hidden fields on your forms, and hence pass aorund session data.

But consider this. A rule of thumb on the App Server I use is that HttpSession of the order of 1k-4k tend not to be a problem. Larger than that (and I have seen sessions of measured in megabytes) do stress the infrastructure. If you were concerned about sessions of that size would you expect to send megabytes of data in a cookie or hidden field back to the browser on every request? Even 1k-2k is probably a bit big.

So recommendations:

  1. Keep it simple. Use the Session API, or its JSF manifestation.

  2. Keep the amount of data in the session under control.

Added in response to question about clustering:

Typically, in a clustered environment we have session affinity, so that requests are sent back to the same cluster member. However we still need to consider the case (perhaps if a cluster members fails) when the request goes to a different server.

Some App Server vendors offer session replication, either via direct inter-server communication or by persisting the session to a database - obviously there are overheads here, so sometimes, for low value sessions we just accept the loss of session in event of failure.

There is an argument that if the session data has high value then it should be persisted by the application, it's actually business data and should be treated as such. Increasingly, NOSQL databases such as Cloudant or MongoDb are used for this. In this case we may think of the HTTP session as a cache, in the knowledge that the session data can be retrieved in the event of error.

So I'd argue that a Shopping Cart may well have considerable value to the business; it represent the customers thoughtful accumulation of things they want to spend money on. So it should be persisted, rather then just kept in the session. Once we decide to persist it, then we find that it leads to other interesting scenarios such as a consolidated experience across many client devices. The customer starts shopping at home on a desktop PC, but completes the purchase online.

So a further principle:

3). Don't over-use the HTTP session just because it's there. Consider the business value of the data and whether it should be persisted.

梦在深巷 2024-08-08 21:58:20

我正在和我的同事一起做一个大学的项目,是一个像GoogleImage Labeler这样的网络。
好吧,我们有一个 UserController,它有登录、注销等方法……我们的会话范围如下:

@ManagedBean(name = "userController")
@SessionScoped

好的,这就是 NetBeans 向导为您创建的内容。

我们创建和管理会话的方法是:

注册方法(我们在 XHTML 中使用表单的属性...)中,我们将用户保存在数据库中,然后添加会话中的值:

FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("user", current);

其中“当前”是用户(当然是登录的用户)。
我们的登录方法也是如此。

注销方法中,我们有:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

希望这对您有所帮助。

I'm working on a project of the university with my colleagues, is a web like GoogleImage Labeler.
Well, so we have an UserController, with its methods login, logout, etc... and we scope the session like this:

@ManagedBean(name = "userController")
@SessionScoped

Ok, this is what the wizard of NetBeans creates for you.

Our way of creating and managing the session is:

At the register method (in which we use the attributes of the form in the XHTML...) we persist the user in the DB and then we add the values in the session:

FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("user", current);

Where "current" is an User (The logged user, of course).
We have the same at the login method.

At the logout method we have:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

I hope this helps you.

迷乱花海 2024-08-08 21:58:20

那么您建议我使用哪种方法 - 会话范围 bean 或会话映射来保存对象以便在会话请求之间进行访问?

这两个东西将数据存储在完全相同的位置。

<managed-bean>
  <managed-bean-class>foo.Bar</managed-bean-class>
  <managed-bean-name>bar</managed-bean-name>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

在表达式中引用后,您可以通过 外部上下文

仅供参考:在 JSF2 中,可以删除声明并用注释替换:

@ManagedBean(name="bar") @SessionScoped
public class Bar {
...

So which method would you suggest that I use - the session scoped bean or the sessionmap to save objects for access between requests for a session?

These two things store data in exactly the same place.

<managed-bean>
  <managed-bean-class>foo.Bar</managed-bean-class>
  <managed-bean-name>bar</managed-bean-name>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Once referenced in an expression, you can lookup "bar" programmatically via the external context.

FYI: in JSF2, the declaration can be removed and replaced with annotations:

@ManagedBean(name="bar") @SessionScoped
public class Bar {
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文