一、前言
HTTP协议是一种无状态的协议,Web服务器本身不能识别出哪些请求是同一个浏览器发出的,浏览器的每一次请求都是完全孤立的。作为web服务器,必须能够采取一种机制来唯一的标识一个用户,同时记录该用户的状态。
二、会话
在日常生活中,从拨通电话到挂断电话之间的一连串的你问我答的过程就是一个会话。Web应用中的会话过程类似于生活中的打电话过程,它指的是一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应过程,例如,一个用户在某网站上的整个购物过程就是一个会话。
在打电话过程中,通话双方会有通话内容,同样,在客户端与服务器端交互的过程中,也会产生一些数据。例如,用户甲和乙分别登录了购物网站,甲购买了一个Nokia手机,乙购买了一个Ipad,当这两个用户结账时,Web服务器需要对用户甲和乙的信息分别进行保存。HttpServletRequest对象和ServletContext对象都可以对数据进行保存,但是这两个对象都不可行,具体原因如下:
- 客户端请求Web服务器时,针对每次HTTP请求,Web服务器都会创建一个HttpServletRequest对象,该对象只能保存本次请求所传递的数据。由于购买和结账是两个不同的请求,因此,在发送结账请求时,之前购买请求中的数据将会丢失。
- 使用ServletContext对象保存数据时,由于同一个Web应用共享的是同一个ServletContext对象,因此,当用户在发送结账请求时,由于无法区分哪些商品是哪个用户所购买的,而会将该购物网站中所有用户购买的商品进行结算,这显然也是不可行的。
- 为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。
三、Cookie
Cookie翻译成中文意思是点心,可以理解为:服务器送给浏览器的一个点心。
其实Cookie就是键值对,由一个键和一个值构成的,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。
底层的实现原理:Web服务器通过在HTTP响应消息中增加 Set-Cookie 响应头字段将Cookie信息发送给浏览器,浏览器通过在HTTP请求消息中增加 Cookie请求头 字段将Cookie回传给Web服务器。
四、Cookie常用API
在JavaEE中提供了javax.servlet.http.Cookie类,该类提供了获取Cookie与设置Cookie的相关方法。具体内容如下:
方法声明 | 功能描述 |
Cookie(String name, String value) | 构造方法 |
getName() | 获取Cookie的名称 |
setValue() | 设置Cookie的值 |
getValue() | 获取Cookie的值 |
setPath() | 设置Cookie项的有效目录路径 |
getPath() | 获取Cookie的路径 |
setMaxAge() | 设置Cookie在浏览器上保持的时间,以秒为单位 |
下面分别学习一些常用方法:
- 向客户端响应Cookie:
HttpServletResponse接口中定义了一个addCookie方法,它用于在发送给浏览器的HTTP响应消息中增加一个Set-Cookie 响应头字段。
// 创建Cookie实例对象
Cookie cookie = new Cookie("name","jzy");
// 将Cookie实例对象添加到Response对象中
response.addCookie(cookie);
- 读取请求中的Cookie:
HttpServletRequest接口中定义了一个getCookies方法,它用于从HTTP请求消息的Cookie请求头字段中读取所有的Cookie项。
//1 通过Request对象获取请求中的Cookies
Cookie[] cookies = request.getCookies();
//2 判断请求中的Cookies是否存在
if(cookies != null && cookies.length > 0){
//3 遍历所有Cookies
for (Cookie cookie : cookies) {
out.print(cookie.getName + "" + cookie.getValue());
}
}
这里比较遗憾的是:我们只能对数组进行遍历循环,直到找到感兴趣的cookie为止。
- 设置 Cookie 的最大时效:
会话Cookie是保存在浏览器的内存中,当一次会话结束或关闭浏览器后,Cookie信息将会丢失或被删除。
持久Cookie是保存在浏览器的临时文件夹中,当一次会话结束或关闭浏览器后,Cookie信息依然会被保存。
值得注意的是,持久Cookie存在过期时间,过期后Cookie会被自动删除。可以利用setMaxAge(int age)方法设置持久Cookie的有效时间。(若为 0 , 表示立即删除该 Cookie;若为负数, 表示不存储该 Cookie, 若为正数, 表示该 Cookie 的存储时间)
//创建一个 Cookie 对象
Cookie cookie = new Cookie("name", "atguigu");
//设置 Cookie 的最大时效, 以秒为单位。
cookie.setMaxAge(30);
//调用 response 的一个方法把 Cookie 传给客户端.
response.addCookie(cookie);
- Cookie中保存中文:
Cookie的name和value都不能使用中文,如果希望在Cookie中使用中文,那么需要先对中文进行URL编码,然后把编码后的字符串放到Cookie中
向客户端响应中添加Cookie
String name = URLEncoder.encode("姓名", "UTF-8");
String value = URLEncoder.encode("张三", "UTF-8");
Cookie cookie = new Cookie(name, value);
c.setMaxAge(3600);
response.addCookie(cookie);
五、Cookie的一个小案例
实现用户自动登录功能(第一次登录时,将用户名和密码存储在Cookie):
login.jsp页面代码:
<form action="index.jsp" method="post">
name: <input type="text" name="name"/>
<input type="submit" value="Submit"/>
index.jsp页面代码:
//若可以获取到请求参数 name, 则打印出欢迎信息。把登录信息存储到 Cookie 中,并设置 Cookie 的最大时效为 30s
String name = request.getParameter("name");
if(name != null && !name.trim().equals("")){
Cookie cookie = new Cookie("name", name);
cookie.setMaxAge(30);
response.addCookie(cookie);
}else{
//从 Cookie 中读取用户信息,若存在则打印欢迎信息
Cookie [] cookies = request.getCookies();
if(cookies != null && cookies.length > 0){
for(Cookie cookie : cookies){
String cookieName = cookie.getName();
if("name".equals(cookieName)){
String val = cookie.getValue();
name = val;
}
}
}
}
if(name != null && !name.trim().equals("")){
out.print("Hello: " + name);
}else{
//若既没有请求参数,也没有 Cookie,则重定向到 login.jsp
response.sendRedirect("login.jsp");
}