Tomcat与JavaWeb 5.1 HTTP会话(HttpSession)的使用

当客户访问Web应用时,许多情况下,Web服务器必须能够跟踪客户的状态。比如有若干客户各自以合法的账号登录到电子邮件系统,然后分别进行收信、写信和发信等一系列操作。在这个过程中,如果某个客户请求查看收件箱,Web服务器必须能够判断出发出请求的客户的身份,这样才能返回与这个客户相对应的数据。

再比如,有许多客户在同一个购物网站上购物,Web服务器为每个客户配置了虚拟的购物车。当某个客户请求将一个商品放入购物车时,Web服务器必须根据发出请求的客户的身份,找到该客户的购物车,然后把商品放到购物车中。

Web服务器跟踪客户状态通常有4中方法:

  • 在HTML表单中加入隐藏字段,它包含用于跟踪客户状态的数据。
  • 重写URL,使它包含用于跟踪客户状态的数据。
  • 用Cookie来传送用于跟踪客户状态的数据。
  • 使用会话(Session)机制。

本章将介绍如何通过会话来实现服务器对客户的状态的跟踪,还介绍了会话的持久化的作用和配置方法,以及会话的监听器的用法。

会话简介

HTTP是无状态的协议。每次当客户端请求访问Web服务器端的一个网页时,都必须与服务器建立一个FTP连接,然后发送HTTP请求,等收到了来自服务器的HTTP响应,本次FTP连接就被关闭。加入有多个客户同时访问某购物网站网页,这些客户都要求把同一种商品加入到他们各自的购物车,并且他们请求的URL地址完全相同。加入这些客户发送的HTTP请求是完全相同的,当Web服务器接收到这些HTTP请求后,如何判断每个请求分别是由哪个客户发出的,从而把书加入到与客户相对应的购物车中?显然,必须在HTTP请求中加入一些额外的用于跟踪客户状态的数据,只有这样,Web应用才能根据HTTP请求中的额外数据来区分不同的客户。

在Web开发领域,会话机制是用于跟踪客户状态的普遍解决方案。会话指的是在一段时间内,单个客户与Web应用的一连串的交互过程。在一个会话中,客户可能会多次请求访问Web应用的同一个网页,也有可能请求访问同一个Web应用的多个网页。

Servlet规范制定了基于Java的会话的具体运作机制。在Servlet API中定义了代表会话的java.servlet.http.HttpSession接口,Servlet容器必须实现这一接口。当一个会话开始时,Servlet容器将创建一个HttpSession对象,在该对象中可以存放表示客户状态的信息(例如购物车)。Servlet容器为每个HttpSession对象分配一个唯一标识符,称为Session ID。

会话的运作流程如下:

  1. 一个浏览器进程第一次请求访问Web应用中的任意一个支持会话的网页,Servlet容器试图寻找HTTP请求中表示Session ID的cookie。由于还不存在这样的Cookie,因此就认为一个新的会话开始了,于是创建一个HttpSession对象,为它分配唯一的Session ID,然后把Session iD作为Cookie添加到HTTP响应结果中。当浏览器就接收到HTTP响应结果后,会把其中表示Session ID的Cookie保存在客户端中。
  2. 浏览器进程继续请求访问同一个Web应用中的任意一个支持会话的网页,在本次HTTP请求中会包含表示Session ID的Cookie。Servlet容器试图寻找HTTP请求中表示Session ID的Cookie。由于得到了这样的Cookie,因此认为本次请求已经处于一个会话中了,Servlet容器不再创建新的HttpSession对象,而是从Cookie 中获取Session ID,然后根据Session ID找到内存中对应的HttpSession对象。
  3. 浏览器进程重复步骤二,直到当前会话被销毁,HttpSession对象就会结束生命周期。会话被销毁的时机参见本章下一节。

假如bookstore网上书店应用同时与3个客户(即3个浏览器进程)展开了会话。在服务器端,Servlet容器为每个会话分配一个HttpSession对象,bookstore应用把每个客户的表示购物车的ShoppingCart对象存放在与之对应的HttpSession对象中。在每个客户端存放了表示Session ID的Cookie。

在默认情况下,JSP网页都是支持会话的,也可以通过以下语句显式声明支持会话:

