Ⅰ 前言
从字面上来看,cookie就是曲奇饼,session就是会话。那在web中,对应的指代就是服务器给客户端一个网络小饼干,和 服务器和客户端建立一次互有往来的对话。
Ⅱ 会话
A. 理解会话
我们简单来定义一下会话的概念,就是用户打开一个浏览器,点了很多链接,访问不同的 Web 资源(对应不同的servlet),关闭浏览器的这个全过程。
会话又分成了无状态会话 和 有状态会话,无状态会话就是一次简单的打开关闭,后台是不需要专门去保存客户端的状态的。我们主要来说一下有状态会话。
我举个例子,学校是如何确定你是本校的学生的呢?
在进校的时候,每个人都会收到一个学号,你可以把学号拿给学校看,这是一个方法。
第二个方法就是学校从自己的系统中找记录,找到你了,那你肯定就是这个学校的学生了。
通过这两个方法都可以明确你确实是这个学校的。
那么一个网站(服务端)要是想要知道某个用户(客户端)访问过它,要怎么做呢?
对应的还是两种方法:
- 在客户端访问它的时候,它会给客户端一个网络小饼干(cookie),这就是一个服务端给客户端的一个信件,下次客户端再去,就带着这个cookie,网站就可以认出它。
- 服务端记录一下你来过了,这样你下次来的时候,网站就会从记录中和你匹配一下,匹配上了,就代表你原来来过。(session)
所以有状态会话的意思就是,客户端访问了一个网站,第二次访问的时候,网站还知道这个客户端来过,这就是有状态会话。而要记录状态就只有 cookie 和 seesion 这两种方法,
B. 保存会话的两种技术
上面我们提到的cookie和session就是保存会话的两种技术,其中:
cookie 是客户端技术,对应着客户端的请求然后服务端响应。
session 是服务器技术,这个技术可以将用户的会话信息保存在session中。
常见的应用就是在一个网站登录之后,一段时间内你就不需要再登了,比如CSDN,登一次可能几个月都不需要再次登录了,每次打开自己的账号就还在那里。
Ⅲ 如何使用cookie
上面说到了网站会记录你的登录信息,那我们就简单实现一下网站是如何记录你的上一次访问时间的。
A. 得到用户上一次访问时间
首先我们先建一个servlet,我们通过doGet()
来实现这个功能。
package com.tyz.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;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;
/**
* 服务器记录用户访问网站的时间,并将这个时间信息作为一个cookie发给客户端,
* 只要用户不是第一次访问,访问时就会带着一个cookie,服务器通过用户带来的
* 这个cookie,就可以取得它上次访问网站的时间。
*
* @author tyz
*/
public class RecordLastVisiting extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//建立一个写数据的writer
PrintWriter out = resp.getWriter();
//服务器从客户端获取cookie (可能有多个)
Cookie[] cookies = req.getCookies();
//判断cookie是否存在
if (cookies == null) {
//用户没有cookie,说明是第一次访问
out.write("This is your first visiting.");
} else {
out.write("The last time you visited is: ");
//Cookie本质是一个键值对(name, value),所以我们可以根据
//name属性来获取对应的cookie的value
for (Cookie cookie : cookies) {
if ("lastAccessTime".equals(cookie.getName())) {
//获取cookie的值
long lastAccessTime = Long.parseLong(cookie.getValue());
//将cookie值转化为日期
Calendar calendar = Calendar.getInstance();
Date date = new Date(lastAccessTime);
calendar.setTime(date);
out.write(calendar.getTime() + "");
}
}
}
//生成一个cookie
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis() + "");
//服务器将生成的cookie响应给客户端。如果客户端是第一次访问则
//第一次得到cookie,不是第一次访问则会更新客户端保留的cookie.
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注释我已经把每一步都写得很详细了,部署完成之后我们直接来看运行结果。
它输出的居然是上一次访问的时间,但是时间是空的,这是怎么回事?我们来看一下控制台。点击 Application,查看左边的cookie。
这个红框圈起来的就是我们定义的cookie,可以看到,除了这个cookie以外,服务器还发送了其他cookie,这就导致我们一开始判断的 cookies == null
是没有起到我们想要的作用的。
这时候我们再进行一次刷新
可以看到已经得到上次的访问时间了。
来,我们再把这条cookie记录删除再刷新试一下。
可以看到又识别出来了我们是第一次。
现在我们点进响应操作看一下:
在response的header里可以清楚地看到我们设置了cookie的键值对,lastAcessTime=...
。那在request里呢?我们再来看看。
可以看到,客户端发来的请求中,除了我们设置的cookie以外,还有几组,这些都是打开浏览器就会出现的默认的cookie,这里我用的Chrom浏览器,如果你用的其他的浏览器可能还会看到一个记录请求次数的cookie。
这时我们可以把浏览器关掉,再打开一次,cookie自己就不在了。我们进去的时候还显示的是第一次访问。
这个cookie的存在时间也是可以设置的,比如我们想让cookie存在一天。直接设置就好了,注意这里的单位是按秒算的,所以要设置成一天需要计算一下。
现在我们再来访问一下试试。
cookie的有效期是被重新设置了的。
B. Cookie总结
根据上面的代码我们可以看出来cookie的使用。
1. 从请求中拿到cookie信息;
2. 服务器响应给客户端cookie。
Cookie主要的几个操作我整理在下面:
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie的键
cookie.getValue(); //获得cookie的值
//新建一个cookie
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24 * 60 * 60); //设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie
//服务器中的输出如果有中文乱码,可以在程序的开头就调用下面两行代码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//如果要在Cookie中存入中文的键或值,若上面两行代码仍没有起作用,
//可以使用下面的方法进行cookie的生成已经value的取得
Cookie cookie1 = new Cookie("name", URLEncoder.encode("李明", "utf-8"));
out.write(URLDecoder.decode(cookie.getValue(), "utf-8"));
Cookie一般会保存在本地的用户目录下的AppData里,大家有兴趣可以去找一下。原来如果用过360的清理的话,大家可能也会有印象,清理垃圾时有一个清理cookie的选项,这实际上就是在清除我们访问的网站中保存下来的信息。