Session是什么,Java Session基本用法(附带实例)
由于 Cookie 中的信息是保存在浏览器端的,浏览器每次访问时都需要发回 Cookie,因此我们不能在 Cookie 中保存大量的信息。
既然客户端不能保存大量的信息,那么可不可以将信息保存到服务器端呢?
答案是肯定的,我们可以为每次会话在服务器端中创建一个对象,然后在该对象中保存相关的信息。这个对象的类型是 HttpSession,后面提到的 Session 对象就是 HttpSession 类型的对象。
那么如何在会话和对象之间建立一个对应关系呢?服务器端会给每个 Session 对象都赋予一个 id 值,这个 id 是不可重复的,也就是说每个 Session 对象都有唯一的标识。这样我们就可以将这个唯一的标识交给浏览器保存,浏览器每次访问服务器时都会带着这个唯一标识,这样服务器就可以根据这个唯一标识找到每个会话对应的 Session 对象了。
这个唯一标识被称为 JSESSIONID,保存在浏览器的 Cookie 中,因此 HttpSession 运行时依赖于 Cookie。
因为 Session 对象是每个浏览器特有的,所以用户的记录可以存放在 Session 对象中,然后传递给用户一个名字为 JSESSIONID 的 Cookie,这个 JSESSIONID 对应这个服务器中的一个 Session 对象,通过它就可以获取到保存用户信息的 Session 对象。
Session 的工作机制如下,Session 对象相当于浏览器在服务器的账户,而 Session 对象的 id(JSESSIONID)相当于这个账户的账号。实际上 Session 对象就是服务器中用来保存会话信息的对象,每个 Session 对象都有唯一的 id,这个 id 通过 Cookie 的形式先由服务器发送给浏览器,浏览器收到 Cookie 后会自动保存,然后在每次访问服务器时,都会带着这个 Cookie,服务器就可以根据 Cookie 中保存的 Session 的 id 找到浏览器对应的 Session 对象。
当服务器端第一次创建 Session 对象的时候,会话就开始了,会话结束分为以下三种情况:
1) 名字为 JSESSIONID 的 Cookie 消失时,即浏览器关闭。名字为 JSESSIONID 的 Cookie 是一个瞬时的 Cookie,当它消失了,对于服务器来说,意味着找不到 Session 对象,此时服务器会重新创建 Session 对象,从而得到一个全新的 Cookie,这样一来,与之前 Cookie 的会话就结束了。
2) 服务器强制将 Session 对象销毁。当服务器强制将 Session 对象销毁后,即使客户端还存在 JSESSIONID,但根据 JSESSIONID 找不到对应的 Session 对象,服务器仍会重新创建 Session 对象,重新分配给客户端一个 Cookie,并覆盖掉之前的 Cookie。
3) Session的自动失效机制。一旦 Session 自动失效,和服务器强制销毁是一个效果,即使客户端有 JSESSIONID,但根据 JSESSIONID 找不到对应的 Session 对象,服务器仍会重新创建 Session 对象,重新分配给客户端一个 Cookie,并覆盖掉之前的 Cookie。
Session 的常用方法如下:
1) 通过 HttpServletRequest 对象获得 Session 对象:
2) 获取 HttpSession 对象的属性值:
3) 设置 HttpSession 对象的属性值:
4) 移除 HttpSession 对象的属性值:
创建 chapter09_session 模块,在该模块下创建 ServletDemo03 类继承 HttpServlet,重写 doGet() 和 doPost() 方法,创建 HttpSession 对象并设置其属性,示例代码如下:
创建 ServletDemo04 类继承 HttpServlet,重写 doGet() 和 doPost() 方法,获取 Session 属性,示例代码如下:
接下来启动项目,首先单击访问 ServletDemo03,创建 Session 对象,查看控制台,如下图所示:

图 1 创建Session对象
在网页上单击 F12 键,查看响应头中的 JSESSIONID,如下图所示:

图 2 查看ServletDemo03的响应头中的JSESSIONID
然后访问 ServletDemo04,获取 Session 对象及设置的属性值,查看控制台,如下图所示:

图 3 获取Session及属性值
结果表明,ServletDemo04 类中获取的 Session 和 ServletDemo03 类中创建的是同一个对象,且在两个类之间成功传递了“session-message”的属性值。
再次在网页单击 F12 键,查看 ServletDemo04 的 Cookie 信息,如下图所示:

