(1)会话
- 会话:一次会话中包含多次请求和响应
- 一次会话,浏览器第一次给服务器发送请求,会话建立,直到有一方断开为止
- 在一次会话的范围内多次请求间,共享数据
- 种类
- 客户端会话技术:Cookie
- 服务端会话技术:Session
(2)Cookie
Cookie例子
将数据保存在浏览器
response.addCookie(cookie); Cookie[] cookies = request.getCookies();
浏览器A先访问cookie1(添加cookie),再去访问cookie2,发现打印了cookie1 name中储存的值
再换成浏览器B访问cookie2,发现没有打印name的值,因为不是一次会话了 ``` @WebServlet(“/cookie1”) public class Cookie1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("nname", "tom");
response.addCookie(cookie);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
} }
@WebServlet(“/cookie2”) public class Cookie2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if (cookies != null){
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
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);
}
}
<a name="99K3b"></a>
#### Cookie原理
- 浏览器请求cookie1
- 服务器addCookie将cookie保存在响应头中,键Set-Cookie 值nname=tom
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600308318453-7912f3c8-23c3-41b1-a19f-eedcc4d14caf.png#align=left&display=inline&height=241&margin=%5Bobject%20Object%5D&name=image.png&originHeight=482&originWidth=1248&size=93772&status=done&style=none&width=624)
- 浏览器收到这个cookie会缓存在本地,下次请求的时候,放在请求头中键Cookie 值nname=tom
- 浏览器请求cookie2
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600308432888-0a289c6f-4bc3-4578-a241-c7388fb3e6ea.png#align=left&display=inline&height=339&margin=%5Bobject%20Object%5D&name=image.png&originHeight=678&originWidth=1388&size=159039&status=done&style=none&width=694)
- 总体流程
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600308190665-a485cb48-3cc6-497d-9c13-1277870366db.png#align=left&display=inline&height=211&margin=%5Bobject%20Object%5D&name=image.png&originHeight=422&originWidth=1224&size=134527&status=done&style=none&width=612)
<a name="TkEzi"></a>
#### 一次性发送多个Cookie
@WebServlet(“/cookie1”) public class Cookie1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie1 = new Cookie("name", "tom");
Cookie cookie2 = new Cookie("age", "20");
response.addCookie(cookie1);
response.addCookie(cookie2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
- 添加Cookie
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600308920163-fd1f5f23-098c-479e-8cac-06cabd489d46.png#align=left&display=inline&height=259&margin=%5Bobject%20Object%5D&name=image.png&originHeight=518&originWidth=852&size=80943&status=done&style=none&width=426)
- 获取cookie
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600308983801-9162917d-ac1d-485a-a95d-bffd7f239cd5.png#align=left&display=inline&height=259&margin=%5Bobject%20Object%5D&name=image.png&originHeight=518&originWidth=1006&size=97830&status=done&style=none&width=503)
<a name="e6V7w"></a>
#### Cookie保存时间
- 默认cookie储存在浏览器内存中,浏览器关闭时,cookie失效
- 设置持久化储存setMaxAge
- 正数 将cookie数据写到硬盘的文件中,n秒后自动删除
- 负数 保存在内存中,浏览器关闭就消失了
- 0 删除cookie
@WebServlet(“/cookie1”) public class Cookie1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie1 = new Cookie("name", "tom");
// 正数 将cookie数据写到硬盘的文件中,n秒后自动删除
// 负数 保存在内存中,浏览器关闭就消失了
// 0 删除cookie
cookie1.setMaxAge(10);
response.addCookie(cookie1);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
<a name="SMl36"></a>
#### Cookie储存中文
- tomcat8之前不能储存中文,8之前的可以使用URL编码
- 不能储存空格
- URLEncoder.encode(value, "utf-8");
String value = "2010 20 20";
value = URLEncoder.encode(value, "utf-8");
Cookie cookie = new Cookie("name", value);
cookie.setMaxAge(0);
response.addCookie(cookie);
- URLDecoder.decode(value);
Cookie[] cookies = request.getCookies();
if (cookies != null){
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name+": "+value);
value = URLDecoder.decode(value);
System.out.println(name+": "+value);
}
}
<a name="coU4a"></a>
#### Cookie共享
- 第一种 同一个Tomcat服务器
- 同一个tomcat服务器,部署多个web项目,默认这些项目之间不能共享cookie
- 可以通过setPath()让同tomcat下的其他web项目可以共享cookie,默认是自身的虚拟目录
> setPath("/web1");
> Cookie.setPath("/");// 让所有的都可以共享
Cookie cookie1 = new Cookie("name", "tom");
cookie1.setPath("/");
response.addCookie(cookie1);
- 第二种 不同tomcat服务器
- Cookie.setDomain(string),如果一级域名先难沟通,那么多个服务器之间cookie可以共享
> 例如
> 百度新闻[http://news.baidu.com/](http://news.baidu.com/)
> 百度贴吧[https://tieba.baidu.com/index.html](https://tieba.baidu.com/index.html)
> setDomain(".baidu.com")后,百度新闻和百度贴吧就可以cookie共享
<a name="t0U5k"></a>
#### Cookie特点和作用
- Cookie储存在客户端浏览器
- 浏览器对单个cookie的大小有限制4kb
- 对同一个域名下的cookie数量也有限制20个
- 储存少量不敏感数据
- 在不登录的情况储存一些用户设置
<a name="dp3b4"></a>
### (3)Session
- 服务端会话技术:在一次会话的多次请求间共享数据,将数据保存在服务端的对象中HttpSession
- 没有大小限制,数据存储在服务器端
<a name="QZaIO"></a>
#### 基本使用
- 常用方法
- request.getSession();
- session.setAttribute("name","tom");
- session.getAttribute("name");
- 在没有关闭服务器的前提下,下例中两个session的地址一致
@WebServlet(“/Session1”) public class Session1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); System.out.println(session); session.setAttribute(“name”,”tom”); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet(“/Session2”) public class Session2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
System.out.println(session);
String name = (String) session.getAttribute("name");
System.out.println(name);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
<a name="x2Se9"></a>
#### 原理
- Session是通过cookie实现的
![image-2.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600391210736-17da3c98-520b-4254-b07c-ff7229536c0e.png#align=left&display=inline&height=235&margin=%5Bobject%20Object%5D&name=image-2.png&originHeight=470&originWidth=1052&size=118688&status=done&style=none&width=526)
- 第一次请求session1,响应头中有set-cookie,请求头没有
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600331511690-e406f7b7-20b6-4b00-b2a0-c49a89bc451a.png#align=left&display=inline&height=319&margin=%5Bobject%20Object%5D&name=image.png&originHeight=638&originWidth=2156&size=140685&status=done&style=none&width=1078)
- 第二次请求session2,请求头中有cookie,服务器会找出JSESSIONID对应的HttpSession对象,保证了一次会话中的Session一直
![image.png](https://cdn.nlark.com/yuque/0/2020/png/503653/1600391149918-49c6aa79-6611-4628-82b6-4e5709e2d76b.png#align=left&display=inline&height=301&margin=%5Bobject%20Object%5D&name=image.png&originHeight=602&originWidth=1786&size=124875&status=done&style=none&width=893)
<a name="S5wqt"></a>
#### Session相关特点
- 客户端关闭,服务端不关闭,两次获取的session不一致
- 解决方法如下,设置Cookie 键JSESSIONID,设置最大存活时间
@WebServlet(“/Session2”) public class Session2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// HttpSession session = request.getSession(); // System.out.println(session); // String name = (String) session.getAttribute(“name”); // System.out.println(name);
HttpSession session = request.getSession();
Cookie c = new Cookie("JSESSIONID", session.getId());
c.setMaxAge(60*60);
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
} ```
- 客户端不关闭,服务端关闭,两次获取的session不一致
解决方法,Tomcat服务自动已经有钝化、活化,(IDEA没有这个功能,他会直接删除work目录)
- session钝化,在服务器正常关闭前,将session序列化到硬盘
- session活化,服务器启动后,将session文件转换成内存中的对象
序列化文件保存在,正常关闭服务时出现,启动服务器后消失
/Users/wangchun/Library/apache-tomcat-8.5.57/work/Catalina/localhost/test/SESSIONS.ser
session销毁时机
- 服务器关闭
- session对象调用invalidate()
- session默认失效时间30分钟,在tomcat/conf/web.xml中的session-config中
<session-config>
<session-timeout>30</session-timeout>
</session-config>