根据session查询服务器信息,二、Session

什么是session

Cookie是存储在客户端方,Session是存储在服务端方,客户端只存储SessionId。

在上一篇我们了解了什么是Cookie,既然浏览器已经通过Cookie实现了有状态这一需求,那么为什么又来了一个Session呢?这里我们想象一下,如果将账户的一些信息都存入Cookie中的话,一旦信息被拦截,那么我们所有的账户信息都会丢失掉。所以就出现了Session,在一次会话中将重要信息保存在Session中,浏览器只记录SessionId一个SessionId对应一次会话请求。

4384cd9dfb8e

利用session,javaweb项目实现了登录状态的控制。

对Tomcat而言,Session是一块在服务器开辟的内存空间,其内部的有一个ConcurrentHashMap,我们做setAttribute和removeAttribute的时候都操作的是此map。(补充一句,request对象的setAttribute也操作的是内部的一个Map)Session是存储在服务端的,可以理解为一个状态列表。拥有一个唯一会话标识SessionId。可以根据SessionId在服务端查询到存储的信息。

Session会引发一个问题,即后端多台机器时Session共享的问题,解决方案可以使用Spring提供的框架。创建:浏览器第一次访问服务器时,容器通过调用 HttpServletRequest的getSession(true)的时候创建  https://www.jianshu.com/p/e564cc4c0a52

删除:超时;程序调用HttpSession.invalidate();程序关闭;

session存放在哪里:服务器端的内存中。不过session可以通过特殊的方式做持久化管理(memcache,redis)。

session的id是从哪里来的,sessionID是如何使用的:当客户端第一次请求session对象时候,服务器会为客户端创建一个session,并将通过特殊算法算出一个session的ID,用来标识该session对象

tomcat中session的创建

4384cd9dfb8e实现包的路径是:org.apache.catalina.session,tomcat对外提供session调用的接口不在这个实现包里,对外接口是在包javax.servlet.http下的HttpSession,而实现包里的StandardSession是tomcat提供的标准实现,当然对外tomcat不希望用户直接操作StandardSession,而是提供了一个StandardSessionFacade类,tomcat容器里具体操作session的组件是servlet,而servlet操作session是通过StandardSessionFacade进行的,这样就可以防止程序员直接操作StandardSession所带来的安全问题。(StandardSessionFacade使用了设计模式里的Façade(外观)模式,外观模式能让不同逻辑层的组件进行解耦)。

Manager接口的实现是Session的管理者,保存着这台tomcat中所有的Session。Manager在Context启动的时候被创建,被启动。所有具体实现session管理功能的类都要继承这个类,该类有一个受保护的方法,该方法就是创建sessionId值的方法:(tomcat的session的id值生成的机制是一个随机数加时间加上jvm的id值,jvm的id值会根据服务器的硬件信息计算得来,因此不同jvm的id值都是唯一的)

StandardManager类是tomcat容器里默认的session管理实现类,它会将session的信息存储到web容器所在服务器的内存里。

PersistentManagerBase也是继承ManagerBase类,它是所有持久化存储session信息的基类,PersistentManager继承了PersistentManagerBase,但是这个类只是多了一个静态变量和一个getName方法,目前看来意义不大,对于持久化存储session,tomcat还提供了StoreBase的抽象类,它是所有持久化存储session的基类,另外tomcat还给出了文件存储FileStore和数据存储JDBCStore两个实现。

session 使用过程用户访问的时候,会在服务器上开辟一块空间(创建一个session,伴随着一个sessionID)。

访问完了就断开连接(http协议连接后就断开连接了),下次该用户还进行重复的访问,会通过服务器response给客户端cookie的sessionid来进行再次连接。

当关闭窗口,cookies里面的东西就没有了,再次打开就取不到相应的sessionID,服务器存的session内容超时后会自动清除。如果客户端禁用了cookie,可以进行url重写,就是将获取到的sessionID跟踪到url后面。

分布式session/单点登录(SSO)

session的实现机制都是web容器里内部机制,这就导致一个web容器里所生成的session的id值是不同的,因此当一个请求到了A服务器,浏览器得到响应后,客户端存下的是A服务器上所生成的session的id,当在另一个请求分发到了B服务器,B服务器上的web容器是不能识别这个session的id值,更不会有这个sessionID所对应记录下来的信息,这个时候就需要两个不同web容器之间进行session的同步。Tomcat容器有一个官方的解决方案就是使用apache+tomcat+mod_jk方案,当一个web容器里session的信息发生变化后,该web容器会向另一个web容器进行广播,另一个web收到广播后将session信息同步到自己的容器里,这个过程是十分消耗系统资源,当访问量增加会严重影响到网站的效率和稳定性。某系统解决方案:当用户请求网站的时候会先将请求发送给硬件的负载均衡设备,该设备可以截获客户端发送过来的session的id值,然后我们根据这个id值找到产生这个session的服务器,将请求直接发送给这台服务器。这种解决方案看起来解决了session共享问题,其实结果是将集群系统最终变回了单点系统,如果处理请求的web容器挂掉了,那么用户的相关会话操作也就废掉了。此外,这种做法也干扰了负载均衡服务器的负载均衡的计算,让请求的分发并不是公平的。分布式缓存技术:例如:memcached和redis,将session信息的存储独立出来也是解决session同步问题的方法。