图 4 查看ServletDemo04响应头中的Cookie信息
可以看出,这里同样携带了与 ServletDemo03 中相同的 JSESSIONID。再次论证了每个浏览器对应唯一的 Session 对象,而每个 Session 对象又对应唯一的 JSESSIONID。
整个过程如下图所示:

图 5 Session工作机制
另外,可以通过如下代码,查看 HttpSession 对象是否为新对象,以及获取 HttpSession 对象的 id 值:
不过困难之处在于,从服务器端角度来看,很难精确得知类似浏览器关闭的动作。而且即使浏览器一直没有关闭,也不代表用户仍然在使用。
因此,决定让服务器端给 Session 对象设置最大闲置时间,服务器端给 Session 对象设置最大闲置时间的默认值为 1800 秒。自行设置具体时间的代码格式如下:

图 6 最大闲置时间生效的机制
测试 Session 时效性的示例代码如下:
既然客户端不能保存大量的信息,那么可不可以将信息保存到服务器端呢?
答案是肯定的,我们可以为每次会话在服务器端中创建一个对象,然后在该对象中保存相关的信息。这个对象的类型是 HttpSession,后面提到的 Session 对象就是 HttpSession 类型的对象。
那么如何在会话和对象之间建立一个对应关系呢?服务器端会给每个 Session 对象都赋予一个 id 值,这个 id 是不可重复的,也就是说每个 Session 对象都有唯一的标识。这样我们就可以将这个唯一的标识交给浏览器保存,浏览器每次访问服务器时都会带着这个唯一标识,这样服务器就可以根据这个唯一标识找到每个会话对应的 Session 对象了。
这个唯一标识被称为 JSESSIONID,保存在浏览器的 Cookie 中,因此 HttpSession 运行时依赖于 Cookie。
因为 Session 对象是每个浏览器特有的,所以用户的记录可以存放在 Session 对象中,然后传递给用户一个名字为 JSESSIONID 的 Cookie,这个 JSESSIONID 对应这个服务器中的一个 Session 对象,通过它就可以获取到保存用户信息的 Session 对象。
Session 的工作机制如下,Session 对象相当于浏览器在服务器的账户,而 Session 对象的 id(JSESSIONID)相当于这个账户的账号。实际上 Session 对象就是服务器中用来保存会话信息的对象,每个 Session 对象都有唯一的 id,这个 id 通过 Cookie 的形式先由服务器发送给浏览器,浏览器收到 Cookie 后会自动保存,然后在每次访问服务器时,都会带着这个 Cookie,服务器就可以根据 Cookie 中保存的 Session 的 id 找到浏览器对应的 Session 对象。
当服务器端第一次创建 Session 对象的时候,会话就开始了,会话结束分为以下三种情况:
1) 名字为 JSESSIONID 的 Cookie 消失时,即浏览器关闭。名字为 JSESSIONID 的 Cookie 是一个瞬时的 Cookie,当它消失了,对于服务器来说,意味着找不到 Session 对象,此时服务器会重新创建 Session 对象,从而得到一个全新的 Cookie,这样一来,与之前 Cookie 的会话就结束了。
2) 服务器强制将 Session 对象销毁。当服务器强制将 Session 对象销毁后,即使客户端还存在 JSESSIONID,但根据 JSESSIONID 找不到对应的 Session 对象,服务器仍会重新创建 Session 对象,重新分配给客户端一个 Cookie,并覆盖掉之前的 Cookie。
3) Session的自动失效机制。一旦 Session 自动失效,和服务器强制销毁是一个效果,即使客户端有 JSESSIONID,但根据 JSESSIONID 找不到对应的 Session 对象,服务器仍会重新创建 Session 对象,重新分配给客户端一个 Cookie,并覆盖掉之前的 Cookie。
Session入门案例
下面同样通过案例演示 Session 的具体应用。在会话域范围内,借助 Session 实现在 ServletDemo03 和 ServletDemo04 之间共享数据。Session 的常用方法如下:
1) 通过 HttpServletRequest 对象获得 Session 对象:
HttpSession session = request.getSession();如果第一次调用该方法,其实是创建 Session 对象,第一次调用之后会通过 SessionId 获取 Session。
2) 获取 HttpSession 对象的属性值:
Object message = session.getAttribute(String name);
3) 设置 HttpSession 对象的属性值:
session.setAttribute(String name, Object value);
4) 移除 HttpSession 对象的属性值:
session.removeAttribute(String name);
创建 chapter09_session 模块,在该模块下创建 ServletDemo03 类继承 HttpServlet,重写 doGet() 和 doPost() 方法,创建 HttpSession 对象并设置其属性,示例代码如下:
//省略 import 语句 @WebServlet("/servletDemo03") public class ServletDemo03 extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取 Session 对象 HttpSession session = request.getSession(); // 2. 向 Session 对象中存入数据 session.setAttribute("session-message","hello-session"); } }
创建 ServletDemo04 类继承 HttpServlet,重写 doGet() 和 doPost() 方法,获取 Session 属性,示例代码如下:
//省略 import 语句 @WebServlet("/servletDemo04") public class ServletDemo04 extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取 Session 对象 HttpSession session = request.getSession(); // 2. 获取 Session 对象中"session-message"对应的属性值 String message = (String)session.getAttribute("session-message"); System.out.println(message); } }同样,在 index.html 文件中编写超链接,访问 ServletDemo03 和 ServletDemo04 类,实现两类之间共享数据。
接下来启动项目,首先单击访问 ServletDemo03,创建 Session 对象,查看控制台,如下图所示:

