(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 {

    1. Cookie cookie = new Cookie("nname", "tom");
    2. response.addCookie(cookie);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    1. this.doPost(request, response);

    } }

@WebServlet(“/cookie2”) public class Cookie2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  1. Cookie[] cookies = request.getCookies();
  2. if (cookies != null){
  3. for (int i = 0; i < cookies.length; i++) {
  4. Cookie cookie = cookies[i];
  5. String name = cookie.getName();
  6. String value = cookie.getValue();
  7. System.out.println(name+": "+value);
  8. }
  9. }
  10. }
  11. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  12. this.doPost(request, response);
  13. }

}

  1. <a name="99K3b"></a>
  2. #### Cookie原理
  3. - 浏览器请求cookie1
  4. - 服务器addCookie将cookie保存在响应头中,键Set-Cookie 值nname=tom
  5. ![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)
  6. - 浏览器收到这个cookie会缓存在本地,下次请求的时候,放在请求头中键Cookie 值nname=tom
  7. - 浏览器请求cookie2
  8. ![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)
  9. - 总体流程
  10. ![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)
  11. <a name="TkEzi"></a>
  12. #### 一次性发送多个Cookie

@WebServlet(“/cookie1”) public class Cookie1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  1. Cookie cookie1 = new Cookie("name", "tom");
  2. Cookie cookie2 = new Cookie("age", "20");
  3. response.addCookie(cookie1);
  4. response.addCookie(cookie2);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. this.doPost(request, response);
  8. }

}

  1. - 添加Cookie
  2. ![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)
  3. - 获取cookie
  4. ![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)
  5. <a name="e6V7w"></a>
  6. #### Cookie保存时间
  7. - 默认cookie储存在浏览器内存中,浏览器关闭时,cookie失效
  8. - 设置持久化储存setMaxAge
  9. - 正数 cookie数据写到硬盘的文件中,n秒后自动删除
  10. - 负数 保存在内存中,浏览器关闭就消失了
  11. - 0 删除cookie

@WebServlet(“/cookie1”) public class Cookie1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  1. Cookie cookie1 = new Cookie("name", "tom");
  2. // 正数 将cookie数据写到硬盘的文件中,n秒后自动删除
  3. // 负数 保存在内存中,浏览器关闭就消失了
  4. // 0 删除cookie
  5. cookie1.setMaxAge(10);
  6. response.addCookie(cookie1);
  7. }
  8. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  9. this.doPost(request, response);
  10. }

}

  1. <a name="SMl36"></a>
  2. #### Cookie储存中文
  3. - tomcat8之前不能储存中文,8之前的可以使用URL编码
  4. - 不能储存空格
  5. - URLEncoder.encode(value, "utf-8");
  1. String value = "2010 20 20";
  2. value = URLEncoder.encode(value, "utf-8");
  3. Cookie cookie = new Cookie("name", value);
  4. cookie.setMaxAge(0);
  5. response.addCookie(cookie);
  1. - URLDecoder.decode(value);
  1. Cookie[] cookies = request.getCookies();
  2. if (cookies != null){
  3. for (int i = 0; i < cookies.length; i++) {
  4. Cookie cookie = cookies[i];
  5. String name = cookie.getName();
  6. String value = cookie.getValue();
  7. System.out.println(name+": "+value);
  8. value = URLDecoder.decode(value);
  9. System.out.println(name+": "+value);
  10. }
  11. }
  1. <a name="coU4a"></a>
  2. #### Cookie共享
  3. - 第一种 同一个Tomcat服务器
  4. - 同一个tomcat服务器,部署多个web项目,默认这些项目之间不能共享cookie
  5. - 可以通过setPath()让同tomcat下的其他web项目可以共享cookie,默认是自身的虚拟目录
  6. > setPath("/web1");
  7. > Cookie.setPath("/");// 让所有的都可以共享
  1. Cookie cookie1 = new Cookie("name", "tom");
  2. cookie1.setPath("/");
  3. response.addCookie(cookie1);
  1. - 第二种 不同tomcat服务器
  2. - Cookie.setDomain(string),如果一级域名先难沟通,那么多个服务器之间cookie可以共享
  3. > 例如
  4. > 百度新闻[http://news.baidu.com/](http://news.baidu.com/)
  5. > 百度贴吧[https://tieba.baidu.com/index.html](https://tieba.baidu.com/index.html)
  6. > setDomain(".baidu.com")后,百度新闻和百度贴吧就可以cookie共享
  7. <a name="t0U5k"></a>
  8. #### Cookie特点和作用
  9. - Cookie储存在客户端浏览器
  10. - 浏览器对单个cookie的大小有限制4kb
  11. - 对同一个域名下的cookie数量也有限制20
  12. - 储存少量不敏感数据
  13. - 在不登录的情况储存一些用户设置
  14. <a name="dp3b4"></a>
  15. ### (3)Session
  16. - 服务端会话技术:在一次会话的多次请求间共享数据,将数据保存在服务端的对象中HttpSession
  17. - 没有大小限制,数据存储在服务器端
  18. <a name="QZaIO"></a>
  19. #### 基本使用
  20. - 常用方法
  21. - request.getSession();
  22. - session.setAttribute("name","tom");
  23. - session.getAttribute("name");
  24. - 在没有关闭服务器的前提下,下例中两个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”); }

  1. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  2. this.doPost(request, response);
  3. }

}

@WebServlet(“/Session2”) public class Session2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

  1. HttpSession session = request.getSession();
  2. System.out.println(session);
  3. String name = (String) session.getAttribute("name");
  4. System.out.println(name);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. this.doPost(request, response);
  8. }

}

  1. <a name="x2Se9"></a>
  2. #### 原理
  3. - Session是通过cookie实现的
  4. ![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)
  5. - 第一次请求session1,响应头中有set-cookie,请求头没有
  6. ![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)
  7. - 第二次请求session2,请求头中有cookie,服务器会找出JSESSIONID对应的HttpSession对象,保证了一次会话中的Session一直
  8. ![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)
  9. <a name="S5wqt"></a>
  10. #### Session相关特点
  11. - 客户端关闭,服务端不关闭,两次获取的session不一致
  12. - 解决方法如下,设置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);

  1. HttpSession session = request.getSession();
  2. Cookie c = new Cookie("JSESSIONID", session.getId());
  3. c.setMaxAge(60*60);
  4. response.addCookie(c);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. this.doPost(request, response);
  8. }

} ``` image.png

  • 客户端不关闭,服务端关闭,两次获取的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中
    1. <session-config>
    2. <session-timeout>30</session-timeout>
  1. </session-config>