电话:0731-83595998
导航

深入理解和改进JSP/Servlet会话管理机制

来源: 2017-12-22 09:33

 百度广告

在Web服务器端编程中,会话状态管理是一个经常必须考虑的重要问题。分析JSP/Servlet的会话管理机制及其所面临的问题,然后提出了一种改进的会话管理方法。

一、Servlet的会话管理机制

根据设计,HTTP是一种无状态的协议。它意味着Web应用并不了解有关同一用户以前请求的信息。维持会话状态信息的方法之一是使用Servlet或者JSP容器提供的会话跟踪功能。Servlet API规范定义了一个简单的HttpSession接口,通过它我们可以方便地实现会话跟踪。 
在HTTP协议中,当用户不再活动时不存在显式的终止信号。由于这个原因,我们不知道用户是否还要再次返回,如果不采取某种方法解决这个问题,内存中会积累起大量的HttpSession对象。 
要获得HttpSession对象,我们可以调用HttpServletRequest对象的getSession方法。为了正确地维持会话状态,我们必须在发送任何应答内容之前调用getSession方法。 
Servlet/JSP会话跟踪机制有着一定的局限,比如:

会话对象保存在内存之中,占用了可观的资源。 
会话跟踪要用到服务器创建的会话标识符。在多个Web服务器以及多个JVM的环境中,Web服务器不能识别其他服务器创建的会话标识符,会话跟踪机制无法发挥作用。

要深入理解会话跟踪机制,首先我们必须理解在Servlet/JSP容器中会话如何运作。

二、会话标识符

每当新用户请求一个使用了HttpSession对象的JSP页面,JSP容器除了发回应答页面之外,它还要向浏览器发送一个特殊的数字。这个特殊的数字称为"会话标识符",它是一个唯一的用户标识符。此后,HttpSession对象就驻留在内存之中,等待同一用户返回时再次调用它的方法。 
会话标识符以Cookie的形式在服务器和浏览器之间传送。如果浏览器不支持Cookie又如何呢?此时,对服务器的后继请求将不会带有会话标识符。结果,JSP容器认为该请求来自一个新用户,它会再创建一个HttpSession对象,而以前创建的HttpSession对象仍旧驻留在内存中,但该用户以前的会话信息却丢失了。 

三、伪会话管理机制

如前所述,基于Cookie的会话管理技术面临着种种问题。下面我们要设计一种新的会话管理机制来解决这些问题。这种会话管理机制称为"伪会话"(Pseudo Session)机制,它具有如下特点: 
2) 文件保存在一个专用的目录中,所有Web服务器都可以访问这个目录。因此,伪会话可以用于Web农场。 
此外,实现伪会话管理机制时我们还要考虑到以下几点: 
5) 考虑到安全原因,应该有一种为会话标识符生成随机数字的办法。 
7) 应该有一种收集过期会话并删除相应文件的机制。 
9) 同时,应该存在一种更新会话文件最后改动时间的机制,使得用户在会话过期时限之前返回时会话总是保持最新且合法的状态数据。 |||

四、实现伪会话管理机制

下面所介绍的工程称为PseudoSession,它是伪会话机制一个很简单的实现。考虑到移植性,我们以JavaBean的形式实现它。PseudoSessionBean的完整代码可以从后面下载。 
public String path;public long timeOut; 
timeOut是用户的最后一个请求到会话过期作废之间的时间。在PseudoSessionBean的代码清单中,timeOut设置成了以毫秒表示的20分钟,这是一个比较合理的超时时间值。对于任何用户,如果他在这个超时时间之后才继续发出请求,他将得到一个新的会话标识符。 

4.1 getSessionID方法

getSessionID方法的声明 
这个方法应该在每一个JSP页面的开头调用。它完成如下任务: 
2) 检查URL所带会话标识符的合法性。如果会话标识符已经过期,则getSessionID方法返回一个新的会话标识符。 
String sessionId = request.getParameter("sessionId"); 
boolean validSessionIdFound = false; 
long now = System.currentTimeMillis(); 

1) 一个合法的会话标识符必须有对应的同名文件。 
3) 如果存在与会话对应的文件,但文件已经过期,则原来的文件被删除。 

