目录
一.介绍
Cookie
对象与
HttpSession
对象的作用是维护客户端浏览器与服务端的会话状态的两个对象。由于
HTTP
协议是一个无状态的协议,所
以服务端并不会记录当前客户端浏览器的访问状态,但是在有些时
候我们是需要服务端能够记录客户端浏览器的访问状态的,如获取
当前客户端浏览器的访问服务端的次数时就需要会话状态的维持。
在
Servlet
中提供了
Cookie
对象与
HttpSession
对象用于维护客户端
与服务端的会话状态的维持。二者不同的是
Cookie
是通过客户端浏
览器实现会话的维持,而
HttpSession
是通过服务端来实现会话状态
的维持。
二.Cookie对象的特点
- Cookie使用字符串存储数据
- Cookie使用Key与Value结构存储数据
- 单个Cookie存储数据大小限制在4097个字节
- Cookie存储的数据中Servlet4.0之前不支持中文,Servlet4.0中支持
- Cookie是与域名绑定所以不支持跨一级域名访问
- Cookie对象保存在客户端浏览器内存或系统磁盘中
- Cookie分为持久化Cooke(放在系统磁盘中)与状态Cookie (放在客户端浏览器内存)
- 浏览器在保存同一域名所返回Cookie的数量是有限的。不同浏览器支持的数量不同,Chrome浏览器为50个
- 浏览器每次请求时都会把与当前访问的域名相关的所有Cookie在请求中提交到服务端。
三.Cookie对象的创建
注意Cookie是服务器端创建并返回给用户的。
Cookie cookie = new Cookie("key","value")
通过
new
关键字创建
Cookie
对象
response.addCookie(cookie)
通过
HttpServletResponse
对象将
Cookie
写回给客户端浏览器。
CreateCookieServlet.java:
package com.first.servlet;
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;
public class CreateCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建Cookie对象
Cookie cookie=new Cookie("key","流连忘返");
//将Cookie写回给客户端浏览器
resp.addCookie(cookie);
PrintWriter pw=resp.getWriter();
pw.println("create cookie ok");
pw.flush();
pw.close();
}
}
配置web.xml:
<servlet>
<servlet-name>CreateCookieServlet</servlet-name>
<servlet-class>com.first.servlet.CreateCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CreateCookieServlet</servlet-name>
<url-pattern>/cookie.do</url-pattern>
</servlet-mapping>
输出:
先按F12,再访问此servlet
点击Application-->Cookie
四.获取Cookie中的数据
浏览器每次请求时都会把与当前访问的域名相关的
Cookie
在请求中提交到服务端。通过
HttpServletRequest
对象获取
Cookie
,返回
Cookie
数组。
Cookie[] cookies = request.getCookies();
上节运行的浏览器不要关(服务器也别关,因为实际生活中服务器就是一直运行),因为我们现在使用的是状态cookie(会保存到当前浏览器中),浏览器一关cookie就被清空了。
GetCookieDataServlet.java:
package com.first.servlet;
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;
public class GetCookieDataServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//从客户端获取Cookie对象
Cookie[] cookies=req.getCookies();
//获取Cookie中的数据
PrintWriter pw=resp.getWriter();
for (int i=0;i<cookies.length;i++){
Cookie cookie=cookies[i];
String name=cookie.getName();
String value=cookie.getValue();
pw.println("Name: "+name+" Value: "+value);
}
pw.flush();
pw.close();
}
}
配置web.xml:
<servlet>
<servlet-name>GetCookieDataServlet</servlet-name>
<servlet-class>com.first.servlet.GetCookieDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetCookieDataServlet</servlet-name>
<url-pattern>/getCookie.do</url-pattern>
</servlet-mapping>
输出:
五.解决Cookie不支持中文
在
Cookie
中
name
的值不能使用中文,
Value
是可以的。但是在Servlet4.0
版本之前
Cookie
中的
Value
也是不支持中文存储的,如果
存储的数据中含有中文,代码会直接出现异常。我们可以通过对含
有中文的数据重新进行编码来解决该问题。在
Servlet4.0
中的
Cookie
的
Value
开始支持中文存储。
报的异常:
java.lang.IllegalArgumentException: Control character in cookie value or attribute.
还是建议做如下处理,因为这样普适性较高,不用担心版本问题。
URLEncoder.encode("content","code")
将内容按照指定的编码方式做
URL
编码处理。
URLDecoder.decode("content","code")
将内容按照指定的编码方式做
URL
解码处理。
上面的两个例子稍加修改:
CreateCookieServlet.java:
//创建Cookie对象
Cookie cookie=new Cookie(URLEncoder.encode("回头看","utf-8"),
URLEncoder.encode("流连忘返","utf-8"));
GetCookieDataServlet.java:
pw.println("Name: "+ URLDecoder.decode(name,"utf-8")
+" Value: "+URLDecoder.decode(value,"utf-8"));
输出:
六.Cookie跨域问题
域名分类:域名分为顶级域、顶级域名(一级域名)、二级域名。
域名等级的区别:一级域名比二级域名更高级,二级域名是依附于一级域名之下的附属分区域名,即二级域名是一级域名的细化分
级。例如:
baidu.com
为一级域名,
news.baidu.com
为二级域
名。
Cookie不支持一级域名的跨域,支持二级域名的跨域。一级域名(即顶级域名)需要申请,二级域名不需要申请,二级域名自己扩展即可。
七.状态Cookie与持久化Cookie
状态
Cookie
:
Cookie
对象仅会被缓存在浏览器所在的内存中。当浏览器关闭后
Cookie
对象
也会被销毁。
持久化
Cookie
:浏览器会对
Cookie
做持久化处理,基于文件形式保存在系统的指定目录中。在
Windows10
系统中为了安全问题不会显
示
Cookie
中的内容。
当
Cookie
对象创建后默认为状态
Cookie
。可以使用
Cookie
对象下的cookie.setMaxAge(60)
方法设置失效时间,单位为秒。一旦设置了
失效时间,那么该
Cookie
为持久化
Cookie
,浏览器会将
Cookie
对象
持久化到磁盘中。当失效时间到达后文件删除。
//创建Cookie对象
Cookie cookie=new Cookie(URLEncoder.encode("回头看","utf-8"),
URLEncoder.encode("流连忘返","utf-8"));
//变为持久化cookie,生存时间是120s,在生存时间内关闭浏览器没问题
cookie.setMaxAge(120);
八.通过Cookie实现客户端与服务端会话的维持
需求:当客户端浏览器第一次访问
Servlet
时响应
“
您好,欢迎您第一次访问!
”
,第二次访问时响应
“
欢迎您回来!
”
。
WelcomeServlet.java:
package com.first.servlet;
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;
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Cookie
Cookie[] cookies=req.getCookies();
//有无标志访问的Cookie
boolean flag=false;
if (cookies!=null){
for (Cookie cookie:cookies){
if ("welcome".equals(cookie.getName())){
//不是第一次访问
flag=true;
break;
}
}
}
resp.setContentType("text/plain;charset=utf-8");
PrintWriter pw=resp.getWriter();
if (flag){
pw.println("欢迎您回来!");
}else {
pw.println("您好,欢迎您第一次访问!");
Cookie cookie=new Cookie("welcome","welcome");
cookie.setMaxAge(60);
//把这个cookie响应给用户
resp.addCookie(cookie);
}
}
}
web.xml配置:
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<servlet-class>com.first.servlet.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/welcome.do</url-pattern>
</servlet-mapping>
输出:
刷新一下
Cookie
总结
Cookie
对于存储内容是基于明文的方式存储的,所以安全性很低。 win10做了改进,不再让用户直接看到明文。
不要在
Cookie
中存放敏感数据。在数据存储时,虽然在
Servlet4.0
中
Cookie
支持中文,但是建议对
Cookie
中存放的内容做编码处理,
也可提高安全性。