一、Cookie
1.1 Cookie工作原理?
1.2 Cookie API
二、Session
2.1 Session原理
2.2 Session API
(1) 构造函数
(2) 常用方法
2.3 Session超时管理
HTTP是无状态的协议,一次请求结束之后连接就会断开,下次服务器再次接收同样的请求时,服务器不知道这个请求是那个用户发过来。当然,服务器知道这个请求是从那个IP地址发过来的,但是服务器所服务的对象是用户,而不是客户端。因此,服务器需要一种能够跨越多个请求识别用户请求的跟踪技术,这个过程就是服务器的会话管理。
举个栗子:用户在访问Web应用程序之前需要进行登录进行身份验证,用户输入正确的用户名和密码之后,用户再次发送访问请求时,Web服务器能够记住这个请求的用户是否已经登录等等。
用于保持状态的方法有4种:网址重写(URL rewriting)、隐藏域、Cookie及HttpSession对象,本篇教程主要介绍Cookie和Session。
Cookie是存储在客户端本地上的文本文件,能够跨越多个页面传递信息。Web应用程序将用户会话过程中产生的数据以Cookie的形式保存到用户本地硬盘中。当用户使用浏览器再去访问服务器中的Web资源时,就会带着上次访问的数据过去,从而使服务器分辨出当前请求是由那个用户发出的。
Cookie是嵌入在HTTP标头的,它的传输过程由HTTP协议。例如,服务器向客户端发送Cookie时,HTTP响应头子段中增加Set-Cookie响应头字段。Set-Cookie头子段中设置的Cookie遵循一定的语法格式,具体如下:
Set-Cookie:user=itcast;Path=/;
上述实例中,user表示Cookie的名称,itcast表示Cookie的值,Path表示Cookie的属性。需要注意的是,Cookie必须以键值对的形式存在,其属性可以有多个,但这些属性必须用分号(;)和空格分隔。下面是响应报文中的例子:
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=Laoye; sex=Male; path=/;
Connection: close
Content-Type: text/html
Servlet API中提供了一个javax.servlet.http.Cookie类,该类包含生成Cookie信息和提取Cookie信息各个属性的方法。它的创建方法和常用方法如下:
(1) 构造函数
Cookie cookie = new Cookie(name,value);
参数name用于指定Cookie的名称,value用于指定该Cookie的值。需要注意的是,Cookie一旦被创建,它的名称就不能更改,但是它的值可以是任何值并且允许创建后被修改。
* 案例代码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//获取所有Cookie
Cookie[] cookies = request.getCookies();
//如果Cookie为空,就创建Cookie对象;如果不为空这就获取值
if(cookies == null || cookies.length == 1){
String name = request.getParameter("name");
String password = request.getParameter("password");
//创建Cookie对象,并添加到响应中
response.addCookie(new Cookie("name",name));
response.addCookie(new Cookie("password",password));
}else{
for(int i=0;i ");
}
}
* 结果展示
(2) 常用方法
下面列表列出了Cookie对象的常用方法,具体如下:
声明方法 |
功能描述 |
String getName() |
获取Cookie的名称 |
String getValue() |
获取Cookie的值 |
void setValue(String newValue) |
设置Cookie的值 |
int getMaxAge() |
获取Cookie的最大生存周期(单位:秒) |
void setMaxAge() |
设置Cookie的过期时间。如果不设置,Cookie只会在当前的Session会话中有效 |
String getPath() |
获取Cookie有效路径 |
void setPath(String uri) |
设置Cookie有效路径 |
String getDomain() |
获取Cookie的有效域 |
void setDomain(String pattern) |
设置Cookie的有效域 |
下面针对比较难以理解的方法进行讲解
上面这两个方法用于设置和返回Cookie在浏览器上保持有效的秒数。
如果值为正整数,浏览器会将Cookie信息保存在本地硬盘中,从当前时间开始,在没有超过指定秒数之前,这个Cookie都保持有效。
如果值为负整数,浏览器会将Cookie信息保存在缓存中,当浏览器关闭时,Cookie信息会被删除。
如果值为0,浏览器会立刻删除这个Cookie信息。
* 案例代码
String name = request.getParameter("name");
Cookie CName = new Cookie("name",name);
CName.setMaxAge(0);
response.addCookie(CName);
* 结果展示
上面这两个方法是针对Cookie在Web应用的有效范围。
如果创建Cookie对象没有设置Path属性,那么该Cookie只对当前访问路径所属的目录及其子目录有效。
如果想让某个Cookie项对站点的所有目录下的访问路径都有效,通过调用setPath()方法设置Path属性值为”/”。
* 结果展示
上面这两个方法,用来指定Cookie在浏览器所访问的有效域。设置Domain属性时,值必须以”.”开头,例如”.laoye.com”。
默认情况下,Domain属性的值为当前主机名,浏览器在访问当前主机下的资源时,都会将Cookie信息回送给服务器。需要注意的时,Domain属性的值是不区分大小写的。
Cookie技术可以将用户的信息保存在各自的浏览器中,并且可以在多次请求下实现数据的共享。但是如果传递的信息比较多,使用Cookie技术显然会增大服务器端程序的处理难度。这时,可以使用Session实现,Session是一种将会话数据保存到服务器端的技术。需要注意的是,由于客户端需要接收、记录和会送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。
客户端初次访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性。其中,Session对象存储着会话数据,ID是识别当前请求的唯一标识。服务器处理完此次请求之后,就会将Session的ID号通过Cookie传递给客户端存储下来。
客户端后续访问Web服务器时,服务器通过客户端Cookie传递过来的ID标识号,就能判断出该请求是那个用户发送的,从而选择与之对应的Session对象为其服务。判断服务器中是否存在这个Session,如果存在则直接使用,如果不存在则生成新的Session。
获取Session对象可以通过调用HttpServletRequest的公共方法getSession()来获取HttpSession对象,该方法有两种重载形式,具体如下:
public HttpSession getSession()
public HttpSession getSession(boolean create)
上面重载的两个方法都用于返回当前请求相关的HttpSession对象。无参的方法在相关HttpSession不存在时总是会创建新的HttpSession对象,而带参的方法则可以手动设置是否创建HttpSession对象。
需要注意的是,getSession()方法会产生会话标识号的Cookie头字段,因此必须在发送响应内容之前调用getSession方法。
获取到HttpSession对象之后,接下来就要对会话数据进行操作了,下面表格列出了常用的操作方法。
方法声明 |
功能描述 |
String getId() |
返回当前HttpSession对象的会话标识 |
long getCreationTime() |
返回Session创建的时间。 |
setMaxInactiveInterval(int interval) |
设置Session对象的有效时间 |
invalidate() |
强制使Session对象无效 |
string getAttribute() |
从Session域中获取指定参数 |
setAttribute(String name,Object value) |
将一个参数存储到Session域中 |
removeAttribute(String name) |
从Session域中删除指定参数 |
接下来,我们通过下面的实例来看看具体的效果吧。
* 案例代码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//如果不存在Session会话,那就创建一个
HttpSession session = request.getSession(true);
int num = 1;
try{
num = (int)session.getAttribute("num");
session.setAttribute("num", (++num));
}catch(Exception e){
session.setAttribute("num", num);
}
writer.print("你是第" + num + "次访问该网站
");
//获取Session的创建时间
Date creatTime = new Date(session.getCreationTime());
//获取该网页的最后一次访问时间
Date lastAccessTime = new Date(session.getLastAccessedTime());
//设置日期的输出格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//获取SessionID
String sessionID = session.getId();
//往Session域中添加参数
session.setAttribute("name", "张三");
//获取Session域中的参数
String name = (String) session.getAttribute("name");
String sex = (String) session.getAttribute("sex");
writer.print("Session创建时间:"+sdf.format(creatTime)+"
");
writer.print("最后一次访问时间"+sdf.format(lastAccessTime)+"
");
writer.print("SessionID:"+sessionID+"
");
writer.print("参数name:"+name+"
");
* 结果展示
需要注意的是,Web服务器无法判断当前客户端是否还会继续访问,也无法监测客户端浏览器是否关闭。所以,即使客户端已经结束访问或关闭了浏览器,Web服务器还是会保留与之对应的HttpSession对象。随着时间推荐,这些不再使用的HttpSession对象积累的越来越多,从而使Web服务器内存耗尽。
所以为了解决上述问题,Web服务器采用了“超时限制”的办法来判断客户端是否还继续访问。在一定时间内,如果某个客户端一直没有请求访问,那么Web服务器就会默认该客户端已经结束请求,并且将与该客户端会话所对应的HttpSession对象编程垃圾对象,等待垃圾回收器将其从内存中彻底删除。
这种方式有以下三种方式
HttpSession session = request.getSession(true);
session.setMaxInactiveInterval(5);
HttpSession session = request.getSession(true);
session.invalidate();
注意:如果当前Session对象被注销之后,后续对该Session对象进行操作的话,程序会报错。
10
注意:<session-timeout>标签中的时间值设置成0或者负整数,则表示会话永远不超时。