在了解cookie和session之前,需要先了解一个概念:会话
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。web应用中的会话过程类似于生活中的打电话过程,它指的是客户端(浏览器)与web服务器之间连续发生的一系列请求和响应的过程。例如:一个用户在某个网站上的整个购物过程就是一个会话。
HttpServletRequest对象和ServletContext都可以对数据进行保存,但是针对下面所描述的需求就不可行:
用户甲和乙分别登录购物网站,甲在购物车中添加了一个iphone手机,乙在购物车中添加了一个Ipad平板,这时web服务器需要对用户甲和用户乙的信息分别进行保存。
HttpServletRequest对象存储为什么不能实现该需求呢?
客户端请求web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买的数据会丢失。
ServletContext对象为什么不能实现改需求呢?
使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用户发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中的所有用户购买的商品进行结算,这显然也是不行的。
为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。
Cookie数据存放在客户的浏览器上。
当用户通过浏览器访问Web服务器时,服务器会给客户端发送一些信息,这些信息会保存在Cookie中。这样,当浏览器再次访问服务器时,会在请求头中将Cookie发送给服务器,方便服务器对浏览器做出正确的响应。
单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K.
服务器向客户端发送Cookie时,会在HTTP响应头中增加Set-Cookie响应头信息。Set-Cookie头字段中设置的Cookie遵循一定的语法格式,具体如下:
Set-Cookie: name=Tom;Path=/;
注意:Cookie必须以键值对的形式存在,其属性可以有多个,但这些属性之间必须用分号;和空格分隔。
1、增加Cookie
// 创建一个Cookie对象
Cookie cookie1 = new Cookie("name", "Tom");
Cookie cookie2 = new Cookie("age", "35");
// 将生成的Cookie发送到浏览器
response.addCookie(cookie1);
response.addCookie(cookie2);
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie.getName()+" " + cookie.getValue());
}
每次请求都会将Cookie放到请求头中。
3、设置Cookie中文:URLEncoder(编码),URLDecoder(解码)
4、设置Cookie持久化时间
Cookie cookie = new Cookie("name", "Tom");
cookie.setMaxAge(60*60*24*365); //单位是秒
response.addCookie(cookie);
5、设置Cookie作用域
cookie.setPath()
Cookie cookie = new Cookie("name", "James");
//设置Cookie访问路径:path
//1:只要访问同一个Tomcat中所有的项目资源,都会携带Cookie
cookie.setPath("/");
//2:只要访问我当前项目中的/cookie目录下所有资源,都会携带Cookie
cookie.setPath("/cookie");
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
6、删除Cookie
//清除Cookie
Cookie cookie = new Cookie("name", "");
//1:设置访问的路径path, 这里的Path必须和设置Cookie 的路径保持一致
cookie.setPath(request.getContextPath());
//2:设置存活时间
cookie.setMaxAge(0);
//3:将cookie发送到浏览器
response.addCookie(cookie);
Session数据放在服务器内存中。
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,当客户端后续访问服务器时,只要将标识号传递给服务器,服务器就能判断该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。
注意:由于客户端需要接受、记录和回送Session对象的ID,因此,通常情况下,Session是借助Cookie技术来传递ID属性的。
Session技术的原理描述:
1、添加Session
// 创建Session对象
HttpSession session = request.getSession();
// 设置值
session.setAttribute("name", "Tom");
2、获取Session
HttpSession session = request.getSession();
Object name = session.getAttribute("name");
3、获取Session编号ID
String id = session.getId();
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
Session的超时时间为maxInactiveInterval属性,可以通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(longinterval)修改。
Session的超时时间也可以在Tomcat的config目录下的web.xml中修改。
30
另外,通过调用Session的invalidate()方法可以使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地址重写。