<%@page session="true"%>
如果一个Web组件支持会话,就意味着:
  • 当客户请求访问该Web组件时,Servlet容器就会自动查找HTTP请求中表示Session ID的Cookie,以及向HTTP响应结果中添加表示Session ID的Cookie。Servlet容器还会创建新的HttpSession对象或者寻找已经存在的与Session ID对应的HttpSession对象。
  • Web组件可以访问代表当前会话的HttpSession对象。

下面的例程会打印保存在客户端的所有Cookie。
sessionid.jsp

<%
    Cookie[] cookies = request.getCookies();
    if (cookies==null){
        out.println("No Cookies!");
        return;
    }
    for (Cookie cookie: cookies) {
%>
    <p>
        <b>Cookie name:</b>
        <%=cookie.getName()%>
    </p>
    <p>
        <b>Cookie value:</b>
        <%=cookie.getValue()%>
    </p>
    <p>
        <b>Max age in seconds:</b>
        <%=cookie.getMaxAge()%>
    </p>
<%
    }
%>
打开一个浏览器进程,初次访问的时候,此时返回“no cookie”。(如果使用IDEA实践过前几章的例程,也许cookie不是空的,但是首次访问的时候不会有名为Session的Cookie)。从同一个浏览器中第二次请求访问该JSP网页。由于初次访问时Servlet容器向客户端发送了一个表示Session ID的Cookie,因此在本次HTTP请求中会包含该Cookie,sessionid.jsp把该Cookie 的数据打印到网页上:

显示Max age in seconds为-1,表示着该Cookie仅仅存在于当前浏览器进程中,当浏览器进程关闭,Cookie也就消失,本次会话也就结束。  此时使用另一个浏览器进程访问该JSP页面,将会从第一个浏览器进程的第一步开始重复。

如果将JSP的开头加入如下代码,使sessionid.jsp不支持会话:

<%@page session="false"%>

这时再打开新的浏览器进程,多次访问该jsp页面,始终不会显示有名为Session的Cookie,因为该JSP不支持会话,Servlet容器并不会创建HttpSession对象,也不会向客户端发送表示Session ID的Cookie。

HttpSession的生命周期及会话范围

前面的章节已经介绍过Web应用范围和请求范围的概念。Web应用范围是指整个Web应用的生命周期,在具体实现上,Web应用范围与ServletContext对象的生命周期对应。Web应用范围内的共享数据作为ServletContext对象的属性而存在,因此Web组件只要共享同一个ServletContext对象,也就能共享Web应用范围内的共享数据。

同样,会话范围是指浏览器端与一个Web应用进行一次会话的过程。在具体实现上,会话范围与HttpSession对象的生命周期相对应。因此Web组件只要共享同一个HttpSession对象,也就能共享会话范围内的共享数据。HttpSession接口中的方法描述参见下表,Web应用的JSP或Servlet组件可通过这些方法来访问会话。

  • getID():返回Session ID。
  • invalidate():销毁当前的会话,Servlet容器会释放HttpSession对象所占用的资源。
  • setAttribute(String name,Object object):将一对name/object属性保存在HttpSession对象中。
  • getAttribute(String name)
  • getAttributeNames()
  • removeAttribute(String name)
  • isNew():判断是否是新创建的会话,如果是,返回true,否则返回false。
  • setMaxInactiveInterval(int interval):设定一个会话可以处于不活动状态的最长时间,以秒为单位。如果超过这个时间,Servlet容器会自动销毁这个会话。如果把参数interval设定为负数,表示不限制会话处于不活动状态的时间,即会话永远不会过期。Tomcat为会话设定的默认“保质期”为1800s。
  • getMaxInactiveInterval():读取当前会话可以处于不活动状态的最长时间。
  • getServletContext():返回会话所属的Web应用的ServletContext对象。

会话被销毁,意味着Servlet容器使HttpSession对象结束生命周期,并且存放在会话范围内的共享数据也都被销毁。会话被销毁只会发生在以下情况:

  1. 浏览器进程终止。
  2. 服务端执行HttpSession对象的invalidate()方法。
  3. 会话过期。

当Tomcat中的Web应用被终止时,它的会话并不会被销毁,而是被Tomcat持久化到永久性存储设备中,当Web应用重启后,Tomcat会重新加载这些会话。后面会介绍会话的持久化机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值