这些任务主要借助File对象完成,创建File对象的参数就是会话文件的路径: 
now) { // 会话合法// 使用setLastModified时,如果文件已经被其他程序锁定,// 程序不会产生任何异常,但文件数据不会改变f.setLastModified(now);validSessionIdFound = true; } else { // 会话已经过期 // 删除文件f.delete(); }} // end if (f.exists) } // end if (sessionId!=null) 
if (!validSessionIdFound) { sessionId = Long.toString(now); // 创建文件 File f = new File(path + sessionId); try {f.createNewFile(); } catch (IOException ioe) {}} // end of if !validSessionIdFound 
综上所述,getSessionID并不总是返回新的合法会话标识符:它返回的标识符可能与传递给它的标识符相同,也可能是新创建的会话标识符。 

4.2 setValue方法

setValue方法保存value字符串以及与它关联的字符串名字。这种"名字-值"对很容易使人想起Dictionary对象。setValue方法要求在第一个参数中提供合法的会话标识符,它假定在自己被调用之前getSessionID方法已经执行,经过检验的合法会话标识符必然存在,因此它不再对传入的会话标识符进行合法性检验。 

1) 如果与value值关联的name以前还没有保存过,则新的名字-值对加入到文件的末尾。 

setValue方法按照如下格式保存名字-值对,注意"名字"是大小写敏感的: 
setValue方法的声明 
setValue方法首先寻找与当前会话对应的文件。如果不能找到文件,则setValue方法不做任何事情直接返回。如果找到了会话文件,setValue方法读取文件的各个行,然后比较读入的行与name:如果读入的文本行开头与name一样,则说明该名字已经保存,setValue方法将替换该行后面的值;如果name不能与读入的文本行匹配,则这行文本被直接复制到一个临时文件。 
try { FileReader fr = new FileReader(path + sessionId); BufferedReader br = new BufferedReader(fr); FileWriter fw = new FileWriter(path + sessionId + ".tmp"); BufferedWriter bw = new BufferedWriter(fw); String s; while ((s = br.readLine()) != null)if (!s.startsWith(name + " ")) { bw.write(s); bw.newLine();} bw.write(name + " " + value); bw.newLine(); bw.close(); br.close(); fw.close(); bw.close(); . . .}catch (FileNotFoundException e) {}catch (IOException e) { System.out.println(e.toString());} 
File f = new File(path + sessionId + ".tmp");File dest = new File(path + sessionId);dest.delete();f.renameTo(dest);

4.3 getValue方法

getValue方法用于提取原来保存在伪会话中的数据。正如setValue方法,getValue方法也要求传入一个合法的会话标识符,而且getValue方法不再对传入的会话标识符进行合法性检查。getValue方法的第二个参数是待提取数据的name,返回值是与指定name关联的value。 
public String getValue(String sessionId, String name) 
4.4 deleteAllInvalidSessions方法 
deleteAllInvalidSessions方法的声明 
它首先把所有会话文件的名字读入files字符串数组: 
deleteAllInvalidSessions方法比较文件的最后修改时间(加上超时时间)和系统当前时间,确定会话是否过期。long类型的变量now用于保存系统的当前时间。 
接下来,deleteAllInvalidSessions方法通过循环访问files数组,依次检查每个文件的lastModified属性。所有与过期会话关联的文件都将被删除: 

五、应用实例

编译好PseudoSessionBean这个JavaBean之后,我们就可以利用伪会话管理机制来管理Web应用的会话状态信息了。由于不必再使用服务器的会话管理机制,我们可以在page指令中把session属性设置为false关闭默认的JSP/Servlet会话管理功能。 
然后,我们用JSP的标记告诉JSP容器程序要使用PseudoSessionBean: 

在上面这个标记中,class属性值是"包.类名字"形式。当然,对于不同的包名字,class属性的值应该作相应的修改。注意Bean的scope属性是"application",这是因为我们要在应用的所有页面中使用这个Bean。在这个应用中,把Bean的scope属性设置为"application"具有最好的效率,因为我们只需创建Bean对象一次就可以了。另外,正如前面所提到的,getSessionID方法必须在所有其他代码之前调用。 
为了说明PseudoSessionBean的应用,下面我们来看两个JSP页面,它们是index.jsp和secondPage.jsp。index.jsp页面在伪会话变量中保存用户的名字,而secondPage.jsp则提取这个用户名字。 

伪会话

伪会话管理机制



 
secondPage.jsp页面只简单地返回以前保存的用户名字。

第2个页面

编辑推荐:

下载Word文档

温馨提示:因考试政策、内容不断变化与调整,长理培训网站提供的以上信息仅供参考,如有异议,请考生以权威部门公布的内容为准! (责任编辑:长理培训)

网络课程 新人注册送三重礼

已有 22658 名学员学习以下课程通过考试

网友评论(共0条评论)

请自觉遵守互联网相关政策法规,评论内容只代表网友观点!

最新评论

点击加载更多评论>>

精品课程

更多
10781人学习

免费试听更多

相关推荐
图书更多+
  • 电网书籍
  • 财会书籍
  • 其它工学书籍
拼团课程更多+
  • 电气拼团课程
  • 财会拼团课程
  • 其它工学拼团
热门排行

长理培训客户端 资讯,试题,视频一手掌握

去 App Store 免费下载 iOS 客户端