最近一年由于工作繁忙,加上各种事情比较多,好久没有更新文章了,向大家,也向自己说声抱歉!后面会继续将学习的内容分享出来!
项目遇到的问题:
启动项目,登录网站,输入用户名、密码,访问,
当项目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共享】测试成功
推荐阅读
- =======j2ee|spring用注解实现注入的@resource,@autowired,@inject区别
- jar|springboot项目打成jar包和war包,并部署(快速打包部署)
- 数据库|效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...
- java人生|35K 入职华为Java开发那天,我哭了(这 5 个月做的一切都值了)
- Java毕业设计项目实战篇|Java项目:在线嘿嘿网盘系统设计和实现(java+Springboot+ssm+mysql+maven)
- 微服务|微服务系列:服务发现与注册-----Eureka(面试突击!你想了解的Eureka都在这里.持续更新中......)
- java|ApplicationListener和SpringApplicationRunListener的联系
- Spring|SpringSecurity--自定义登录页面、注销登录配置
- 性能|性能工具之 Jmeter 通过 SpringBoot 工程启动
- 代码狂魔|Spring源码分析之IOC容器初始化流程