1 什么是会话?
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求响应的过程,例如一个用户在某网站上的整个购物过程就是一个会话。
在打电话过程中,通话双方有通话内容,同样,在客户端与服务器端交互的过程中,也会产生一些数据。例如,用户甲和乙的信息分别登录了购物网站,甲购买了一个iphone手机,乙购买了一个ipad,当这两个用户结账时,Web服务器需要对用户甲和乙的信息分别进行保存。其中HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是这两个对象都不行,具体原因如下:
客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求的数据会丢失。
使用ServletContext对象保存数据时,由于同一个Web应用共享的时是一个ServletContext对象,因此,当用户在发送结账请求时,由于无法区分哪些商品时哪个用户购买的,而会将购物网站中所有用户购买的商品进行结算,这显然也是不可行的。
为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别为Cookie和Session。
具体来说,Cookie和Session技术的存在是为了保存会话过程中产生的数据。
2 Cookie技术
2.1 Cookie简介
Cookie翻译过来是饼干的意思。Cookie 是 Servlet 发送到 Web 浏览器的少量信息,这些信息由浏览器保存,然后发送回服务器。 Cookie 可以唯一的标识客户端,因此 Cookie 常用于会话管理。
说明:
- Cookie是服务器通知客户端保存键值对的一种技术
- 客户端有了 Cookie 后,每次请求都发送给服务器
- 每个 Cookie 的大小不超过 4kb
2.2 Cookie的理解与创建
在生活中,我们经常遇到这样的情况:登录一个网站后,下一次再登录,不需要重复输入账户密码,这就是使用到了cookie存储了一些需要的数据。
Cookie是客户端技术,服务器会将每个用户的数据以cookie的形式发送给用户各自的浏览器,当用户使用浏览器访问各自的资源时,就带着各自的数据去操作。 Cookie唯一标识了客户端。示意图如下:
Cookie创建的实现原理如下:
Cookie实现基于http协议,响应头:set-cookie,请求头:cookie
浏览器会一次性地将当前域名下的所有的Cookie都携带到对应的资源里去,我们需要时就直接获取对应键的名称就可以得到。
在Cookie的创建中,首先客户端是没有Cookie的,由Tomcat服务器创建了Cookie对象,存储了相应的键值对,并通过响应头通知客户端保存相应的cookie。客户端收到响应后,则会去创建相应的Cookie,如果已经存在,则会去修改。 示意图如下:
Cookie创建示例代码:
import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 兴趣使然黄小黄 * @version 1.0 */ public class HelloCookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Cookie cookie = new Cookie("name", "Peter"); resp.addCookie(cookie); } }
示例中,我们只创建了一个Cookie,实际可以创建多个,这里不再赘述。
2.3 服务器获取Cookie与Cookie的修改
服务器获取客户端的Cookie,只需要短短一行代码:
req.getCookies(); 1
该方法会返回一个Cookie[]。
下面演示将Cookie创建案例中的cookie获取到服务端,并打印:
HelloCookie添加如下代码:
CookieServlet.java
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author 兴趣使然黄小黄 * @version 1.0 */ public class CookieServlet extends HttpServlet { protected void getCookie(HttpServletRequest req, HttpServletResponse resp) throws IOException { Cookie[] cookies = req.getCookies(); for (Cookie cookie : cookies) { //getName方法返回cookie的key //getValue方法返回对应的value resp.getWriter().write("Cookie[" + cookie.getName() + "=" + cookie.getValue() + "]<br/>"); } } }
如果想要获取特定name的值,只需要在遍历过程中进行过滤判断。一般进行过滤筛选的方法,为了方便起见,常常写成工具类:
import javax.servlet.http.Cookie; /** * @author 兴趣使然黄小黄 * @version 1.0 * 工具类 */ public class CookieUtils { /** * 寻找特定的cookie * @param name 查找的key * @param cookies 获取的cookies数组 * @return 返回特定的cookie或者null */ public static Cookie findCookie(String name, Cookie[] cookies){ if (name == null || cookies == null || cookies.length == 0){ return null; } for (Cookie cookie : cookies) { if (name.equals(cookie.getName())) { return cookie; } } return null; } }
Cookie的修改
方案一:
创建一个同名的Cookie对象;
在构造器中赋予新Cookie值;
调用response.addCookie(newCookie);
方案二:
先找到需要修改的Cookie对象;
调用setValue()方法赋予新的Cookie值;
调用response.addCookie(cookie);
2.4 Cookie的生命控制与生命周期
Cookie的生命控制指的是如何管理Cookie什么时候被销毁(删除)。
默认情况下:
Cookie存储在浏览器内存中,当关闭浏览器内存释放,它自动销毁,所谓的无痕浏览就是这样。
非默认情况,人为设定:
通过setMaxAge(int expiry)指定cookie的最大生存时间(以秒为单位)。
正值表示cookie将在经过该值数秒后过期,负值则意味着不能持久存储,将在web浏览器退出时删除。
Cookie cookie = new Cookie("name", "Peter"); cookie.setMaxAge(60*60*24*3); //设置存活时间三天 resp.addCookie(cookie);