摘自:《深入体验Java Web开发内幕--核心基础》。
Web应用的会话状态是指Web服务器与浏览器在会话过程中产生的状态信息,借助会话状态,Web服务器能够把属于同一会话中的一系列的请求和响应过程关联起来,使得他们之间可以相互依赖和传递信息。
由于HTTP协议本身不具有会话状态,要想在Web应用程序中维持会话状态信息和实现有状态的会话管理,在Web服务器端程序的开发方案中需要提供一些专门的技术来解决。
会话ID可以通过Cookie技术在请求消息中传递,也可作为请求URL的附加参数进行传递。会话ID是Web服务器为每个客户端浏览器分配的一个唯一代号,通常是Web服务器接收到浏览器的第一次访问时产生,并随同响应消息一道发给浏览器,浏览器以后在以后发出的访问消息中都顺带一条“我的代号是...”。会话过程由Web服务器端的程序开启,一旦开启了一个会话,同一个会话中的访问请求都可以且只能访问属于该会话的存储结构中的状态信息。
Cookie
=======
Cookie是在浏览器访问Web服务器的某个资源时,由Web服务器在HTTP响应消息头中附带传送给浏览器的一片数据,浏览器可以决定是否保存这片数据,一旦保存了,以后每次访问时,都应在请求头中将数据回传给Web服务器。Cookie最先是Web服务器发出的,通过在HTTP响应消息中增加Set-Cookie字段将Cookie信息发送给浏览器。
一个Cookie只能标识一种信息,它至少包含有一个信息的名称(NAME)和设置值(VALUE)。
Cookie实现了一种在浏览器和服务器之间产生有状态会话的方式,它可以把一个浏览器访问的同一个服务器上的所有程序连贯起来,在这些程序之间传递数据。
响应头:Set-Cookie2: user=me; Version=1; Path=/
如果浏览器愿意接受Web服务器发送过来的Cookie信息,它将存储Cookie信息。多个Cookie信息可以且只能通过一个Cookie请求字段回送给Web服务器。
请求头:Cookie: $Version=1; Course=Java; $Path=/my/lesson; Course=vc; $Path=/my
在Servlet程序中使用Cookie
----------------------------------------
javax.servlet.http.Cookie类封装了Cookie信息。
getName(), setValue(), getValue(), setMaxAge, getMaxAge, setPath, getPath, setDomain, getDomain, setVersion, getVersion, setComment, getComment, setSecure, getSecure。
HttpServletResponse.addCookie()
HttpServletRequest.getCookies()
Cookie ckName = new Cookie("name", name);
Cookie ckNickname = new Cookie("nickname", nickname);
ckNickname.setMaxAge(365*24*3600);
response.addCookie(ckName);
response.addCookie(ckNickname);
Cookie[] cks = request.getCookies();
for (int i = 0; cks != null & i < cks.length; i++) {
if ("nickname".equals(cks[i].getName()))
{
lastNickname = cks[i].getValue();
break;
}
}
Session
========
使用Cookie和附加URL参数都可以将上一次请求的状态信息传递到下一次请求中,但是如果传递的状态信息较多,将极大降低网络传输效率和增大服务器端程序处理的难度。
Servlet API规范中定义了一个HttpSession接口,HttpSession接口定义了各种管理和操作会话状态的方法,一个客户端在Web服务器端对应一个各自的HttpSession对象。由于创建HttpSession对象会消耗内存资源,Web服务器并不会在客户端开始访问它时就创建HttpSession对象。只有客户端访问某个特殊的Servlet程序,并且这个Servlet程序决定与客户端开启一个会话时,Web应用程序才会创建一个与该客户端对应的HttpSession对象,并把这个会话标识号传递给客户端。HttpSession对象驻留在Web服务器内存之中,该客户端此后访问任意的Servlet程序时,它们都使用与客户端对应的那个已存在的HttpSession对象。setAttribute(),getAttribute()。
超时限制时间单位为分钟。
<session-config>
<session-timeout>30</session-timeout>
</session-config>
HttpSession接口中的方法
------------------------------------
getId, getCreationTime, getLastAccessedTime, setMaxInactiveInterval, getMaxInactiveInterval, isNew, invalidate, getServletContext, setAttribute, getAttribute, removeAttribute, getAttributeNames.
HttpServletRequest接口中的Session方法
---------------------------------------------------------
getSession, isRequestedSessionIdValid, isRequestedSessionIdFromCookie, isRequestedSessionIdFromURL.
application域与session域属性的比较
------------------------------------------------------
在ServletContext对象和HttpSession对象中设置的属性都可以被Web应用程序中的多个Servlet程序访问,从而可以实现在多个Servlet程序之间传递和共享信息的功能。
同一个Web应用程序中的所有Servlet程序得到的是同一个ServletContext对象,所以存储在ServletContext对象中的属性可以被所有的Servlet程序访问和共享,而不管访问来自哪个客户端。
存储在HttpSession对象中的属性也可以被所有的Servlet程序访问,但仅仅是来自同一个客户端的一组访问才能共享一个HttpSession对象,来自不同客户端的各组访问共享的HttpSession对象是不同的。
利用Cookie实现Session跟踪
-------------------------------------------
如果Web服务器处理某个访问请求时创建了新的HttpSession对象,它将把会话标识号作为一个Cookie项加入到响应消息中,通常情况下,浏览器在随后发出的访问请求中又将会话标识号以Cookie的形式回传给Web服务器。
利用URL重写实现Session跟踪
-----------------------------------------------
考虑到浏览器有可能不支持Cookie的情况,Servlet规范中还引入了一种补充的会话管理机制。这种补充机制要求在响应消息的实体内容中必须包含下一次请求的超链接,并将会话标识号作为超链接的URL地址的一个特殊参数。
HttpServletResponse接口中定义了两个用于完成URL重写方法:encodeURL,encodeRedirectURL。
out.println("<a href='" + response.encodeURL("SessionServlet2") + "'>访问SessionServlet2</a>");