spring shiro redis : 将session存入redis,实现session共享

最近一年由于工作繁忙,加上各种事情比较多,好久没有更新文章了,向大家,也向自己说声抱歉!后面会继续将学习的内容分享出来!
项目遇到的问题:
启动项目,登录网站,输入用户名、密码,访问,
当项目tomcat停止,然后重新启动,
在网页继续访问时,因为session失效,被强制跳转到登录页面,提示重新登录,
这样在tomcat集群时,就会有问题,因此需要将session统一存放到redis中,项目的启动和停止不影响session。

我们的项目已经集成好了spring shiro redis,但是session没有存入redis实现共享,因此此文是实现session存入redis集群,共享部分功能:
(该项目借鉴了博文:https://blog.csdn.net/zhaoyachao123/article/details/78332488)

解决步骤:
1-sessionManager添加sessionDAO属性 想要实现使用redis管理session 需要在shiro 的sessionmanager添加sessionDAO属性 如下

a)如果是使用xml配置,如下:


b)如果是使用的spring注解配置,如下:
@Configuration public class ShiroConfig { @Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); Collection listeners = new ArrayList(); listeners.add(new ShiroSessionListener()); sessionManager.setSessionListeners(listeners); sessionManager.setSessionDAO(sessionDAO()); return sessionManager; } //SessionDAO是一个接口: org.apache.shiro.session.mgt.eis.SessionDAO //我们自己写一个类,类名是SessionDao ,继承EnterpriseCacheSessionDAO //而EnterpriseCacheSessionDAO和 SessionDAO的关系如下: //EnterpriseCacheSessionDAO extends CachingSessionDAO //CachingSessionDAO extends AbstractSessionDAO //AbstractSessionDAO implements SessionDAO @Bean public SessionDAO sessionDAO() { //改造后 SessionDao sessionDao = new SessionDao() ; return sessionDao ; //改造前 //MemorySessionDAO sessionDAO = new MemorySessionDAO(); //return sessionDAO; } }


2- 创建sessionDao类 sessionDao需要实现EnterpriseCacheSessionDAO类或者CachingSessionDAO类,咱们这里以EnterpriseCacheSessionDAO类为例如下:
public class SessionDao extends EnterpriseCacheSessionDAO { // Integer expireSeconds = 60*60*24 ; //60*60*24=7天 @Override protected Serializable doCreate(Session session) { Serializable sessionId = super.doCreate(session); byte[] session_value = https://www.it610.com/article/sessionToByte(session) ; byte[] sessionId_key = sessionId.toString().getBytes() ; RedisUtil.set(sessionId_key, session_value) ; return sessionId ; } @Override protected void doDelete(Session session) { super.doDelete(session); RedisUtil.remove(session.getId().toString()); } @Override protected Session doReadSession(Serializable sessionId) { Session session = super.doReadSession(sessionId); if(session == null) { byte[] sessionId_key = sessionId.toString().getBytes() ; byte[] session_value = RedisUtil.get(sessionId_key) ; if(session_value != null && session_value.length> 0){ session = byteToSession(session_value) ; } } return session ; } @Override protected void doUpdate(Session session) { super.doUpdate(session); byte[] session_value = https://www.it610.com/article/sessionToByte(session) ; byte[] sessionId_key = session.getId().toString().getBytes() ; RedisUtil.set(sessionId_key, session_value) ; } // 把session对象转化为byte保存到redis中 public byte[] sessionToByte(Session session){ ByteArrayOutputStream bo = new ByteArrayOutputStream(); byte[] bytes = null; try { ObjectOutput oo = new ObjectOutputStream(bo); oo.writeObject(session); bytes = bo.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return bytes; } // 把byte还原为session public Session byteToSession(byte[] bytes){ ByteArrayInputStream bi = new ByteArrayInputStream(bytes); ObjectInputStream in; SimpleSession session = null; try { in = new ObjectInputStream(bi); session = (SimpleSession) in.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }return session; } }


3-redisUtil类如下:
@Component public class RedisUtil { @Autowired private JedisCluster jCluster ; private static JedisCluster jedisCluster ; @PostConstruct public void init() { jedisCluster = jCluster ; } /** * 写入缓存,无超时功能 * * @param key * @param value * @return */ public static boolean set(final byte[] key, byte[] value) { boolean result = false; try { jedisCluster.set(key, value) ; result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 写入缓存,带有超时功能 * * @param key * @param value * @param expireSeconds * @return */ public static boolean set(final byte[] key, byte[] value, int expireSeconds) { boolean result = false; try { jedisCluster.set(key, value) ; jedisCluster.expire(key, expireSeconds) ; result = true; } catch (Exception e) { e.printStackTrace(); } return result; } public static void remove(final String key) { if (exists(key)) { jedisCluster.del(key); } } public static boolean exists(final String key) { return jedisCluster.exists(key); } public static byte[] get(final byte[] key) { byte[] result = jedisCluster.get(key) ; return result; }}


测试:
启动项目,登录网站,访问,
然后将项目停止,重新启动,
继续访问,依然可以正常使用登录后的一起状态。
【spring shiro redis : 将session存入redis,实现session共享】测试成功

    推荐阅读