Web应用开发中非常重要的主题---会话管理


      由于HTTP的无状态性,使得会话管理或会话跟踪成为Web应用开发一个无可避免的主题。默认下,一个Web服务器无法区分一个HTTP请求是否为第一次访问。
      例如,一个Web邮件应用要求用户登录后才能查看邮件,因此,当用户输入了相应的用户名和密码后,应用不应该再次提示需要用户登录,应用必须记住哪些用户已经登录。换句话说,应用必须能管理用户的会话。接下来将阐述4中不同的状态保持技术:URL重写、隐藏域、cookies和HTTPSession对象。

1.URL重写

      URL重写是一种会话跟踪技术,它将一个或多个token添加到URL的查询字符串中,每个token通常为key=value形式,如下:

url?key1=value1&key2=value2...

注意:URL和tokens间用问号(?)分割,token间用与号(&)。
      URL重写适合于tokens无须在太多URL间传递的情况下,然而它有如下限制:

  • URL在某些浏览器上最大长度为2000字符。
  • 若要传递值到下一个资源,需要将值插入到链接中,换句话说,静态页面很难传值。
  • URL重写需要在服务端上完成,所有的链接都必须带值,因此当一个页面存在很多链接时,处理过程会是一个不小的挑战。
  • 某些字符,例如空格、与和问号等必须用base64编码。
  • 所有的信息都是可见的,某些情况下不合适。

因为存在如上限制,URL重写仅适合于信息仅在少量页面间传递,且信息本身不敏感。

2.隐藏域

      使用隐藏域来保持状态类似于URL重写技术,但不是将值附加到URL上,而是放到HTML表单的隐藏域中。当表单提交时,隐藏域的值也同时提交到服务器端。隐藏域技术仅当网页有表单时有效。该技术相对于URL重写的优势在于:没有字符数限制,同时无需额外编码。但该技术同URL重写一样,不适合跨越多个界面。

3.Cookies

      URL重写和隐藏域仅适合保存无需跨越太多页面的信息。如果需要在多个页面间传递信息,则以上两种技术实现成本高昂,因为你不得不在每个页面都进行相应处理。幸运的是Cookies技术可以帮到我们。
      Cookies是一个很少的信息片段,可自动地在浏览器和Web服务器间交互,因此cookies可存储在多个页面间传递的信息。Cookie作为HTTP header的一部分,其传输由HTTP协议控制。此外,你可以控制cookie的有效时间。浏览器通常支持每个网站高达20个cookies。
      Cookies的问题在于用户可以通过改变其浏览器设置来拒绝接受cookies。要使用cookies,需要熟悉javax.servlet.http.Cookie类以及HttpServletRequest和HttpServletResponse两个接口。可以通过name和value两个参数给Cookie类的构造函数来创建一个cookies:

Cookie cookie=new Cookie(name,value);

如下是一个创建语言选择的cookie示例:

Cookie languageSelectionCookie=new Cookie("language","China");

      创建完一个Cookie对象后,你可以设置domain、path和maxAge属性。其中,maxAge属性决定cookie何时过期。要将cookie发送到浏览器,需要调用HttpServletResponse的addcookie方法:

httpServletResponse.addCookie(cookie);

      浏览器在访问同一Web服务器时,会将之前收到的cookie一并发送。
      此外,Cookies也可以通过客户端的javascript脚本创建和删除。服务端若要读取浏览器提交的cookie,可以通过HttpServletRequest接口的getCookies方法,该方法返回一个Cookie数组,若没有cookies则返回null。你需要遍历整个数组来查询某个特定名称的cookie。如下为查询名为maxRecords的cookie的示例:

