一次会话的范围内的多次请求数据
之间来共享数据Cookie
,就是把共享数据保存在客户端Session
,就是把共享数据保存在服务器new Cookie(String name, String Value)
response.addCookie(Cookie cookie)
Cookie[] request.getCookies()
@WebServlet("/cookieDemo1")
public class CookieDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建Cookie对象
Cookie c = new Cookie("msg", "hello");
//2.发送Cookie
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/cookieDemo2")
public class CookieDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//3.获取Cookie
// 因为可能获取多个嘛 所以有数组
Cookie[] cs = request.getCookies();
//遍历
if (cs != null){
for (Cookie cookie : cs) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name + ":" + value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
/cookieDemo1
时,response
会自动的在响应头
里设置Cookie
的相关信息,可以通过抓包观察到/cookieDemo2
的时候,会在请求头里添加刚才的收到的Cookie
数据,也可以很容易的在抓包工具里观察到:基于响应头set-cookie
和请求头cookie
实现//1.创建Cookie对象
Cookie c1 = new Cookie("msg", "hello");
Cookie c2 = new Cookie("name", "zqx");
//2.发送Cookie
response.addCookie(c1);
response.addCookie(c2);
setMaxAge(int seconds)
//1.创建Cookie对象
Cookie c1 = new Cookie("msg", "hello");
//2.设置cookie的存活时间
//2.1持久化到硬盘 30s后失效
// c1.setMaxAge(30);
//2.2 设置-1 就是默认请教
// c1.setMaxAge(-1);
//2.3设置0 删除cookie信息
c1.setMaxAge(0);
//2.发送Cookie
response.addCookie(c1);
%E3
)空格
)还是不支持,建议使用URL编码存储,URL解码解析1.在同一个tomcat
服务器下,部署了多个web项目,这些项目之间的cookie可以共享吗?
setPath(String path)
: 设置cookie的获取范围。默认情况下,设为为当前的虚拟目录,那么就只能在当前的项目内进行共享,如果要在不同的项目间共享,则设置为:setPath("/")
2不同的服务器之间的web项目的cookie可以共享吗?
setDomain(String path)
:如果设置一级域名相同,那么多个服务器之间cookie可以共享
setDomain(".baidu.com")
,那么tieba.baidu.com
和news.baidu.com
中cookie可以共享lastTime
的cookie
整体逻辑简单,两个注意实现
package com.zqx.cookie;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 20190816
* 利用cookie实现访问时间的显示与存储
*/
@WebServlet("/cookieTest")
public class CookieTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0.设置响应消息体的数据格式以及编码
response.setContentType("text/html;charset=utf-8");
boolean flag = false; //默认没有访问过
//1.获取所有cookie
Cookie[] cookies = request.getCookies();
//2.遍历
for (Cookie cookie : cookies) {
//3.获取每一个cookie的name
String name = cookie.getName();
//4.判断name是否为指定的cookie名字 lastTime
if ("lastTime".equals(name)){
//有 说明不是第一次访问
flag = true;
//先获取当前的值
String value = cookie.getValue();
//设置cookie的value 会自动覆盖
//获取当前时间的字符串 设置cookie 然后发生
Date date = new Date();
//时间格式化输出
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String date_value = sdf.format(date);
//为了解决 时间字符串的空格 无法被cookie直接识别的问题 进行URL编码和解码
System.out.println("编码前:" + date_value);
//URL编码
date_value = URLEncoder.encode(date_value, "utf-8");
System.out.println("编码后:" + date_value);
//设置cookie值
cookie.setValue(date_value);
//设置存活时间 一个月
cookie.setMaxAge(60 * 60 * 24 * 30);
// 发生cookie
response.addCookie(cookie);
//响应 检测到有cookie 应取出当前的值(上一次访问时间)
//同样这里也是经过URL编码的 所以先解码
System.out.println("解码前:" + value);
value = URLDecoder.decode(value, "utf-8");
System.out.println("解码后:" + value);
//回写到界面
response.getWriter().write("欢迎回来,您上次访问时间为:"
+value+"");
//只要访问到想要的cookie后面则不再循环
break;
}
}
if (cookies == null || cookies.length == 0 || !flag ){
//没有名为 lastTime的cookie 则第一次访问
Date date = new Date();
//时间格式化输出
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String date_value = sdf.format(date);
//为了解决 时间字符串的空格 无法被cookie直接识别的问题 进行URL编码和解码
System.out.println("编码前:" + date_value);
//URL编码
date_value = URLEncoder.encode(date_value, "utf-8");
System.out.println("编码后:" + date_value);
Cookie cookie = new Cookie("lastTime", date_value);
cookie.setMaxAge(60 * 60 * 24 * 30);
// 发生cookie
response.addCookie(cookie);
response.getWriter().write("您好,欢迎您首次访问
");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
保存在服务端的一次会话的共享数据
HttpSession
对象:HttpSession session = request.getSession();
HttpSession
对象:
Object getAttribute(String name) ;
void setAttribute(String name, Object value);
void removeAttribute(String name)
@WebServlet("/sessionDemo1")
public class SessionDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取Session对象
HttpSession session = request.getSession();
//2.设置数据
session.setAttribute("msg", "hello session");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/sessionDemo2")
public class SessionDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取Session对象
HttpSession session = request.getSession();
//2.获取数据
Object msg = session.getAttribute("msg");
System.out.println(msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Session的实现是依赖Cookie的
浏览器在第一次访问sessionDemo1
的时候,服务器内存里没有Session
对象,则会创建一个Session
对象,并为其分配一个唯一的ID
浏览器第二次访问sessionDemo2
的时候,获取到Session
对象,关键问题在于?如何确保第二次获取到的session
和上一次是通一个Session对象呢?
Session
的ID
信息:set-cookie=JSESSIONID=2323819319
set-cookie=JSESSIONID=2323819319
的信息session
的ID
保存在cookie
中完成的 //1.获取Session对象
HttpSession session = request.getSession();
//2. 使用Cookie持久化session 让关闭浏览器后 获取到的Session为同一个
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60 * 60);
response.addCookie(cookie);
//2.打印session的内存地址
System.out.println(session);
}
不是同一个,因为服务器关闭后,web项目的内存空间肯定也关闭了,Session信息肯定丢失了。
但是这个Session的数据又很重要,需要想办法确保服务器关闭后也能保存下来。
例如,用户在淘宝刚刚加入了很多商品在购物车,这个购物车的信息就是保存在session中的,如果服务器关闭了,且session数据没有被保存,那么购物车的信息也就被丢失了。
所以,为了解决上述问题,tomcat服务器会自动的完成以下工作:
这种方法仅仅在手动部署项目到tomcat服务器才生效,使用IDEA联合配置是不生效的
正常关闭tomcat(/bin/shutdown.bat
),观察work目录下的项目目录
-可以发现生成了一个Session文件,接下来,再次手动启动tomcat,观察现象
发现.ser文件消失,这是因为被自动加载到内存中去了
这个例子很清楚了说明了tomcat自动保存和加载session的过程
那么为什么IDEA不行呢?
先说结论,在IDEA中正常关闭服务器后,仍然会自动保存
但是重启服务器后,IDEA会自动删除work目录,再新建,自然session.ser也被删除了
<session-config>
<session-timeout>30session-timeout>
session-config>