概念
Cookie是服务端发送到用户浏览器并且保存到本地的一小块数据,它会在浏览器下次向同一服务器发起请求时,被携带到服务器上。
为什么有cookie
因为HTTP协议是无状态的(HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。),即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。 在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。 最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么。 所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。 服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。 在刚才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段Cookie,记录着那项商品的信息。 当用户访问另一个页面,浏览器会把Cookie发送给服务器,于是服务器知道他之前选购了什么。 用户继续选购饮料,服务器就在原来那段Cookie里追加新的商品信息。 结帐时,服务器读取发送来的Cookie就行了。 Cookie另一个典型的应用是当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。 如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。 这正是因为前一次登录时,服务器发送了包含登录凭据(用户名加密码的某种加密形式)的Cookie到用户的硬盘上。 第二次登录时,如果该Cookie尚未到期,浏览器会发送该Cookie,服务器验证凭据,于是不必输入用户名和密码就让用户登录了。
以上内容是维基百科对Cookie的解释,为什么有Cookie? 说白了: 因为浏览器与人需要一种交互,Cookie则实现了这种交互;服务器通过向用户发送Cookie给予了用户某种“权限”,这好比是一张门票,当浏览器携带着“门票”向服务器发起请求时,服务器通过验证“门票”信息就可以赋予用户某种“权限”。接下来我用注册与登陆的示例来简单地介绍下 Cookie的具体应用场景。
基本原理
当浏览器向服务器发送请求的时候,服务器会将少量的数据以 set-cookie 消息头的方式发送给客户端, 浏览器一般会自动将 cookie 数据进行存储,当客户端再次访问服务器时,会将这些数据以 cookie 消息头的方式发送给服务器,服务端就可以根据 cookie 消息头来判别用户的身份或进行一些特别的处理并返回响应。
生存期
从 cookie 的工作原理上可以知道 cookie 信息主要是存储在客户端的状态, 而 cookie 在客户端的生存期则主要由属性 max-age 决定, max-age 属性以秒为单位表示 cookie 的存活时间为 max-age 秒; 当然 cookie 还有一个属性 expires 其作用和 max-age 是一样的这在后续会进行详细说明。默认情况下 cookie 只是暂时存在的,他们存储的值只在浏览器会话期间存在,当用户关闭浏览器窗口后这些值也会随之销毁(生成的 cookie 临时存储于浏览器内存中)
max-age 为正数: cookie 会在 max-age 秒之后被销毁(会将状态存储于 cookie 文件中并存储于本地硬盘中)
max-age 为负数时: cookie 只在浏览器会话期间存在,当用户关闭浏览器窗口后这些值也会随之销毁(生成的 cookie 临时存储于浏览器内存中)
max-age 为 0 时: cookie 将被立即销毁
Cookie细节
cookie编码
在tomcat 8 之前 cookie中不能直接存储中文数据。需要将中文数据转码---一般采用URL编码(%E3)
在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析。
举个例子 在服务器中的Servlet判断是否有一个名为lastTime的cookie有:不是第一次访问响应数据:欢迎回来,您上次访问时间为:2020年7月31日11:50:20
写回Cookie:lastTime=2020年7月31日11:50:20
没有:是第一次访问响应数据:您好,欢迎您首次访问
写回Cookie:lastTime=2020年7月31日11:50:20
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应的消息体的数据格式以及编码
response.setContentType("text/html;charset=utf-8");
// 1.获取所有Cookie
Cookie[] cookies = request.getCookies();
boolean flag = false;//没有cookie为lastTime
// 2.遍历cookie数组
if(cookies != null && cookies.length > 0){
for (Cookie cookie : cookies) {
// 3.获取cookie的名称
String name = cookie.getName();
// 4.判断名称是否是:lastTime
if("lastTime".equals(name)){
// 有该Cookie,不是第一次访问
flag = true;//有lastTime的cookie
// 设置Cookie的value
// 获取当前时间的字符串,重新设置Cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String str_date = sdf.format(date);
System.out.println("编码前:"+str_date);
// URL编码