Session简介
HTTP协议是无状态的。每次当客户端请求访问Web服务端的一个网页时,都必须与服务器建立一个TCP连接,然后发送THTP请求,等到收到了来自服务器端的HTTP相应,本次FTP连接就被关闭。
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。
在Web开发领域,会话机制是用于跟踪客户状态的普遍解决方案。
会话是指在一段时间内,单个客户与Web应用的一连串相关的交互过程。
在一个会话中,客户可能会多次请求访问Web应用的同一个网页,也有可能请求访问同一个Web应用中的多个网页。
Session对浏览器的要求
虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。该Cookie为服务器自动生成的,它的maxAge属性一般为–1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。注意:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择“在新窗口中打开”时,子窗口便可以访问父窗口的Session。
如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:
URL地址重写
。
Java Web中的Session
Servlet规范制定了基于Java的Session的具体运作机制。
在Servlet API中定义了代表Session的接口:
javax.servlet.http
public interface HttpSession
Servlet容器必须实现这一接口。
当一个Session开始时,Servlet容器将创建一个HttpSession对象,在该对象中可以存放表示客户状态的信息。
Servlet容器为每个HttpSession对象分配一个唯一的标识符,称为Session ID.
Java Web中的Session的运作流程
例如:
-
当一个浏览器第一次请求访问web应用中的任意一个支持会话的网页,Servlet容器试图寻找HTTP请求中表示Seesion ID的Cookie,由于还不存在这样的Cookie,因此就认为一个新的会话开始了,于是创建一个HttpSession对象,为它分配唯一的Seesion ID,然后把Session ID作为Cookie添加到HTTP响应结果中,当浏览器接受到HTTP响应结果后,会把其中表示Seesion IDde Cookie保存在客户端。
-
浏览器继续请求访问web应用中的任意一个支持会话的网页,在本次HTTP请求中会包含表示Session ID的Cookie,因此认为本次请求已经处于一个会话中了,Servlet容器不再创建新的HttpSession对象,而是从Cookie中获取Session ID,然后根据Session ID找到内存中对应的HttpSession对象
-
浏览器重复步骤2,直到当前Session被销毁,HttpSession对象就会结束生命周期
Java Web中对Session的支持
在默认情况下,
JSP 网页都是支持Session的
。
也可以通过显式声明会支持Session:
<%@ page session="true" %>
如果一个Web组件支持Session,就意味着:
-
当客户请求访问该Web组件时,Servlet容器会自动查找HTTP请求中表示Session ID的Cookie。以及向HTTP响应结果中添加表示Session ID的Cookie。
-
Servlet容器会创建新的HttpSession对象或者寻找已经存在的与Session ID对应的HttpSession对象。
-
Web组件可以访问代表当前Session的HttpSession对象。
JSP与Servlet的区别
JSP文件在默认情况下都支持Session,而HttpServlet类在默认情况下不支持Session,这是JSP与Servlet的一个小小的区别
。
当Servlet容器调用HttpServlet类的服务方法时,会传递一个HttpSevletRequest类型的参数,HttpServlet可通过HttpServletRequest对象来获得HttpSession对象。
在HttpServletResponse接口中提供了两个与Session有关的方法:
-
getSession() —— 使得当前HttpServlet支持Session;假如Session已经存在,就返回相应的HttpSession对象,否则就创建一个新Session,并返回新建的HttpSession对象。该方法等价于调用HttpServletRequest.getSession(true)方法;
-
getSession(boolean create) —— 如果参数为true,等价于调用HttpServletRequest的getSession()方法;如果参数为false,那么假如Session已经存在,就返回相应的HttpSession对象,否则就返回null;
查看请求Cookie中的Session信息
sessiontest.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>Session Test</title>
</head>
<body>
<%
Cookie[] cookies = request.getCookies();
if (cookies == null){
out.println("no cookie");
return;
}
for (int i = 0; i < cookies.length; i++){
%>
<p>
<b>Cookie name:</b>
<%= cookies[i].getName() %>
<b>Cookie value:</b>
<%= cookies[i].getValue() %>
</p>
<p>
<b>max age in seconds:</b>
<%= cookies[i].getMaxAge() %>
</p>
<%
}
%>
</body>
</html>
访问如下URL:
http://localhost:8080/base-webapp/jsp/session/sessiontest.jsp
打开一个浏览器,第一次请求访问,页面: no cookie
从同一个浏览器进程中第二次访问,页面如下:
打开一个新的浏览器进程,访问,页面:
多次请求访问,返回的结果:
Session ID的Cookie有效期为-1;这意味着该Cookie仅存在于当前浏览器进程中,当浏览器进程关闭,Cookie也就消失,本次Sessio结束。