1. 会话技术
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止(浏览器关闭,标签页关闭不算会话结束)。一次会话中包含多次请求和响应。
- 会话的功能:在一次会话的范围内的多次请求间,共享数据。
- HTTP 是基于请求响应模型的,一次请求对应一次响应,请求之间相互独立,不能进行数据通信。想要在多次请求之间共享数据,就需要会话技术。
- 在 Java 中,会话技术分为 Cookie 和 Session 两种。
- Cookie:客户端会话技术,数据存储在客户端。
- Session:服务器端会话技术,数据存储在服务器端。
2. Cookie
-
概念:客户端会话技术,将数据保存到客户端。
-
使用步骤:
- 创建 Cookie 对象,绑定数据:
new Cookie(String name, String value);
- 发送 Cookie 对象,
response.addCookie(Cookie cookie);
,使用此语句会自动响应 Cookie 到客户端,原理是服务器设置了响应头Set-Cookie: name=value
,发送给了客户端。 - 在同一个会话中在次请求的时候,客户端会将存储在本地的 Cookie 放置在请求头中自动发送给服务端,其原理是设置请求头
Cookie: name=value
- 获取 Cookie,拿到数据,
Cookie[] request.getCookies();
- 创建 Cookie 对象,绑定数据:
-
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.com
和news.baidu.com
的时候, Cookie 都会被浏览器携带过去
- 在同一个服务器(同一个 tomcat)的不同项目(不同 Web 项目)之间进行 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 的活化。
- 不是同一个,但是为了确保数据的不丢失,Tomcat 自动完成以下操作
-
session 什么时候被销毁?
- 服务器关闭
- session 对象调用
invalidate()
- session 默认失效时间 30 分钟,可以修改,Tomcat 在 web.xml 下修改 session-timeout 即可
-
session 的特点
- session 用于存储一次会话的多次请求的数据,存在服务器端
- session 可以存储任意类型,任意大小的数据。
-
Session 与 Cookie 的区别:
- session 存储数据在服务器端,Cookie 在客户端
- session 没有数据大小限制,Cookie 有
- session 数据安全,Cookie 相对不安全