【JavaWeb】Servlet 系列——session 会话机制
29 关于 B/S 结构系统的会话机制(session 机制)
29.1 关于会话
会话对应的英语单词:session
用户打开浏览器,进行一系列操作,然后最终将浏览器关闭,这个整个过程叫做:一次会话。会话在服务器端也有一个对应的 java 对象,这个 java 对象叫做:session。
什么是一次请求:用户在浏览器上点击了一下,然后到页面停下来,可以粗略认为是一次请求。请求对应的服务器端的 java 对象是:request。
一个会话当中包含多次请求。(一次会话对应 N 次请求。)
在 java 的 servlet 规范当中,session 对应的类名:HttpSession(jarkata.servlet.http.HttpSession)
session 机制属于 B/S 结构的一部分。如果使用 php 语言开发 WEB 项目,同样也是有 session 这种机制的。session 机制实际上是一个规范。然后不同的语言对这种会话机制都有实现。
session 对象最主要的作用是:保存会话状态。(用户登录成功了,这是一种登录成功的状态,你怎么把登录成功的状态一直保存下来呢?使用 session 对象可以保留会话状态。)
29.2 为什么需要 session 对象来保存会话状态呢?
因为 HTTP 协议是一种无状态协议。
什么是无状态:请求的时候,B 和 S 是连接的,但是请求结束之后,连接就断了。为什么要这么做?HTTP 协议为什么要设计成这样?因为这样的无状态协议,可以降低服务器的压力。请求的瞬间是连接的,请求结束之后,连接断开,这样服务器压力小。
只要 B 和 S 断开了,那么关闭浏览器这个动作,服务器知道吗?
不知道。服务器是不知道浏览器关闭的。
张三打开一个浏览器 A,李四打开一个浏览器 B,访问服务器之后,在服务器端会生成:
张三专属的 session 对象
李四专属的 session 对象
29.3 为什么不使用 request 对象保存会话状态?为什么不使用 ServletContext 对象保存会话状态?
request.setAttribute()存,request.getAttribute()取,ServletContext 也有这个方法。request 是请求域。ServletContext 是应用域。
request 是一次请求一个对象。
ServletContext 对象是服务器启动的时候创建,服务器关闭的时候销毁,这个 ServletContext 对象只有一个。
ServletContext 对象的域太大。
request 请求域(HttpServletRequest)、session 会话域(HttpSession)、application 域(ServletContext)
request < session < application
29.4 session 对象的实现原理。
HttpSession session = request.getSession();
这行代码很神奇。张三访问的时候获取的 session 对象就是张三的。李四访问的时候获取的 session 对象就是李四的。
JSESSIONID=xxxxxx 这个是以 Cookie 的形式保存在浏览器的内存中的。浏览器只要关闭。这个 cookie 就没有了。
session 列表是一个 Map,map 的 key 是 sessionid,map 的 value 是 session 对象。
用户第一次请求,服务器生成 session 对象,同时生成 id,将 id 发送给浏览器。
用户第二次请求,自动将浏览器内存中的 id 发送给服务器,服务器根据 id 查找 session 对象。
关闭浏览器,内存消失,cookie 消失,sessionid 消失,会话等同于结束。
29.5 Cookie 禁用
cookie 禁用是什么意思?服务器正常发送 cookie 给浏览器,但是浏览器不要了。拒收了。并不是服务器不发了。
session 找不到了。每一次请求都会获取到新的 session 对象。
cookie 禁用了,session 机制还能实现吗?
可以。需要使用 URL 重写机制。
http://localhost:8080/servlet12/test/session;jsessionid=19D1C99560DCBF84839FA43D58F56E16
URL 重写机制会提高开发者的成本。开发人员在编写任何请求路径的时候,后面都要添加一个 sessionid,给开发带来了很大的难度,很大的成本。所以大部分的网站都是这样设计的:你要是禁用 cookie,你就别用了。
29.6 域对象:
request(对应的类名:HttpServletRequest)
请求域(请求级别的)
session(对应的类名:HttpSession)
会话域(用户级别的)
application(对应的类名:ServletContext)
应用域(项目级别的,所有用户共享的。)
这三个域对象的大小关系
request < session < application
他们三个域对象都有以下三个公共的方法:
setAttribute(向域当中绑定数据)
getAttribute(从域当中获取数据)
removeAttribute(删除域当中的数据)
使用原则:尽量使用小的域。
29.7 解决 oa 项目中的登录问题,让登录起作用。
登录成功之后,可以将用户的登录信息存储到 session 当中。也就是说 session 中如果有用户的信息就代表用户登录成功了。session 中没有用户信息,表示用户没有登录过。则跳转到登录页面。
29.8 会话结束
关闭浏览器之后,浏览器中保存的 sessionid 消失,下次重新打开浏览器之后,浏览器缓存中没有这个 sessionid,自然找不到服务器中对应的 session 对象。session 对象找不到等同于会话结束。
29.9 销毁 session 对象:
session 对象什么时候被销毁?一种销毁:是超时销毁。一种销毁:是手动销毁。
浏览器关闭的时候,服务器是不知道的,服务器无法检测到浏览器关闭了,所以 session 的悄毁要依靠 session 超时机制,但也有一种可能,系统提供了“安全退出”,用户可以点击这个按钮,这样服务题就知道你退出了,然后服务器会自动销毁 session 对象。 注意:session 对象销毁和 session 会话结束不同。
版权声明: 本文为 InfoQ 作者【胖虎不秃头】的原创文章。
原文链接:【http://xie.infoq.cn/article/733f19755cea939da41c3be99】。文章转载请联系作者。
评论