apache shiro框架如何使用nginx负载
来源:互联网 发布:linx mysql执行sql文件 编辑:程序博客网 时间:2024/05/16 03:41
1.apache shiro框架在使用负载均衡的时候出现的问题
当我进入我的项目的首页的时候发现是无法登陆的,原因是因为服务器之间的session没有共享这也是Apache Shiro集群需要解决的问题。
Apache Shiro集群要解决2个问题,一个是session的共享问题,一个是授权信息的cache共享问题,官网给的例子是Ehcache的实现。这里我们可以
通过集成redis来实现。
2.apache shiro集成redis。
这个比较简单。只需要引入相关的jar包,我项目里的redis是使用的哨兵模式。配置如下:
redis的安装可以参考我之前写的文章。
3.apache shiro集群解决session共享的问题。
我们可以看DefaultWebSessionManager的源码,发现其父类DefaultSessionManager中有sessionDAO属性,这个属性是真正实现了session储存的类,这个就是我们自己实现的redis session的储存类。
之前我在项目中使用的是EnterpriseCacheSessionDAO
<property name="sessionDAO">
<bean class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/>
</property>
<bean class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/>
</property>
现在我们就要通过redis来实现了。
redisShiroSessionDAO:
/** * Created by Maggie on 2017/7/14. */public class RedisSessionDAO extends AbstractSessionDAO { private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class); private ShiroSessionRepository shiroSessionRepository; public ShiroSessionRepository getShiroSessionRepository() { return shiroSessionRepository; } public void setShiroSessionRepository( ShiroSessionRepository shiroSessionRepository) { this.shiroSessionRepository = shiroSessionRepository; } @Override public void update(Session session) throws UnknownSessionException { getShiroSessionRepository().saveSession(session); } @Override public void delete(Session session) { getShiroSessionRepository().deleteSession(session.getId()); } //用来统计当前活动的session @Override public Collection<Session> getActiveSessions() { return shiroSessionRepository.getAllSessions(); } @Override protected Serializable doCreate(Session session) { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); getShiroSessionRepository().saveSession(session); return sessionId; } @Override protected Session doReadSession(Serializable sessionId) { return getShiroSessionRepository().getSession(sessionId); }
shiroSessionRepository:
/** * Created by Maggie on 2017/7/17. */public class JedisShiroSessionRepository implements ShiroSessionRepository{ private static Logger logger = LoggerFactory.getLogger(JedisShiroSessionRepository.class); public static final String REDIS_SHIRO_SESSION = "shiro_redis_session:"; public static final String REDIS_SHIRO_ALL = "*shiro_redis_session:*"; public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; } private RedisManager redisManager; @Override public void saveSession(Session session) { if(session == null || session.getId() == null){ logger.error("session or session id is null"); return; } session.setTimeout(redisManager.getExpire()* TimeEnum.SESSION_TIME_BASE.getCode()); getRedisManager().insertObject(this.buildRedisSessionKey(session.getId()), session, redisManager.getExpire()); } @Override public void deleteSession(Serializable sessionId) { if (sessionId == null) { throw new NullPointerException("session id is empty"); } getRedisManager().deleteObject(this.buildRedisSessionKey(sessionId)); } @Override public Session getSession(Serializable sessionId) { if (sessionId == null) throw new NullPointerException("session id is empty"); Session session = null; try { session =SerializeUtil.deserialize(getRedisManager().queryObjectByKey(this.buildRedisSessionKey(sessionId)),Session.class); } catch (Exception e) { logger.error( "获取session异常,id:[%s]",sessionId); } return session; } @Override public Collection<Session> getAllSessions() { Collection<Session> sessions = new HashSet<>();; try { Set<byte[]> byteKeys = getRedisManager().keys(REDIS_SHIRO_ALL); if (byteKeys != null && byteKeys.size() > 0) { for (byte[] bs : byteKeys) { Session obj =SerializeUtil.deserialize(getRedisManager().queryObjectByKey(bs),Session.class); if(obj instanceof Session){ sessions.add(obj); } } } } catch (Exception e) { logger.error(e.toString(),"获取全部session异常"); } return sessions; } private String buildRedisSessionKey(Serializable sessionId) { return REDIS_SHIRO_SESSION + sessionId; }}
RedisManager:
/** * Redis管理 * Created by Mac Zhang on 14-11-06 上午10:45 */@Componentpublic class RedisManager { protected org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private StringRedisTemplate redisTemplate; /** * 查询redis数据库 * @param key 查询关键字 * @return redis 返回对象 ecustjxjy */ public byte[] queryObjectByKey(final Object key) { log.debug("queryObjectByKey request:{}", key); Object session =redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { byte[] redisKey=null; if(key instanceof String) { redisKey = serialize(key); }else { redisKey=(byte[])key; } if (connection.exists(redisKey)) { return connection.get(redisKey); } return null; } }); return (byte[])session; } public Set<byte[]> keys(final String key){ log.debug("queryObjectByKey request:{}", key); Set<byte[]> value=redisTemplate.execute(new RedisCallback<Set<byte[]>>() { @Override public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException { byte[] redisKey = serialize(key); Set<byte[]> value = connection.keys(redisKey); return value; } }); return value; } /** * 插入redis 数据库,设置有效期 * @param obj 保存对象 * @param key 关键字 * @param timeout 有效期(秒) * @return 对象类型,泛型 */ public boolean insertObject(final String key,final Object obj,final long timeout){ log.debug("insertObject request:key={},obj={}", key, obj.getClass()); if(key.contains("SessionUser")){ System.out.println(SerializeUtil.deserialize((byte [])obj)); } boolean result = redisTemplate.execute(new RedisCallback<Boolean>() { @Override public Boolean doInRedis(RedisConnection connection) throws DataAccessException { byte [] redisKey = serialize(key); byte [] redisValue = serialize(obj); connection.set(redisKey,redisValue); if(timeout > 0){ redisTemplate.expire(key, timeout, TimeUnit.SECONDS); } return true; } }); log.debug("insertObject response:{}", result); return result; } /** * 删除redis 保存对象 * @param key 查询关键字 * @return boolean */ public boolean deleteObject(final String key){ log.info("deleteObject request:key={}", key); Long result = redisTemplate.execute(new RedisCallback<Long>() { @Override public Long doInRedis(RedisConnection connection) throws DataAccessException { byte [] redisKey = serialize(key); return connection.del(redisKey); } }); log.debug("deleteObject response:{}",result); return result > 0; } /** * 解决缓存key时前缀的乱码(序列化key时使用redis序列化) * @param key * @return */ public byte [] serialize(final Object key){ if(key instanceof String){ return this.redisTemplate.getStringSerializer().serialize(key.toString()); } return SerializeUtil.serialize(key); } public long getExpire(){ return TimeEnum.REDIS_EXPIRE_TIME.getCode(); } public Session deserialize(byte[] var1){ return SerializeUtil.deserialize(var1,Session.class); }}
通过上面的方式就可以实现session共享了,并且session由redis来保存。下一篇解决cache共享的问题。
阅读全文
0 0
- apache shiro框架如何使用nginx负载
- apache shiro使用nginx集群如何解决cache共享
- Apache Shiro(安全框架)
- Apache Shiro 框架解析
- 安全框架Apache Shiro
- Apache Shiro框架简介
- Apache Shiro 权限框架
- apache shiro权限框架
- 开发框架-Shiro-30分钟学会如何使用Shiro
- Nginx+Apache均衡负载
- 如何使用Apache做负载均衡
- Spring MVC 中Apache Shiro 框架的使用步骤
- 在Spring MVC中使用Apache Shiro安全框架
- 在Spring MVC中使用Apache Shiro安全框架
- 使用Windows创建Nginx+Apache的负载均衡
- Apache Shiro的使用
- 安全框架Apache Shiro学习心得
- Apache Shiro权限管理框架
- 解决的各种报错
- 【Git零基础教程】(4)分支
- react 中 使用 没有启用图片上传功能的simditor 富文本编辑器
- 并查集 POJ 1182 食物链
- Telnet指定源地址IP (telnet use source ip)
- apache shiro框架如何使用nginx负载
- 百度地图-创建检索信息窗口对象
- java的数组知识
- 《魂斗罗:归来》卖“情怀”?不!质量体系来撑腰
- 机器学习(十二)
- 算法系列——Search Insert Position
- C++线程的几种调用方式
- Python学习笔记——深拷贝与浅拷贝
- android 代码规范文档(命名规范)