shiro自身实现了一套线性管理体系,使我们在不借助于任何web容器或servlet的情况下使用session
SessionManager:session的管理器
SessionDAO:session的增删改查操作
shiro会话管理
继承AbstractSessionDAO
Redis实现Session共享及可能存在的问题.
需要重点看
Shiro会话管理
其会话管理主要涉及到了Shiro整体框架的SessionManager与SessionDao模块。
视频中讲的是与Redis相结合,进行对Session的增删改查操作。
当然Shiro管理Session还可以通过别的介质进行管理。
步骤如下:
先加载Redis,在Maven 的pom.xml文件中配置Redis依赖包,坐标如下:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency>
配置Spring与Redis结合的配置文件。新建立Spring-redis.xml文件。
由于之前也没接触过Redis,这里只能重复视频中的配置。配置JedisPool的bean,
其中设置属性jedisPoolConfig、host、port信息,其中JedisPoolConfig则需要另外建立bean,然后将此Bean引入到JedisPool中,host则写本机地址,port一般为6379.当然以上的类都是Redis包下的,Redis是依靠Jedis来实现其功能。然后将此文件导入到Spring.xml主文件中,即采用import标签。
注意:需要下载相应redis server,程序启动的时候,要先启动redis server,否则会报错。
新建util包,建立JedisUtil类,此类中主要是对Redis进行增删改查操作。因为Reids是存放键值对的形式。在JedisUtil中,将JedisPool注入到类中,写入单独方法获取Jedis,即通过JedisPool.getResource()来获取Jedis,此方法用于获取Jedis对象,通过Jedis进行直接对Redis存放值进行增删改查操作。
创建Shiro中SessionDao类,实现AbstractSessionDao,实现其中的增删改查、获取当前活跃的Session等方法。由于redis中存放的是key与value都是二进制的数组形式,所以在修改Redis值的时候需要注意将其转成二进制的数据,并且判断是否存在相应id、session等。
其中:generateSessionId(session) 生成Serializable序列化的sessionId
assignSessionId(session,sessionId) 绑定session与相应的Id值
session.getId 返回的是SessionId值,同理也是Serializable的类型
SerializationUtils.serialize (session) 通过序列化将session转成相应的byte[]数组
SerializationUtils.deserialize(byte[]) 通过反序列化将字节转成Object类型,可通过强转获取 Session对象.
PS:注意session 与 sessionId是否为空的情况判断。另外如果加入前缀,可以在搜索的时候加入前缀+“*”代表搜索前缀是aa的所有匹配的key值。
6.同样JedisUtils中也需要通过Jedis 的get put expire del keys方法进行获取 存储 设置等待时间 删除操作、查询匹配key的值集合。
7.新建类SessionManager 继承 DefaultWebSessionManager类,里面可以什么都不做。
8.在spring.xml文件中,写入SessionManager的Bean 并且写入Sessiondao的bean,将SessionDao的Bean 注入到Sessionmanager中。最后将SessionManager的Bean注入到SecurityManager中即可。
9.此处将5-1与5-2整合在一起了,5-2的例子就不单独写了。
此处在测试过程中,发现系统会读取Session多次。
需要在SessionManager中重写,retrieveSession方法。
a.先通过参数SessionKey获取sessionId,然后判断sessionkey是否为websessionkey,如果是则通过强转将其转为WebSessionKey并且获取ServletRequest。
b.核心是将SessionId 与 Session 放到Reqeust中,如果Request有,则直接拿去,没有在去Redis中拿,如此一来则减少了访问Redis的次数,减轻了Reids 的压力。此时判断request是否为空以及sessionId是否为空,如果同时都不为,则通过sessionId 从request的属性中获取Session,在判断Session是否为空,如果不是空,则返回。
c.当不符合以上条件时候,直接调用父类的方法获取Session,继续判断request是否为空,如果不是空,则将session和sessionId放入到request的属性中即可,方便下次再来寻找直接从request中拿出,不用再多次访问Redis了。
Shiro会话管理
session管理
会话管理