Session与会话跟踪
利用Session,服务器能够标识出来自单个客户的一系列请求,并把这些请求组成一个单独的工作会话,就能区分不同的用户;同时服务器能够记住前面的请求的信息,以及对前一请求作出的处理信息,记住客户的操作状态。
当请求一个会话的时候,Servlet容器就创建一个HttpSession对象,有了这个对象,就可以利用这个对象保存客户的状态信息。
Servlet容器为HttpSession对象分配一个唯一的SessionID,将其作为Cookie的一部分(或URL的一部分)发送给浏览器,浏览器在内存中保存这个Cookie。当客户再次发送HTTP请求时,浏览器会将Cookie随请求一起发送,Servlet容器从请求对象中读取SessionID,然后根据SessionID找到对应的HttpSession对象,从而得到客户的状态信息。

Cookies
Cookies是一种由服务器发送给客户的片段信息,存储在客户端浏览器的内存中或硬盘上,在客户随后对该服务器的请求中发回它。
Cookie以键值对的方式记录会话跟踪的内容,服务器利用响应报头Set-Cookie来发送Cookie信息,请求报头利用Cookie发回它。
Set-Cookie响应报头的格式:
Set-Cookie: <\name>=<\value>[; <\name>=<\value>]…
[; expires=<\date>][; domain=<\domain_name>]
[; path=<\some_path>][; secure][; httponly]
说明:1、Name是Cookie的名字,Name=value属性–值对必须首先出现,在此之后的属性-值对可以以任何顺序出现。(在Servlet规范中,用于会话跟踪的Cookie的名字必须是JSESSIONID )。
2、Domain属性是可选的,用于指定Cookie在哪一个域中有效。所指定的域必须以点好(.)开始。
3、expires=<\date>: 设置cookie的有效期,如果cookie超过date所表示的日期时,cookie将失效。如果没有设置这个选项,那么cookie将在浏览器关闭时失效。
例如:
Set-Cookie: MODXOXd=”32434343322”; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/MODXOXd=”“;
当浏览器下一次发送请求时,同时会发送下面的请求报头:
Cookie:MODXOXd=”32434343322”
Cookie类
利用setMaxAge(int expir)可以设置Cookie的生存时间
大于0的秒数:将会在指定的秒数后到期;
小于0的负数:Cookie不能被保存到持久存储设备中,只能存活于浏览器内存中,当浏览器关闭时,Cookie将被删除。
指定0秒:表示浏览器删除Cookie;
使用Cookie保存用户的登录信息,只需要登录一次,以后就可以直接访问页面:
//登录的用户名和密码
String name=req.getParameter("name");
String pwd=req.getParameter("password");
StringBuffer sb=new StringBuffer();
sb.append("username-");
sb.append(name);
sb.append("&password-");
sb.append(pwd);
//新建一个Cookie对象用来保存用户信息
//cookie中是以键值对保存信息
Cookie cookie=new Cookie("myInfo",sb.toString());
//设置存活时间
cookie.setMaxAge(1800);
//在响应中添加该cookie
res.addCookie(cookie);
//重定向
res.sendRedirect("login");
//获取cookie中的信息
Cookie[] cookies=req.getCookies();
for(int i=0;i<cookies.length;i++){
Cookie cookie1=cookies[i];
String cname=cookie1.getName();
if(cname.equals("myInfo")){
String cvalue=cookie1.getValue();
String[] myinfo=cvalue.split("&");
//继续处理
}
}
Cookie是在响应报头和请求报头中被传送,不与传送的内容混合在一起,所以Cookie的使用对于用户来说是透明的。
URL重写
使用浏览器时,如果禁用Cookie,Web服务器就无法利用Cookie来跟踪用户的会话,就要使用URL重写机制。
URL重写就是在URL中附加标识客户的SessionID。Servlet容器解释URL,取出SessionId,与特定的Session关联。
例如:http://163.com/bbs/index.jsp;jsessionid=1234567
服务器将SessionID作为URL的一部分发送给客户端,客户端在请求URL中再传回来,就可以跟踪用户的会话。
要跟踪客户端会话,需要将所有发往客户端的URL进行编码,可以使用HttpServletResponse接口的encodeURL()方法和encodeRedirectURL()方法来实现。
public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException,IOException{
res.setContentType("text/html;charset=utf-8");
//判断曾经是否登录
//获得HttpSession对象,如果没有给客户端分配,则创建一个新的session
//可以给参数false,当没有分配Session,则会返回null
HttpSession session=req.getSession();
//客户端禁止Cookie,则每次请求都是新的
boolean isnew=session.isNew();
//设置和获取属性 维护客户的状态信息
session.setAttribute("user","wdz");
String user=(String)session.getAttribute("user");
//会话ID
String id=session.getId();
//创建时间 1970年以来的 毫秒数
long createTime=session.getCreationTime();
//最后一次访问时间
long acctime=session.getLastAccessedTime();
//最大不活动时间间隔(秒),连续两次请求之间保持Session打开的最大时间间隔
//超过这个时间间隔,Session失效
int inactive=session.getMaxInactiveInterval();
//设置最大间隔时间:负值:表示Session永不失效(只对调用该方法的session有效)
session.setMaxInactiveInterval(36);
定义Web应用程序中所有session 的超时时间:web.xml中配置
<!--单位是 分钟-->
<!--0或负数:session不会没有超时值,不会因长时间没有提交而失效-->
<session-config>
<session-timeout>5</session-timeout>
</session-config>
在%CATALINA%\conf\web.xml中定义了session的默认超时值是30分钟。可以修改这个默认值。
在使用URL重写机制的时候,为了保证会话跟踪的正确性,所有的链接和重定向语句中的URL都需要调用encodeURL()或encodeRedirectURL()方法进行编码。
当调用getSession()方法时,而且没有在客户的请求中得到会话ID时,容器会尝试与客户建立一个新的会话。容器并不知道Cookie是否被禁用,所以在向客户返回第一个响应时,它会同时使用Cookie和URL重写这两种机制。
客户发出下一个请求,那么在请求中会包含Sessionid Cookie,同时在URL后也会有附加的Sessionid。容器会首先尝试从Cookie中获取Session,如果发现能够得到SessionId,就会知道这个用户接受Cookie,那么在随后的响应中,它就会使用Cookie来跟踪会话。
Session与Cookie深入探讨
Session在服务端保存信息,Cookie在客户端保存信息,为了跟踪会话,服务器端在创建Session后,需要将SessionID交给客户端,因此在cookie中有JSessionID=value;但是它通常是保存在浏览器的内存中(因为Tomcat中设置为MaxAge为负数),并且也不能在多个浏览器之间共享。当不关闭浏览器在客户端再次请求时,这个ID随请求一起发送回来。如果关闭浏览器,那么保存该SessionID的cookie就被删除,导致sessionid丢失了,无法找到先前的sessionid,服务器只能创建一个新的session。而这个时候先前的session是仍然存在的,直到超过设置的session超时时间间隔,那么服务器会清除该session。(可以通过持久化cookie找回session)
而利用Cookie进行会话,既可以保存在浏览器内存中,也可以持久化(这时sessionid也是被保存到硬盘,因为sessionid就是cookie中的一个键值对)。当cookie存储在浏览器内存中时,只能被同一个浏览器进程所共享;但是对于保存在硬盘上的Cookie,可以在多个浏览器所共享。
总结一句话:SessionId是随着Cookie的保存位置而保存。
