您的位置:首页 > 数据库 > Redis

利用Redis 实现多tomcat 同一用户同一环境单一在线

2016-03-02 23:46 405 查看
在实际开发中,我们需要控制一个用户在pc和app的同类型环境下只能登录一个,最多可以pc和app同时在线。

在单一的tomcat环境中,我们可以通过建立一个全局的map,存放用户名(id)+登录环境(APP或PC)和对应的session。按如下方法实现:

1、session里保存用户名id和登录方式。

2、每次用户登录的时候判断是否有重复的登录,有的话就将原来的session失效,没有就保存到map里。

3、监听session,在session destroy事件处理里负责根据session里的值找到对应的map里面的key-value键值对并将其删除。

但在多tomcat环境下,我们可以通过redis 实现tomcat的session的共享:

配置很简单,:

1、在context.xml里配置(注意不要在server.xml里配置)

<ValveclassName="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"
/> 

<ManagerclassName="com.orangefunction.tomcat.redissessions.RedisSessionManager"

host="localhost"

port="6379"

database="0"

maxInactiveInterval="60"/>

2、将下列jar放到tomcat的lib下面

tomcat-redis-session-manager-2.0.0

jredis-2.8

commons-pool2-2.3

3、注意不要在webapp对应的应用的lib里包含tomcat-redis-session-manager-2.0.0 包,否则会报错。当时同事用的maven,打包的时候把omcat-redis-session-manager-2.0.0 包一并打进去,出现错误,找了半天才找到。

原来想法很简单,只有把对应的全局的map保存到redis里就可以了,但发现在应用层HttpSession对象根本不支持序列化,无法保存到redis里。

同时发现tomcat的session在redis里是把sessionId作为key来保存的,但同样对应的value,取出后该对象不是HttpSession,没法按照HttpSession的方法将session失效(调用session.invalidate()方法)

解决办法如下:

1、不使用全局的map,直接将存放用户名(id)+登录环境(APP或PC)作为键值,对应的sessionid作为value保存到redis里。(注意这里不保存session)

2、每次用户登录的时候判断是否有重复的登录,有的话就将原来的session失效,失效的方法是直接将sessionid键值从redis里删除。如果没有就按照1的方式保存到redis里。

3、监听session,在session destroy事件处理里负责根据session里的值找到对应的redis里面的key-value键值对并将其删除。

用上面的方式实现了功能,但同时发现还遗漏了一个问题,就是session是有过期的,他在redis里tomcat设置了对应的有效时间,而我们的用户登录信息的生命周期应该和其对应session同步。因此我们需要进行如下改造:

1、保存信息到redis里的时候同时设置有效时间。

2、增加一个filter,对所有信息进行拦截,filter里对该session对应的保存在redis里的登录信息设置有效时间。

至此,所有的问题都解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  redis tomcat session