首页 > 代码库 > 【JSP/Servlet-HTTP会话解析】
【JSP/Servlet-HTTP会话解析】
个人学习整理,如有不足之处,请不吝指教。转载请注明:@CSU-Max
Max之前的一篇关于Session 和 Cookie 的文章:cookie和session那些事
会话简介
web服务器跟踪客户状态的几种方式:
1、在html表单中加入隐藏字段,它包含用于跟踪用户状态的数据;
2、重写URL,及在URL中附带用户的状态信息;
3、使用cookie来传递用于跟踪客户状态的数据;
4、使用会话来跟踪用户状态的数据。
会话能够把用户与同一用户发出的不同请求之间关联起来。不同用户的会话应当是相互独立的。在web开发领域,会话机制是用于跟踪用户状态的普遍解决方案。会话是指在一段时间内,单个用户与web应用的一系列交互过程。在一个会话过程中,用户可以多次请求该web应用的同一页面,也可以访问该web应用中的其他页面。
在Servlet中有关于会话的 javax.servlet.http.HttpSession 接口,Servlet容器必须实现这一接口。当一个会话开始时,Servlet容器会创建一个HttpSession对象,将客户信息状态存储在该对象中,如购物车信息。Servlet容器为每个HttpSession对象分配一个唯一的标志符,称为SessionID。
会话的运作流程
1、当一个浏览器进程第一次请求访问某个web应用中任意一个支持会话的网页(也可以设置页面不支持会话,下文有介绍),Servlet容器会试图寻找HTTP请求中表示SessionID的Cookie,由于还不存在这样的Cookie,故此时就会开启一个新的会话,Servlet容器会创建一个HttpSession对象,并为其分配一个唯一的SessionID,在返回HTTP响应结果时,Cookie会附带该SessionID。当浏览器接收到HTTP响应结果之后,会把Cookie(带有SessionID)保存在客户端。
2、该浏览器进程继续访问该web应用中的任意支持会话的页面,在本次的HTTP请求中会包含带有SessionID的Cookie,Servlet容器会获取本次HTTP请求中的SessionID,该SessionID就是1中产生的,因此Servlet容器认为本次请求与上次请求处于同一个会话中,Servlet容器不会创建新的HttpSession对象,而是根据Cookie中的SessionID,找到内存中该SessionID对应的HttpSession对象。
3、重复步骤2,在当前会话销毁之前(关于会话的销毁下文有介绍),仍是在同一个会话中进行访问,故不会产生新的HttpSession对象。
通过代码实例来了解会话机制
在默认情况下,JSP页面都会支持会话,也可以通过代码显式控制支持会话:
<%@ page session = "true" %>
若web组件支持会话,当客户请求访问该web组件时,Servlet容器会自动查找HTTP请求中表示SessionID的Cookie,并向HTTP响应结果中添加表示SessionID的Cookie。在此过程中,若有与SessionID对应的HttpSession对象,则Servlet容器使用该对象,若没有,则Servlet容器会创建一个新的HttpSession对象。
web组件可以访问代表当前会话的HttpSession对象。
我们可以通过下面的实例代码来了解,新建一个web工程,在根目录下新建一个test.jsp,具体代码如下:
<%@ page language ="java" contentType="text/html; charset=utf-8" pageEncoding= "utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv= "Content-Type" content ="text/html; charset=utf-8"> <title> Insert title here</ title> </head> <body> <% Cookie[] cookies = request.getCookies(); if (cookies == null) { out.println( "no cookie"); return; } for ( int i = 0; i < cookies.length; i++) { %> <b >Cookie Name </b> <%=cookies[i].getName() %> <br > <b >Cookie Value </b> <%=cookies[i].getValue() %> <br > <b >Cookie Maxage</ b> <%=cookies[i].getMaxAge() %> <% } %> </body> </html>
1、打开一个浏览器进程,第一次请求访问test.jsp页面,会返回“no cookie”。
2、利用1打开的浏览器进程,再次访问test.jsp页面(即再按一次回车即可)。由于在1中,Servlet容器会向客户端发送一个包含SessionID的Cookie(上面已经讲到),所以本次的HTTP请求中会包含该Cookie,故test.jsp页面上会显示该Cookie的数据,如下图:
注:此处Cookie的maxage(有效期)属性值为 -1,表示该Cookie仅存在与当前的浏览器进程中,当浏览器关闭,该Cookie也就失效了,本次会话也结束了。
3、利用1打开的浏览器进程再多次访问test.jsp页面,页面显示的数据仍如上图所示。
4、重新打来一个浏览器进程,重复步骤1、2、3,会发现页面显示的Cookie Value不一样,即SessionID不一样,因为不同的浏览器进程对应不同的会话,每个会话都拥有一个唯一的SesionID。
5、在test.jsp中加入如下代码,使test.jsp不支持会话,再重新打开一个浏览器进程,多次访问test.jsp页面,结果都是显示“no cookie”。因为test.jsp显式要求不支持会话,所以Servlet容器不会创建HttpSession对象,也不会向客户端发送表示SessionID的Cookie。
HttpSession 的会话范围
会话的范围指的是浏览器端与一个web应用进行一次会话的过程。在具体实现时,会话范围与HttpSession对象的生命周期相对应,所以web组件只要共享同一个HttpSession对象,就能实现共享会话范围内的共享数据。
在HttpSession接口中关于在会话范围内存取共享数据有如下方法:
/** * 向会话范围内存放共享数据 */ public void setAttribute(String name, Object value) { } /** * 返回会话范围内与name对应的共享数据 */ public Object getAttribute(String name) { return null; } /** * 返回会话范围内所有共享数据的name */ public Enumeration getAttributeNames() { return null; } /** * 删除会话范围内与name对应的共享数据 */ public void removeAttribute(String name) { }
利用以上的方法,我们就可以在会话范围内存取共享数据了:
HttpSession session = request.getSession(); //将username 存储到会话范围内的共享数据中 session.setAttribute( "username", username); //从会话范围内读取username currentUser = (String) session.getAttribute("username" );
在HttpSession接口中还有一些其他的访问会话的方法,想了解的可以自行研究。
HttpSession 的生命周期
在以下情况下,会开启一个新的会话,即Servlet容器会创建一个新的HttpSession对象:
1、一个浏览器进程第一次访问某个web应用中支持会话的任意一个网页。
2、当浏览器与web应用的上一次会话被销毁后,浏览器进程再次访问web应用中支持会话的任意一个网页。
注:当浏览器进程与web应用的一次会话被销毁之后,web服务器端相应的HttpSession对象结束其生命周期。当浏览器进程再次访问该web应用时,在它的HTTP请求中的Cookie中包含了之前已被销毁的SessionID,但是此时Servlet容器无法找到次SessionID对应的HttpSession对象,故Servlet容器会创建新的HttpSession对象,开启新的会话。
在以下情况下,会销毁一个会话,即Servlet容器会使HttpSession对象结束生命周期,并且存储在会话范围内的共享数据也会被销毁:
1、浏览器进程终止。
2、服务器端执行了HttpSession对象的invalidate()方法。
3、会话过期。
会话过期是指在会话开启之后,若在一段规定的时间内,用户没用和web应用进行交互,则Servlet容器会自动的销毁这个会话。HttpSession中的 setMaxInactiveInterval(int interval) 方法用于设置允许会话保持不活动状态的时间(以秒为单位),如果超过这个规定的时间,会话就会被Servlet容器销毁。若把 interval 参数设为负数,则表示会话永远不会过期。在Tomcat中,默认的会话保持不活动状态的时间是1800秒。
当一个会话开启后,如果浏览器进程突然关闭,Servlet容器无法立即知道浏览器进程已经关闭,因此Servlet容器中的HttpSession对象不会立即结束生命周期,会话会在浏览器进程关闭之后,进入不活动状态,等到超出上述规定的时间后,会话就会因为过期而被Servlet容器销毁。
为什么要有会话过期的机制呢?
我们知道,过多无用的HttpSession对象会影响web服务器的性能,销毁长期不活动的会话,可以及时释放这些HttpSession对象占用的内存空间。同时,会话过期机制也提高了web应用的安全性,防止未授权的用户访问会话。如某个用户访问某个web应用,之后并没有关闭浏览器进程,此时另一个用户使用该浏览器进程访问同一web应用,此时看到的是前一个用户的信息,这就给安全带来了隐患。
********************************************************************************
** 转载请注明出处: @CSU-Max http://blog.csdn.net/csu_max ** ********************************************************************************
【JSP/Servlet-HTTP会话解析】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。