目录
一、现有问题
二、简介
三、Cookie原理
四、Cookie应用
4.1 创建并向客户端发送Cookie
4.2 从客户端读取Cookie
4.3 Cookie的生命周期
4.4 Cookie的编码和解码
4.5 优缺点
五、记录上次登录的时间(案例)
六、Cookie 获取范围有多大?
一、现有问题
HTTP协议是无状态的,不能保存每次提交的信息,如果用户发来一个新请求,服务器无法知道它是否与上次的请求有联系。那么服务器将如何建立、维护与客户端的会话呢?
因此对于需要客户端和服务器端多次交互的网络应用,则必须记住客户端状态,如:网上的购物车,用户登录。
二、简介
客户端状态管理技术:将状态保存在客户端,代表性的是:Cookie技术。
Cookie,其实就是储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息,类型为“小型文本文件”。
- Cookie是在浏览器访问Web服务器的某个资源时, 由Web服务器在HTTP响应消息头中附带传送给浏览器的一小段数据。
- 一旦Web浏览器保存了某个Cookie, 那么它在以后每次访问该Web服务器时, 都应在HTTP请求头中将这个Cookie回传给Web服务器。
- Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。
三、Cookie原理
浏览器首次向服务器发送请求时,服务器需要创建cookie,服务器会通过响应携带cookie(在产生响应时会产生Set-Cookie响应头,从而将cookie信息传递给了浏览器)
当浏览器再次向服务器发送请求时,会产生cookie请求头,将之前服务器的cookie信息再次发送给了服务器,然后服务器根据cookie信息跟踪客户端状态。
注意:
- 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称name和设置值value。
- 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个大小限制为4kb。
四、Cookie应用
4.1 创建并向客户端发送Cookie
调用Cookie的构造方法,给出Cookie的名称和Cookie的值,二者都是字符串
Cookie c = new Cookie("userName" , "a1234")
将Cookie放入到HTTP响应中(如没有这一步,将不会有任何Cookie被发送到浏览器)
response.addCookie(c)
4.2 从客户端读取Cookie
调用request.getCookies,得到Cookie对象组成的数组。循环数组,调用每个对象的getName找到想要的cookie。
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("username".equals(cookie.getName())) {
System.out.println(cookie.getValue());
}
}
}
getName():读取Cookie的名称。不存在setName()方法。
getValue()/setValue():读取/设置与Cookie关联的值,如果重新设置了某Cookie的值,需要用addCookie()方法将其发送回去。
4.3 Cookie的生命周期
- 默认情况下,Cookie存储在浏览器内存中,当浏览器关闭时内存释放,Cookie销毁
- 设置Cookie存活时间:setMaxAge(int seconds)
- 零:删除对应 Cookie
- 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,Cookie立即销毁
- 正数:将Cookie 写入浏览器所在电脑硬盘的文件中,持久化存储。超时自动删除。
设置一周(7天的有效时间)
cookie.setMaxAge(60*60*24*7);
4.4 Cookie的编码和解码
Cookie默认不支持中文,只能包含ASCII字符,所以Cookie需要对Unicode字符进行编码, 否则会出现乱码。
- 编码可以使用 java.net .URLEncoder类的encode(Stringstringencoding)方法
- 解码使用 java.net .URLDecoder类的decode(Stringstr,Stringencoding)方法
// 编码
Cookie cookie = new Cookie(
URLEncoder.encode("键名", "utf-8"),
URLEncoder.encode("键值", "utf-8")
);
response.addCookie(cookie);
// 解码
String keyStr = URLDecoder.decode(cookie.getName(), "utf-8");
4.5 优缺点
优点:
● 可配置到期规则
● 简单性:基于文本的轻量结构,简单键值对
● 数据持久性:虽然Cookie可被客户端浏览器的过期处理和干预,但Cookie通常也是客户端上持续时间最长的数据保留形式。
缺点:
● 大小受到限制:大多数浏览器的Cookie只有4kb大小的限制
● 用户配置禁用:有些用户禁用了浏览器或客服端接收Cookie的能力,限制了该功能
● 潜在安全风险:用户可能会操纵篡改浏览器上的Cookie,会造成Cookie应用程序执行失败的问题
五、记录上次登录的时间(案例)
- 需求:
- 访问 LoginServlet ,如果是第一次访问,提示:您好,欢迎首次访问
- 如果不是第一次访问,则提示:欢迎回来,您上次访问的时间为:上次访问时间
@WebServlet(name = "work",value = "/work")
public class HelloServlet extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//告诉服务器以哪种方式解析乱码(中文)
request.setCharacterEncoding("UTF-8");
//设置客服端和服务端编码一致且支持中文
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
Cookie[] cookies = request.getCookies();
boolean isFirstVisit = true;
String lastVisitTime = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
if ("lastVisitTime".equals(name)) {
isFirstVisit = false;
String value = cookie.getValue();
lastVisitTime = URLDecoder.decode(value, "UTF-8");
break;
}
}
}
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String format = simpleDateFormat.format(date);
String encode_format = URLEncoder.encode(format, "UTF-8");
Cookie lastvisitCookie = new Cookie("lastVisitTime", encode_format);//同名会被覆盖
lastvisitCookie.setMaxAge(60*60*24);
response.addCookie(lastvisitCookie);
if (isFirstVisit) {
writer.println("您好,欢迎首次访问");
} else {
writer.println("欢迎回来,您上次访问的时间为:" + lastVisitTime);
}
writer.close();
}
}
六、Cookie 获取范围有多大?
假设在同一 tomcat 服务器中,部署多个web项目(比如本机tomcat/webapp下面有两个应用:webapp_a和webapp_b),那么多个项目中 Cookie 能不能共享数据?
● 默认 Cookie 不能共享数据(正常的cookie只能在一个应用中共享,即一个cookie只能由创建它的应用获得。)
● 但可以用 setPath(String path) 设置Cookie路径来实现共享
- 若在webapp_a下面设置cookie的时候,增加一条cookie.setPath("/");或者cookie.setPath("/webapp_b/"); 就可以在webapp_b下面获取到webapp_a设置的cookie了。
- 最简单还是设置 cookie.setPath("/")(解释:此处的参数,是相对于应用服务器存放应用的文件夹的根目录而言的(比如tomcat下面的webapp),因此cookie.setPath("/");之后,可以在webapp文件夹下的所有应用共享cookie)
不同 tomcat 服务器间,如何共享 Cookie 数据?
- 使用 setDomain(String path) 设置一级域名相同,即可共享
- 使用实例:setDomain(".baiud.com")
以上内容了解即可,如果感兴趣可以多搜搜其他博客看看~