Cookie[] cookies=request.getCookies();
Cookie maxRecordCookie=null;
if(cookies!=null)
{
   for(Cookie cookie:cookies)
   {
      if(cookie.getName().equals("maxRecords"))
      {
        maxRecordCookie=cookie;
        break;
      }
   }
}

      目前,还没有类似于getCookieByName这样的方法来帮助简化工作。此外,也没有一个直接的方法来删除cookie,你只能创建一个同名的cookie,并将maxAge属性设置为0,并添加到HttpServletResponse接口中。如下为删除一个名为userName的cookie代码:

Cookie cookie=new Cookie("userName","");
cookie.setMaxAge(0);
response.addCookie(cookie);

4.HttpSession对象

      在所有的会话跟踪技术中,HttpSession对象时最强大和最通用的。一个用户可以有且最多有一个HttpSession,并且不会被其他用户访问到。HttpSession对象在用户第一次访问网站的时候自动被创建,你可以通过调用HttpServletRequest的getSession方法来获取该对象。getSession有两个重载方法:

HttpSession getSession()
HttpSession getSession(boolean create)

      没有参数的getSession方法会返回当前的HttpSession,若当前没有,则创建一个返回。getSession(false)返回当前HttpSession,如当前会话不存在,则返回null。getSession(true)和getSession()功能一样。
      可以通过HttpSession的setAttribute方法将值放入HttpSession,将方法签字如下:

void setAttribute(java.lang.String name,java.lang.Object value)

      请注意,不同于UTL重写、隐藏域或cookie,放入到HttpSession的值,是存储在内存中,因此,不要往HttpSession放入太多对象或大对象。尽管现代的Servlet容器在内存不够用的时候会将保存在HttpSessions的对象转储到二级存储上,但这样有性能问题,因此小心存储。
      调用setAttribute方法时,若传入的name参数此前已经使用过,则会用新值覆盖旧值。通过调用HttpSession的getAttribute方法可以取回之前放入的对象,该方法的签名如下:

java.lang.Object getAttribute(java.lang.String name)

      HttpSession还有一个非常有用的方法,名为getAttributeNames,该方法会返回一个Enumeration对象来迭代访问保存在HttpSession中的所有值:

java.util.Enumeration<java.lang.String> getAttributeNames()

      注意,所有保存在HttpSession的数据不会被发送到客户端,不同于其他会话管理技术,Servlet容器为每个HttpSession生成唯一的标识,并将该标识发送给浏览器,或创建一个名为JSESSIONID的cookie,或者在URL后附加一个名为jsessionid的参数。在后续的请求中浏览器会将标识提交给服务端,这样服务器就可以识别该请求时由哪个用户发起的。Servlet容器会自动选择一种方式传递会话标识,无须开发人员介入。
      可以通过HttpSession的getId方法来读取该标识:

java.lang.String getId()

      此外,HttpSession还定义了一个名为invalidate的方法。该方法强制会话过期,并清空其保存对象。默认情况下,HttpSession会在用户不活动一段时间后自动过期,该时间可以通过部署描述符的session-timeout元素配置,若设置为30,则会话对象会在用户最后一次访问30分钟后过期,如果部署描述没有配置,则该值取决于Servlet容器的设定。
      大部分情况下,你应该主动销毁无用的HttpSession,以便释放相应的内存。
      可以通过调用HttpSession的getMaxInactiveInterval方法来查看会话多久会过期。该方法返回一个数字类型,单位为秒。调用setMaxInactiveInterval方法来单独对某个HttpSession设置器超时时间。

void setMaxInactiveInterval(int seconds)

      若设置为0,则该HttpSession用不过期。通常这不是一个好的设计,因此该HttpSession所占用的堆内存将永不释放,直到应用重加载或Servlet容器关闭。

5.小结

      这4中会话管理技术,URL重写和隐藏域是轻量级的会话跟踪技术,适用于那些仅跨少量页面的数据。而cookies和HttpSession对象,更加灵活但也有限制,尤其是在应用HttpSession时会消耗服务器内存。

猜你喜欢

转载自blog.csdn.net/Achenming1314/article/details/105949418
今日推荐