1. 会话技术

  • 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止(浏览器关闭,标签页关闭不算会话结束)。一次会话中包含多次请求和响应。
  • 会话的功能:在一次会话的范围内的多次请求间,共享数据。
    • HTTP 是基于请求响应模型的,一次请求对应一次响应,请求之间相互独立,不能进行数据通信。想要在多次请求之间共享数据,就需要会话技术。
  • 在 Java 中,会话技术分为 Cookie 和 Session 两种。
    • Cookie:客户端会话技术,数据存储在客户端。
    • Session:服务器端会话技术,数据存储在服务器端。
  • 概念:客户端会话技术,将数据保存到客户端。

  • 使用步骤:

    1. 创建 Cookie 对象,绑定数据:new Cookie(String name, String value);
    2. 发送 Cookie 对象,response.addCookie(Cookie cookie);,使用此语句会自动响应 Cookie 到客户端,原理是服务器设置了响应头 Set-Cookie: name=value,发送给了客户端。
    3. 在同一个会话中在次请求的时候,客户端会将存储在本地的 Cookie 放置在请求头中自动发送给服务端,其原理是设置请求头 Cookie: name=value
    4. 获取 Cookie,拿到数据,Cookie[] request.getCookies();
  • javax.servlet.http.Cookie

    • String getName() 获取 Cookie 中的键
    • String getValue() 获取 Cookie 中的值
  • 原理:基于响应头 Set-Cookie 和请求头 Cookie 实现。

  • 一次可以发送多个 Cookie,调用两次 addCookie() 方法即可,在响应头中表现为

    Set-Cookie: username=admin
    Set-Cookie: password=123456
    

    在请求头中的表现形式为 Cookie: username=admin; password=123456

  • 设置 Cookie 在浏览器中的存活时间,实现持久化存储,将 Cookie 存储在硬盘上,在多次会话间共享数据

    • 默认情况下,Cookie 存储在浏览器内存中,当浏览器关闭后,即会话结束,Cookie 数据被销毁
    • 通过 setMaxAge(int seconds) 来设置 Cookie 的存活时间
      • 正数:将 Cookie 数据写到硬盘的文件中,持久化存储,并指定 cookie 存活时间,时间到后,Cookie 文件自动失效。
      • 负数:默认值
      • 零:删除 Cookie 信息
    • 设置存活时间以后即会生效,即使会话没有结束,存活时间到了,Cookie 也会失效。
    • 要手动删除 Cookie,设置一个新的 Cookie 回客户端即可,name 一致,maxAge 为 0,如果设置了 path 和 domain,也需要一样。
  • Cookie 中存储中文:

    • 在 Tomcat 8 之前 cookie 中不能直接存储中文数据,需要将中文数据转码,一般采用 URL 编码解决(一个字节编码为 %E3 形式)

    • 在 Tomcat 8 之后,cookie 支持中文数据。特殊字符还是不支持,建议使用 URL 编码存储,URL 解码解析

    • URL 编码和解码

      //存储数据
      Cookie cookie1 = new Cookie("username", URLEncoder.encode("你好呀", "utf-8"));
      response.addCookie(cookie1);
      //取出数据
      System.out.println(cookie.getName() + "=" + URLDecoder.decode(cookie.getValue(), "utf-8"));
      
  • Cookie 共享问题

    • 在同一个服务器(同一个 tomcat)的不同项目(不同 Web 项目)之间进行 Cookie 的共享
      • 默认不能,默认情况下 setPath(String path) 方法会设置 path 为当前项目的虚拟路径,比如对于 http://localhost:8080/solo,则会设置 setPath("/solo");
      • 如果要在不同项目间共享,设置 setPath("/")
    • 在不同服务器共享,比如多个项目之间有关联,但部署在不同服务器上,一般通过设置一级域名来实现。
      • setDomain(String path):如果设置一级域名相同,那么多个服务器之间 Cookie 可以共享
      • setDomain(".baidu.com"):那么访问 tieba.baidu.comnews.baidu.com 的时候, Cookie 都会被浏览器携带过去
  • Cookie 的特点和作用

    • Cookie 存储数据在客户端浏览器
    • 浏览器对于单个 Cookie 的大小有限制(4kb) 以及对同一个域名下的总 cookie 数量也有限制(20 个)
    • Cookie 一般用于存储少量的不太敏感的数据(不安全)
    • 比如在不登录的情况下,完成服务器对客户端的身份识别,例如没有登录的情况下通过浏览器对 www.baidu.com 进行了一些设置,这些设置需要保存在客户端,就通过 Cookie 来进行,如果登录了,可以将数据保存在服务端。

3. Session

  • 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象(HttpSession)中。

  • 获取 HttpSession 对象:通过 request 来获取

    • HttpSession session = request.getSession(); 此方法会判断客户端的请求 Cookie 中有没有 JSESSIONID,若有,且服务器有对应 ID 的 session,则返回此 ID 对应的 session,否则返回新建的 session,并向客户端响应新建 session 的 ID。
  • 使用 HttpSession 对象:

    • Object getAttribute(String name)
    • void setAttribute(String name, Object value)
    • void removeAttribute(String name)
    • String getId() 获取此 session 的 JSESSIONID
  • Session 的原理:Session 的实现是依赖于 Cookie 的

    当客户端第一次请求服务器获取 Session 的时候,获取 JSESSIONID,发现没有此 Cookie,服务器会在内存中创建一个新的 Session 对象,这个对象有一个 ID,然后响应给客户端一个包含此 ID 的 Cookie,响应头的值为 JSESSIONID=值 的形式,再次请求的时候根据此 ID 去获取对应的 Session,这样就保证了一次会话范围内,多次获取的 Session 对象是同一个。

  • 当客户端关闭后,服务器不关闭,两次获取 session 是否为同一个?

    • 默认情况下。不是。
    • 如果需要相同,则可以创建 Cookie,键为 JSESSIONID,值为 session.getId(),设置最大存活时间,让 Cookie 持久化保存,这样每次请求的时候 JESSIONID 是一样的,能获取到同一个 session。
  • 客户端不关闭,服务器关闭后,两次获取的 session 是同一个吗?

    • 不是同一个,但是为了确保数据的不丢失,Tomcat 自动完成以下操作
      • session 的钝化:在服务器正常关闭之前,将 session 对象序列化到硬盘上
      • session 的活化:在服务器启动后,将 session 文件转化为内存中的 session 对象。
      • 此时,即使服务器重启,获取的 session 对象还是同一个
    • 项目放置在 Tomcat 的 webapps 中可以完成自动钝化和活化,在 IDEA 中启动 Tomcat 不行,因为 Tomcat 会把钝化后的文件放置到 work 目录下,但是 IDEA 每次启动 Tomcat 都会删除并重新创建 work 目录,无法完成 session 的活化。
  • session 什么时候被销毁?

    • 服务器关闭
    • session 对象调用 invalidate()
    • session 默认失效时间 30 分钟,可以修改,Tomcat 在 web.xml 下修改 session-timeout 即可
  • session 的特点

    • session 用于存储一次会话的多次请求的数据,存在服务器端
    • session 可以存储任意类型,任意大小的数据。
  • Session 与 Cookie 的区别:

    • session 存储数据在服务器端,Cookie 在客户端
    • session 没有数据大小限制,Cookie 有
    • session 数据安全,Cookie 相对不安全