图 1 创建Session对象
在网页上单击 F12 键,查看响应头中的 JSESSIONID,如下图所示:

图 2 查看ServletDemo03的响应头中的JSESSIONID
然后访问 ServletDemo04,获取 Session 对象及设置的属性值,查看控制台,如下图所示:

图 3 获取Session及属性值
结果表明,ServletDemo04 类中获取的 Session 和 ServletDemo03 类中创建的是同一个对象,且在两个类之间成功传递了“session-message”的属性值。
再次在网页单击 F12 键,查看 ServletDemo04 的 Cookie 信息,如下图所示:

图 4 查看ServletDemo04响应头中的Cookie信息
可以看出,这里同样携带了与 ServletDemo03 中相同的 JSESSIONID。再次论证了每个浏览器对应唯一的 Session 对象,而每个 Session 对象又对应唯一的 JSESSIONID。
Session工作机制
在浏览器正常访问服务器的前提下,当服务器端调用了 request.getSession() 方法,服务器端会检查当前请求中是否携带了 JSESSIONID 的 Cookie。分两种情况:- 如果有,则根据 JSESSIONID 在服务器端查找对应的 HttpSession 对象,能够找到的话,将找到的 HttpSession 对象作为 request.getSession() 方法的返回值返回;找不到,则服务器端会新建一个 HttpSession 对象作为 request.getSession() 方法的返回值返回。
- 如果没有,服务器端会直接新建一个 HttpSession 对象作为 request.getSession() 方法的返回值返回。
整个过程如下图所示:

图 5 Session工作机制
另外,可以通过如下代码,查看 HttpSession 对象是否为新对象,以及获取 HttpSession 对象的 id 值:
// 1. 调用 request 对象的方法尝试获取 HttpSession 对象 HttpSession session = request.getSession(); // 2. 调用 HttpSession 对象的 isNew() 方法 boolean whetherNew = session.isNew(); // 3. 打印 HttpSession 对象是否为新对象 System.out.println("whetherNew = " + whetherNew + "\nHttpSession 对象是新的:\nHttpSession 对象是旧的"); // 4. 调用 HttpSession 对象的 getId() 方法 String id = session.getId(); // 5. 打印 JSESSIONID 的值 System.out.println("JSESSIONID = " + id);
Session有效时间
当浏览器的用户访问量较大时,Session 对象相应的也要创建很多。如果一味创建不释放,那么服务器端的内存迟早要被耗尽。因此我们要为 Session 设置时限。不过困难之处在于,从服务器端角度来看,很难精确得知类似浏览器关闭的动作。而且即使浏览器一直没有关闭,也不代表用户仍然在使用。
因此,决定让服务器端给 Session 对象设置最大闲置时间,服务器端给 Session 对象设置最大闲置时间的默认值为 1800 秒。自行设置具体时间的代码格式如下:
void setMaxInactiveInterval(int var1); // 设置最大闲置时间,单位是 s (秒)最大闲置时间生效的机制如下图所示:

图 6 最大闲置时间生效的机制
测试 Session 时效性的示例代码如下:
// 获取默认的最大闲置时间 int maxInactiveIntervalSecond = session.getMaxInactiveInterval(); System.out.println("maxInactiveIntervalSecond = " + maxInactiveIntervalSecond); // 设置默认的最大闲置时间 session.setMaxInactiveInterval(15);前面提到,我们还可以直接强制 Session 立即失效,代码格式如下:
session.invalidate();