首页 理论教育JavaWeb应用开发:ServletAPI会话跟踪

JavaWeb应用开发:ServletAPI会话跟踪

【摘要】:当请求一个会话的时候,Servlet 容器就创建一个HttpSession 对象,有了这个对象后,就可以利用这个对象中保存客户的状态信息,例如购物车。表3.2HttpSession 接口中的主要方法例3.5:Session 的使用和URL 重写示例。在本例中,首先提供给用户一个登录表单,用户输入用户名和密码,单击登录按钮将数据提交至Servlet。图3.21会话信息从图3.21 可以看出,encodeURL()、encodeRedirectURL()等方法都没有重写URL,并且没有获取到当前用户,而是会话状态显示为新的会话。

在Java Servlet API 中,javax.servlet.http.HttpSession 接口封装了Session的概念,Servlet 容器提供了这个接口的实现。当请求一个会话的时候,Servlet 容器就创建一个HttpSession 对象,有了这个对象后,就可以利用这个对象中保存客户的状态信息,例如购物车。Servlet 容器为HttpSession 对象分配一个唯一的Session ID,将其作为Cookie(或者利用URL 重写机制作为URL 的一部分,或者作为隐藏表单字段的值)发送给浏览器,浏览器在内存中或硬盘上保存这个Cookie。当客户再次发送HTTP 请求时,浏览器将Cookie 随请求一起发送,Servlet 容器从请求对象中读取Session ID,然后根据Session ID 找到对应的HttpSession 对象,从而得到客户的状态信息。整个过程如图3.18 所示。

图3.18(a) 会话跟踪过程的示意图

图3.18(b) 会话跟踪过程的示意图

需要注意的是,图3.18 中的id 就是指Session ID,但是在会话跟踪过程中,其名称不是id,而是jsessionid(使用URL 重写、隐藏表单域等技术时)或JSESSIONID(使用Cookie 技术时)。而且Servlet 容器产生的Session ID 并不是如123 这样的十进制数,而是一个十六进制的数,如D4FC2F9E47D3A2644661B4B342A94E54。

➢ HttpSession 接口

HttpSession 接口提供的主要方法见表3.2。

表3.2 HttpSession 接口中的主要方法

例3.5:Session 的使用和URL 重写示例。

在本例中,首先提供给用户一个登录表单,用户输入用户名和密码,单击登录按钮将数据提交至Servlet。在Servlet 中获取用户输入的数据,并验证用户名和密码,若通过验证就将用户名存储到Session 中。然后使用外部跳转的方式跳转到显示会话信息的页面,在该页面中输出登录用户名和会话信息,并提供一个退出登录的超级链接。单击“退出”链接将退回到登录页面。

本例主要为了演示Session 的使用和URL 重写,默认情况下采用基于Cookie 的会话跟踪,若客户端禁用了Cookie,则采用URL 重写的机制来进行会话跟踪。

登录页面/ch04/login.html 代码如下:

登录界面运行效果如图3.19 所示。

图3.19 登录页面

当单击“登录”之后,会将表单数据提交至servlet/SessionAndURLRewrite,该Servlet 的处理逻辑如下:

在该Servlet 中,首先获取用户提交的表单数据,并且进行了验证,若通过验证就获取Session,若还没有Session 就为用户分配一个Session,并将用户名保存至Session 中。该Servlet 最终将跳转至servlet/OutputSessionInfo,在调用sendRedirect()方法之前将URL 进行了重写,这是为了保证在客户端禁用Cookie 的情况下程序仍然能正确运行。OutputSessionInfo.java 的处理逻辑如下:

(www.chuimin.cn)

在OutputSessionInfo.java 中,首先获取了Session,接着将上一个Servlet 中存储在Session 中的用户名取出来并输出,然后输出了有关会话的信息,包括会话状态(新会话还是旧会话)、会话ID、会话创建时间、上次访问时间和最大不活动时间间隔等信息。在该Servlet 中还提供了一个“退出”的超级链接,该超级链接的URL 使用了response 对象的encodeURL()方法进行了URL 重写。以下是用于执行退出的Servlet(LoginOut.java)的处理逻辑代码:

在LoginOut.java 的doGet()方法中,调用了Session 对象的invalidate()方法来实现使用会话失效,然后重定向至登录页面。可能大家会有疑问:为什么这里在执行重定向之前没有进行URL重写呢?其实,这是因为encodeURL()方法主要为了将Session ID 写入URL 从而实现会话跟踪,而这里调用了Session 对象的invalidate()使会话失效,也就是说会话都失效了,就不用再进行会话跟踪了。

现在代码完成了,在以下两种情况下来测试一下这个Web 应用程序。

1.客户端未禁用Cookie 的情况

访问登录页面,输入正确的用户名和密码,即用户名为“zhangsan”,密码为“123456”,然后单击“登录”按钮,将看到如图3.20 所示的效果。

图3.20 会话信息(通过登录验证且客户端未禁用Cookie)

从图3.20 可以看出,地址栏的URL 没有进行重写,且退出链接所指向的URL 也没有进行重写(请看图中浏览器状态栏显示的链接)。即在客户端支持Cookie 的情况下,encodeURL()、encodeRedirectURL()等方法均不会重写URL,都返回没有改变的URL。从图3.20 也可以看出,正确获取了当前用户和会话相关信息,并且会话状态为旧的会话,说明会话在SessionAndURLRewrite.java 中就创建了。

现在单击“退出”链接将跳转到登录页面。这次使用错误的用户名或密码进行登录。登录后最终同样将跳转到会话信息页面(OutputSessionInfo),如图3.21 所示。

图3.21 会话信息(未通过登录验证且客户端未禁用Cookie)

从图3.21 可以看出,encodeURL()、encodeRedirectURL()等方法都没有重写URL,并且没有获取到当前用户,而是会话状态显示为新的会话。没有获取到用户是因为错误的用户名或密码没有通过验证,所以也没有执行将用户名存入Session 的那部分代码;而会话显示为新的会话,这是因为在SessionAndURLRewrite.java 中没有为客户端分配Session,而在OutputSessionInfo.java 中执行request 对象的getSession()方法时才为用户分配Session。

2.客户端禁用Cookie 的情况

上面是客户端未禁用Cookie 时的情况,默认使用的是Cookie 进行会话跟踪,所以encodeURL()、encodeRedirectURL()方法均无效果。现在禁用浏览器的Cookie,再次访问登录页面,输入正确的用户名和密码,单击登录之后看到的效果如图3.22 所示。

图3.22 会话信息(通过登录验证且客户端禁用了Cookie)

从图3.22 可以看出,效果和图3.20 差不多,但是浏览器地址栏的URL 和退出链接指向的URL 地址,都进行了重写。这说明使用了URL 重写机制。

当退出后,使用错误的用户名或密码进行登录后,会话信息页面如图3.23 所示。

图3.23 会话信息(未通过登录验证且客户端禁用了Cookie)

从图3.23 也可以看出使用了URL 重写机制,但是为什么浏览器地址栏的URL 未进行重写,这是由于错误的用户名或密码未通过验证,在SessionAndURLRewrite 中没有使用request.getSession()为用户分配Session,即在未分配Session 的情况下,使用encodeRedirectURL()等方法进行URL 重写是没有效果的。在会话信息页面也显示会话状态为新的会话,说明Session 是在OutputSessionInfo 中分配的。因为在OutputSessionInfo 中分配了Session,而且客户端也禁用了Cookie,所以在OutputSessionInfo中使用encodeURL()方法对“退出”链接的URL进行重写是有效果的。