34-Session技术
Session
javax.servlet.http.HttpSession
Servlet 还提供了 HttpSession
接口,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式。
Servlet 容器使用这个接口来创建一个 HTTP 客户端和 HTTP 服务器之间的 session 会话。会话持续一个指定的时间段,跨多个连接或页面请求。
一个会话只有一个Session对象, 整个会话中session中的数据共享
Session原理
生命周期
-
创建: 第一次调用request.getSession()方法时,会创建一个session对象。(当浏览器在服务器端没有对应的session时,调用request.getSession()方法服务器会创建一个session对象。)
-
销毁:
-
超时销毁:默认情况下,当超过30分钟没有访问session,session就会超时销毁。(30分钟是默认时间,可以修改,但不推荐修改)
-
自杀:调用session的invalidate方法时,会立即销毁session。
-
意外身亡:当服务器非正常关闭时(硬件损坏,断电,内存溢出等导致服务器非正常关闭),session会随着服务器的关闭而销毁;
当服务器正常关闭,在关闭之前,服务器会将内部的session对象序列化保存到服务器的work目录下,变为一个文件。这个过程叫做session的钝化(序列化);再次将服务器启动起来,钝化着的session会再次回到服务器,变为服务器中的对象,这个过程叫做session的活化(反序列化)
序列化session文件目录:
tomcat目录\work\Catalina\主机名\应用名\SESSIONS.set
例如:
apache-tomcat-8.5.56\work\Catalina\localhost\sessionTest\SESSIONS.set
-
获取Session对象
您会通过调用 HttpServletRequest
的公共方法 getSession()
来获取 HttpSession
对象,如下所示:
HttpSession session = request.getSession();
Session方法
返回值及修饰符 | 方法 | 说明 |
---|---|---|
public void |
setAttribute(String name, Object value) |
使用指定的名称 绑定一个对象到该 session 会话。 |
public Object |
getAttribute(String name) |
返回在该 session 会话中具有指定名称的对象, 如果没有指定名称的对象,则返回 null。 |
public void |
removeAttribute(String name) |
将从该 session 会话 移除指定名称的对象。 |
public void |
invalidate() |
指示该 session 会话无效, 并解除绑定到它上面的任何对象。 |
public String |
getId() |
返回一个包含分配给该 session 会话 的唯一标识符的字符串。 |
public long |
getCreationTime() |
返回该 session 会话被创建的时间, 自格林尼治标准时间 1970 年 1 月 1 日午夜起, 以毫秒为单位。 |
public long |
getLastAccessedTime() |
返回客户端最后一次发送与该 session 会话 相关的请求的时间 自格林尼治标准时间 1970 年 1 月 1 日 午夜算起,以毫秒为单位。 |
public void |
setMaxInactiveInterval(int interval) |
在 Servlet 容器指示该 session 会话无效之前, 指定客户端请求之间的时间, 以秒为单位。 |
public int |
getMaxInactiveInterval() |
返回 Servlet 容器在客户端访问时 保持 session 会话打开的最大时间间隔, 以秒为单位。 |
public boolean |
isNew() |
如果客户端还不知道该 session 会话, 或者如果客户选择不参入该 session 会话, 则该方法返回 true。 |
public Enumeration |
getAttributeNames() |
返回 String 对象的枚举, String 对象包含所有绑定到 该 session 会话的对象的名称。 |
Session超时时间
一般session的超时时间默认是无响应(期间没有给服务器发送请求)30分钟后失效, 我们也可以手动修改
-
( 修改全局默认 )修改tomcat目录下的conf/web.xml
全局修改, 如果单个web应用没有指定session失效时间, 则使用全局的配置
<!-- 配置Session失效时间, 单位: 分钟 --> <session-config> <session-timeout>30</session-timeout> </session-config>
-
( 修改某一个应用的 )WEB应用目录下webapp中的 WEB-INF/web.xml ( 常用 )
只对当前的WEB应用生效
<!-- 配置Session失效时间, 单位: 分钟 --> <session-config> <session-timeout>30</session-timeout> </session-config>
-
应用程序代码中:硬编码
session.setMaxInactiveInterval(30*60);//以秒为单位
-
修改tomcat的server.xml ( 很少使用, 也不推荐使用这种方式 )
添加如下标签, 指定应用名为test的web应用session的时间为3600秒
<Context path="/test" docBase="/test" defaultSessionTimeOut="3600" isWARExpanded="true" isWARValidated="false" isInvokerEnabled="true" isWorkDirPersistent="false"/>
获取不到之前的session的问题
问题: 将数据保存到session中后,关闭浏览器再打开浏览器,访问服务器,此时获取不到之前的session。因为session是基于Cookie工作的。
分析原因: 在服务器创建一个session后,会为session分配一个独一无二的编号,称之为session的id,在此次响应时,服务器会将session的id以一个名称为JSESSIONID的cookie发送给浏览器保存到浏览器内部。
由于保存sessionid的cookie默认是会话级别的cookie,在浏览器关闭后,cookie会跟着销毁,sessionid也丢失了。因此下次访问服务器,没有session的id就获取不到之前的session。也获取不到session中的商品信息
解决方法:我们可以创建一个名称为JSESSIONID的cookie,其中保存session的ID,并设置cookie的最大存活时间,让cookie保存到硬盘上(即使浏览器关闭,cookie也不会销毁),这样下次访问服务器时,还可以将sessionid带给服务器,服务器可以通过sessionid获取到之前的session。 从session中获取到商品信息
// 第一次使用session的时候这样写
HttpSession session = request.getSession(); // 获取session
...
Cookie cookie = new Cookie("JSESSIONID", session.getId()); // 保存session编号到cookie
cookie.setMaxAge(3600 * 24); // 设置cookie失效时间一天
response.addCookie(cookie); // 把cookie添加到响应对象response
...
模拟登录原理
登录:
// 假设用户登录成功后获取了User的对象 user
HttpSession session = request.getSession();
session.setAttribute("user", user);
// 防止关闭浏览器再打开session丢失
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(3600 * 24);
response.addCookie(cookie);
后续代码中, 如果session中有user的数据说明已经登录, 没有就是未登录
HttpSession session = request.getSession();
// 当session中有user对象, 说明已经登录
if (session.getAttribute("user") != null) {
// 已登录, 正常访问
} else {
// 没有登录, 跳转到登录界面
}
注销:
HttpSession session = request.getSession();
session.invalidate();
// 然后重定向到登录界面