1. 什么是session?
1.1. 定义
提供了一种在多个页面请求或对网站的访问中识别用户并存储有关该用户的信息的方法。
理解http session是什么,就需要理解session的本质。session即“会话”,生活中张三与李四进行一次会话,他们可能会以互相问答的形式持续好多次。这个过程就是一次session。 http请求采用client的request 和 server的response 作为会话过程的载体,这种典型的B/S模式下的client和server就好比张三和李四。
相比张三和李四的记忆力,不幸的是http是无状态的(stateless)。这导致http的下一次request根本不知道上一次request是谁,或者其他信息。
这里有三种方案可以存储这些信息,或者说三个地方,分别是:
-
客户端
cookie就是客户端存储信息的实现,可以参考:https://www.jianshu.com/p/fe0a4b5943e3。客户端存储信息的方式,显然会随着客户端的关闭清除信息,这不利于服务端对用户信息的获取,一些场景下我们还是希望服务端可以存储用户信息的。 -
过程中
当然我们也可以在url中携带一些参数,这些参数包含了上一个请求的信息,比如http://example.com/myPage?asd=lol&boo=no。这种方式显然无法存储信息,只能让信息作为参数在多个request间传递。 -
服务端
如果我们可以在客户端存储用户的一些信息,当用户访问时,我们就可以进行身份认证或者其他操作。这种思想促成了http session的产生。
对比以上三种方案,显然服务端存储更加利于会话信息的存储,具体一点,当发起http请求我们可以选择服务端存储session对象,其中可以包含一些信息。然后返回session id,客户端在接下来的调用加入sessionid,传入客户端。客户端就可以跟绝sessionid确认请求者的信息,从而实现身份认证等功能。
1.2. java实现
显然,每种语言都可以对session有自己的实现,java提供了一个接口HttpSession,https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html
jdk是这样解释的:servlet 容器使用此接口在 HTTP 客户端和 HTTP 服务器之间创建会话。 会话持续指定的时间段,跨越来自用户的多个连接或页面请求。 一个会话通常对应一个用户,他可能多次访问一个站点。 服务器可以通过多种方式维护会话,例如使用 cookie 或重写 URL。
该接口允许 servlet
- 查看和操作有关会话的信息,例如会话标识符、创建时间和上次访问时间
将对象绑定到会话,允许用户信息跨多个用户连接保持 - 当应用程序在会话中存储对象或从会话中删除对象时,会话会检查该对象是否实现了 HttpSessionBindingListener。如果是,servlet 会通知对象它已绑定到会话或从会话中解除绑定。在绑定方法完成后发送通知。对于失效或过期的会话,在会话失效或过期后发送通知。
1.3. 总结
session的本质是会话跟踪技术的一种,它就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出返回给客户端Cookie保存。
1.4. 一些疑问
- session存储在什么地方?
存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,显然关掉浏览器并不会关闭session。
- 什么时候创建了session?
不同语言实现的应用程序有不同创建Session的方法,而在Java中是通过调用HttpServletRequest的getSession方法(使用true作为参数)创建的。在创建了Session的同时,服务器会为该Session生成唯一的Session id,而这个Session id在随后的请求中会被用来重新获得已经创建的Session;在Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有Session id;当客户端再次发送请求的时候,会将这个Session id带上,服务器接受到请求之后就会依据Session id找到相应的Session,从而再次使用之。
- 保存session id的方式
- 保存sessionid的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
- 由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把sessionid传递回服务器,经常采用的一种技术叫做URL重写,就是把sessionid附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个sessionid。
2. 如何使用session?
2.1. servlet中如何新建http session?
在Servlet中,你肯定用过下面这句话,
HttpSession session = request.getSession();
如果当前没有session,则会立刻建立一个session;
如果有session则返回当前session。
这句话和
HttpSession session = request.getSession(true);
的效果是一样的。
但是如果你写成
HttpSession session = request.getSession(false);
则不会自动建立session。
若当前没有session,你所得到的seesion只会是一个null。
显然session是调用getSession方法产生的。
相应的jsp中没有显式的使用 <% @page session="false"%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句
HttpSession session = HttpServletRequest.getSession(true);
这也是JSP中隐含的session对象的来历。
2.2. http session的属性
获取到HttpSession对象后,我们就需要使用HttpSession的某些方法去设置和更改某些参数了。如:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);
还有另外一个常用的设置:session.setMaxInactiveInterval(5); 可以用来设置过期时间。
更多细节可以参考jdk:https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html