Tomcat的session同步也有使用memcache的解决方案: http://blog.sina.com.cn/s/blog_5376c71901017bqx.html

但是该方案只是解决了同步问题,session机制任然和web容器紧耦合,我们需要一个高效、可扩展的解决方案,那么我们就应该不是简单的把session独立出来存储而是设计一个完全独立的session机制,它既能给每个web应用提供session的功能又可以实现session同步,下面是一篇用zookeeper实现的分布式session方案:http://www.open-open.com/lib/view/open1378556537303.htmlweblogic实现-主从备份:https://blog.csdn.net/liuxueping1987/article/details/53316930bboss会话共享框架:

模式一 实现同一个应用集群各节点之间的会话共享  模式二 实现同一域名或者同一根域(不同的子域名)下不同应用之间的会话共享(可以灵活定义哪些会话数据需要在两个应用之间进行共享,哪些数据作为应用私有会话数据不对其他应用共享,默认情况下共享两个应用间的所有会话数据。) https://www.iteye.com/problems/102344session现在在分布式系统中用得越来越少了,都自己实现,存在后端缓存系统中,这样对服务无状态和跨应用跨域单点登录都有好处

关于session的几个问题:

1、浏览器关闭后session会销毁吗? --还在,换浏览器就不在了

2、request.getSession 当request失效后对应的session也会失效吗?什么时候request就失效了?---request.请求一次使命就完成了,session还在。Session容器中的变量作用于整次会话,request的话只能做转发,重定向就无效了。requst作用于一次请求,比如你登录,然后跳转到一个页面,request还在,如果你又发送了另个请求,用于登录的请求就失效了。session只要不关闭浏览器或者退出这个网页就一直存在。

3、request.getSession()和HttpServletRequest.getSession(boolean)的区别:

HttpSession session=request.getSession();

1) 查询浏览器中是否有session对象,

2) 如果没有,就创建一个新的session对象

3) 如果有,就取出session对象

HttpSession session=HttpServletRequest.getSession(boolean);

当boolean为true时,和request.getSession()一样

当boolen为false时,只查询,没有查到,返回null

4、在JSP中怎么设置session不创建?用

由于session会消耗内存资源,因此,如果不打算使用session,应该在所有的JSP中关闭它。

当JSP页面没有显式禁止session的时候,在打开浏览器第一次请求该jsp的时候,服务器会自动为其创建一个session,并赋予其一个sessionID,发送给客户端的浏览器。以后客户端接着请求本应用中其他资源的时候,会自动在请求头上添加:Cookie:JSESSIONID=客户端第一次拿到的session ID。这样,服务器端在接到请求时候,就会收到session ID,并根据ID在内存中找到之前创建的session对象,提供给请求使用。

5、tomcat容器总是自动创建session,有没有什么方法可以让所有的session不自动创建?

只有当自己真正需要session的时候,才手动去创建?

7、同一客户端机器多次请求同一个资源,session一样吗?

一般来说,每次请求都会新创建一个session。对于多标签的浏览器(比如360浏览器)来说,在一个浏览器窗口中,多个标签同时访问一个页面,session是一个。对于多个浏览器窗口之间,同时或者相隔很短时间访问一个页面,session是多个的,和浏览器的进程有关。对于一个同一个浏览器窗口,直接录入url访问同一应用的不同资源,session是一样的。

Spring Session源码

使用 GemFire 来构建 C/S 架构的 httpSession(不关注)

使用第三方仓储来实现集群 session 管理,也就是常说的分布式 session 容器,替换应用容器(如 tomcat 的 session 容器)。仓储的实现,Spring Session 提供了三个实现(redis,mongodb,jdbc),其中 redis 使我们最常用的。程序的实现,使用 AOP 技术,几乎可以做到透明化地替换。(核心)

可以非常方便的扩展 Cookie 和自定义 Session 相关的 Listener,Filter。

可以很方便的与 Spring Security 集成,增加诸如 findSessionsByUserName,rememberMe,限制同一个账号可以同时在线的 Session 数(如设置成 1,即可达到把前一次登录顶掉的效果)等等

4384cd9dfb8e

4384cd9dfb8e

session和cookie的结合使用

session本身并不难,如果只是做登录校验之类的功能,并不需要深入了解,但难的是session和cookie的结合使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值