目录
一、会话
- 会话:一次会话中包含多次请求和响应
- 什么是一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开位置。
- 会话功能:在一次会话的范围内的多次请求间,共享数据。
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
二、Cookie
2.1 API
1. 创建Cookie对象,绑定数据
Cookie(String name, String value);
2. 服务器端通过HttpServletResponse,发送Cookie到客户端
void addCookie(Cookie cookie);
3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
Cookie[] getCookies();
2.2 发送和接收Cookie,演示代码
创建Demo1_Cookie发送Cookie,Demo2_Cookie2获取Cookie
Demo1_Cookie:
@WebServlet("/cookie1")
public class Demo1_Cookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
1. 创建Cookie对象,绑定数据
* Cookie(String name, String value);
2. 服务器端通过HttpServletResponse,发送Cookie到客户端
* void addCookie(Cookie cookie);
3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
* Cookie[] getCookies();
* */
// 1. 创建Cookie对象,绑定数据
Cookie cookie = new Cookie("msg", "Cookie的值");
// 2. 发送Cookie到客户端
response.addCookie(cookie);
// 3. 创建Demo2_Cookie 获取Cookie
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Demo2_Cookie2:
@WebServlet("/cookie2")
public class Demo2_Cookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
3. 服务器端通过HttpServletRequest,获取Cookie,拿到数据(客户端再次访问服务器端资源时,会携带客户端保存的Cookie到服务器端。服务器端可以获取该Cookie)
* */
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println("name=" + name + ",value=" + value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
打开浏览器,先访问 cookie1,如下图,我们可以看到,响应头会携带cookie发送到客户端: set-cookie : key=value
然后在浏览器中,访问 cookie2,如下图,我们可以看到,客户端会在请求头中携带cookie到服务器端:cookie : key=value
2.3 Cookie实现原理
2.4 一次发送多个cookie
// 1. 创建Cookie对象,绑定数据
Cookie cookie1 = new Cookie("key1", "value1");
Cookie cookie2 = new Cookie("key2", "value2");
Cookie cookie3 = new Cookie("key3", "value3");
// 2. 发送Cookie到客户端
response.addCookie(cookie1);
response.addCookie(cookie2);
response.addCookie(cookie3);
2.5 在浏览器中存储时间
- 默认情况下,cookie保存在内存中,当浏览器关闭后,Cookie数据被销毁。
- 自定义存储方式
参数:expiry 秒
1. 正数:将cookie数据写到硬盘的文件中,即持久化存储。cookie存货时间。例如,expiry=30,那么30秒后,硬盘中的cookie会被删除。
2. 负数:默认值-1。cookie存储在浏览器的内存中,浏览器关闭后,cookie就会消失。
3. 0:删除cookie信息
public void setMaxAge(int expiry);
2.6 能否存中文和特殊符号
- tomcat8 之前,cookie不能存储中文数据:需要将中文数据转码。一般采用URL编码。
- tomcat8 之后,cookie支持存储中文。但是,对于特殊字符还是不支持(例如,空格),建议使用URL编码存储,使用URL解码解析。
URL编码:需要使用java.net
包下的URLEncoder
对value值进行编码,然后存储。
URL解码:使用URLDecoder
对获取的value值进行解码。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 有中文、空格这两种特殊符号
String value = "阳光 明媚";
System.out.println("编码前:" + value);
/*------------URL编码--------------*/
value = URLEncoder.encode(value, "utf-8");
System.out.println("编码后:" + value);
// 生成、发送cookie
Cookie cookie = new Cookie("key", value);
cookie.setMaxAge(3000);
response.addCookie(cookie);
/*------------URL解码--------------*/
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
String name = c.getName();
if ("key".equals(name)) {
String cValue = c.getValue();
System.out.println("解码前:" + cValue);
// URL解码
cValue = URLDecoder.decode(cValue, "utf-8");
System.out.println("解码后:" + cValue);
}
}
}
}
2.7 共享问题
- 同一个tomcat服务器中,部署了多个web项目,多个web项目之间cookie的共享问题:
① 默认情况下cookie是不能共享的;
② 设置cookie的获取范围,使用Cookie对象的setPath方法:
* 默认情况下,path是当前web项目的虚拟目录。
* 指定 path="/",则同一个tomcat服务器中的所有web项目可以共享cookie
public void setPath(String uri)
- 不同的tomcat服务器之间,cookie共享问题
public void setDomain(String pattern);
使用 setDomain 方法,如果多个服务器一级域名相同,那么 Cookie 可以共享。
例如:setDomain(".baidu.com"); 那么 tieba.baidu.com 服务器和 news.baidu.com 服务器之间可以共享Cookie。
2.8 特点
- Cookie存储数据在客户端浏览器。不安全,容易被篡改。
- 浏览器对于单个cookie的大小有限制(一般4kb),以及对同一个域名下的总cookie数量也有限制(20个以内)。
2.9 作用
- 存储少量的不太敏感的数据;
- 在不登录的情况下,来完成服务器对客户端的身份识别
2.10 案例:记录浏览器上一次访问时间,再次访问时显示
实现如下代码,然后在浏览器中访问该资源:
@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. 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
2. 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
* */
// 1. 获取所有cookie
Cookie[] cookies = request.getCookies();
boolean flag = false; // 未找到key=lasttime的cookie
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
// 获取cookie名称
String name = c.getName();
// 判断name是否是lasttime
if ("lasttime".equals(name)) {
// 不是第一次访问
flag = true;
// 设置cookie的value
// 获取当前时间的字符串,修改cookie的值,重新发送cookie
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String formatDate = sdf.format(date);
System.out.println("编码前:" + formatDate);
// URL编码
formatDate = URLEncoder.encode(formatDate, "utf-8");
System.out.println("编码后:" + formatDate);
c.setValue(formatDate);
// 设置cookie存活时间为一个月
c.setMaxAge(30 * 24 * 3600);
response.addCookie(c);
// 响应数据,写出到页面
// 获取value
String value = c.getValue();
System.out.println("解码前:" + value);
// URL解码
value = URLDecoder.decode(value, "utf-8");
System.out.println("解码后:" + value);
response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + value + "</h1>");
break;
}
}
}
if (cookies == null || cookies.length == 0 || flag == false) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String formatDate = sdf.format(date);
System.out.println("编码前:" + formatDate);
// URL编码
formatDate = URLEncoder.encode(formatDate, "utf-8");
System.out.println("编码后:" + formatDate);
Cookie cookie = new Cookie("lasttime", formatDate);
// 设置cookie存活时间为一个月
cookie.setMaxAge(30 * 24 * 3600);
response.addCookie(cookie);
// 响应数据,写出到页面
response.getWriter().write("<h1>您好,欢迎您首次访问。</h1>");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}