Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1530093
  • 博文数量: 3500
  • 博客积分: 6000
  • 博客等级: 准将
  • 技术积分: 43870
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-03 20:31
文章分类

全部博文(3500)

文章存档

2008年(3500)

我的朋友

分类:

2008-05-04 19:55:12

一起学习
对于在客户机而不是服务器上存储会话数据,有两种主要的解决方案 - cookie 和隐藏域(hidden field)- 每一种方案都有各自的优势和劣势。 隐藏域 出现的第一种保留会话数据的机制之一是使用“隐藏域”。这种选择依赖于 HTML 的一个特殊功能来保存会话信息。HTML INPUT 标记有几种不同的类型,可以让 Web 作者指定如何接收输入。例如,“TEXT”类型会导致浏览器显示一个文本域。然而,有一种输入类型不符合任何特定的 UI 部件:“HIDDEN” 类型。隐藏域没有 UI 表现形式,所以不能被浏览器用户改变。隐藏域的值可以在 Web 页面上由应用服务器设置,以后再通过 HTTPServletRequest 接口的 getParameter() 方法读取回来,就好像其它所有 HTML 域一样。这正是我们在客户机 HTML 中记录会话信息所需要的。使用隐藏域存储会话数据的一个主要缺点是,我们必须改写 HTML 使其包括这些新的信息。下面的 Java 代码指出要做下面的工作: out.print("input type=\"HIDDEN\"); out.print("NAME=\"FieldName\" value=\""); out.print(fieldValue); out.println("\"\>"); 隐藏域使用很简单,正因如此,它们也存在一些问题以至于对很多系统来说不适用。第一个问题是,JSDK 没有提供一种将任意对象移出和移入隐藏域的方法。在 JSDK 中,处理隐藏域的方法和处理其它 HTTP 参数的方法是一样的,也就是说隐藏域是作为字符串来处理的。如果您想在自己的程序中使用这些字符串里面的信息,就必须建立一个架构用来生成合适的 HTML 和重新解析信息。 另一个缺点是,您的会话信息最终会在网络上发送很多次。为了理解这是怎样发生的,考虑下面的情况: 我们的酒类购物站点有一个两页的“频繁顾客程序”。第一页接收用户信息(姓名、地址等),而第二页接收选择信息(您更喜欢加州酒还是法国酒?您喜欢夏敦埃酒还是墨尔乐红葡萄酒?诸如此类等等)。第一个 servlet 从前一个 HTML 表单中解析出用户信息,并将其记录在隐藏域中。第二个 servlet 不仅必须解析出新的 HTML 表单信息,还要解析出前一个 servlet 重新写入隐藏域的信息。这样,每一个后续的页面不断地增加要解析的信息,当您进一步继续处理时就会使下载时间变长。 使用隐藏域的一个最大的缺点存在于混合型的站点中。新的 servlet 实现必须与旧的 CGI 和 HTML 共存很多次。如果您不能修改这些页面,当用户在 servlet 和旧的页面之间遍历时,隐藏数据就会丢失。 假定我们的酒类购物站点一直是用 CGI 程序实现的。并且假定旧的购物车是作为 来实现的。站点中目前所有的 HTML 页面都指向这个 URL。我们可以改变所有的页面让它们指向 ,或者我们可以简单地用旧的链接给 servlet 起一个别名。如果您有数百个目录页指向这个链接,这个别名可以省掉您很多时间。然而,如果您是用隐藏域遍历站点,这种解决方法就不起作用。隐藏域必须添加到旧的 HTML 中,而且您可能还要改变这些链接。 使用隐藏域还有其它的缺点(请参阅下面章节有关安全性的讨论),但是对于某些情况,他们还是不错的。在安全性不高的某些站点中可以考虑它们,那里旧页面浏览最少,而且页面不是大量地“建立”在彼此之上,还有在不能接受服务器亲缘关系的地方也可以考虑它们。在为隐藏域的生成而建立框架和解析这两个步骤上付出的一些简单的努力以后可能会带来很多好处。然而,正如我们所见到的,对于大多数情况,都会有更好的解决方案。 Cookie 我们要研究的下一个存储会话数据的方法是直接在 cookie 中存储数据。正如我们在 HTTPSessions 的讨论中已经看到的,cookie 也可以用于在客户机浏览器上存储信息。它们不仅可以用于存储客户机身份标识,还可以存储实际的会话数据本身。cookie 有巨大的优势。 首先,cookie 不需要 HTML 重写。您将会话数据转换成如隐藏域示例所示的字符串,然后将其添加到您的 HttpServletResponse 对象中,如下所示: package com.winesrus.tests; import javax.servlet.http.*; public class CookieTest { public CookieTest(HttpServletResponse resp, String state) { String warning = Please accept this Cookie or bad things will happen to you!" Cookie cookie = new Cookie("winecookie", state); cookie.setDomain(".winesrus.com"); cookie.setPath("/"); cookie.setComment(warning); cookie.setVersion(0); resp.addCookie(cookie); } } 您可以用以下语句检索 cookie: javax.servlet.http.HttpServletRequest.getCookies(); 就是这样。您没有必要重写 HTML 页面来获取和设置 cookie 数据。 关于 cookie 的另一个优点就是,您可以和非 Java 资源共享您的会话数据。您的 JavaScript 和 CGI 程序可以利用这种状态信息,因为它是通过每一个客户机请求发送的。 然而,容量限制可能是使用 cookie 存储会话数据的致命弱点。一个 cookie 头最多可以存储 4K 的文本。这就让存储大的数据集合很不实际。您还需要注意您决定在 cookie 中存储的内容。这个 cookie 头包括了您 Web 站点中的所有 cookie。如果超过了最大的 cookie 容量,就会出现不好的后果。例如,依照用户浏览器的不同,不是旧 cookie 会丢失就是新 cookie 不能写入。要避免这种情况,要确保您的 cookie 不接近 4K 的限制。您要给自己足够的空间,来应付用户在自己的浏览器中已经有别的来自您的域的 cookie 的情况。这样就必须编写代码检查 cookie 是否被成功写入。您当然不能盲目地将对象序列化后将它们放到 cookie 中去。您必须非常有选择性的组织例程。 另一个主要的缺点是用户可以随意关掉 cookie。现在大多数浏览器都支持 cookie。然而,有少数 Web 站点用户希望在自己的浏览器中禁用 cookie。这就强迫您要在 HTML 页面中编写 JavaScript 或在 servlet 中编码以检测用户浏览器中的 cookie 是否被打开。所以,如果您使用 cookie 作为会话数据存储机制,您就必须有另一种机制作为“退路”,或者通报您的用户该站点没有 cookie 无法正常运行。 cookie 还有另一个缺点,就是关于它们怎样在 Web 中传送是有限制的。它们不能传送给同级域名。 这么说吧,WinesRus 买了一个新的域名:BeerIsUs.com。我们希望用户能够使用同样的购物车付帐()。问题在于,使用 cookie 的话,我们站点的 WinesRus.com 部分无法看到 BeerIsUs.com 创建的 cookie,反过来也一样。注意,如果我们有一个名为 Commerce.WinesRus.com 的特定的商业服务器,它就能够看到在 WinesRus.com 创建的 cookie,但是 WinesRus.com 看不到 Commerce.WinesRus.com 创建的 cookie。 在单独域名上可以存在的 cookie 数目是有限制的。某些域名限制是与浏览器有关的,所以您必须用多个浏览器来作全面的测试以确保 cookie 按照设计运行。使用 cookie 会使域名问题非常复杂。 cookie 和隐藏域都有另一个主要的缺点:安全性。 在客户机上存储的状态信息是不安全的。除非您花时间将数据加密,您在因特网上来回发送的数据都是明文。即使您手工或使用 SSL 将数据加密,您仍然不会愿意在客户机上存储敏感的商业数据。 所以,使用客户机保存会话的不利情况可能会使会话数据存储机制的优势黯然失色。客户机端解决方案最初看起来可能很简单,但复杂性很快就会成倍增长。相反,我们需要寻找那些最初比较复杂但会带来更好的整体效果的解决方案。 下载本文示例代码


客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?客户机如何存储会话数据?
阅读(121) | 评论(0) | 转发(0) |
0

上一篇:EJB2.0的JMS

下一篇:ejb内部资参之五

给主人留下些什么吧!~~