shiro redis 集群

1、配置文件


   
   

   
   
	
    
    
	
    
    
	
    
    
	
    
    

   
   


   
   

   
   
	
    
    

   
   


   
   

   
   
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    
		
     
     
			
      
      
		
     
     
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    

   
   


   
   
	
    
    
	
    
    

   
   

   
   
	
    
    

   
   

   
   
	
    
    
	
    
    
	
    
    

   
   

   
   
	
    
    
	
    
    
	
    
    
	
    
    
	
    
    

   
   


   
   

   
   


   
   

   
   
	
    
    

   
   


   
   
	
    
    

   
   


   
   
	
    
    
    
    
    
    
    
    
    
    
    

   
   


   
   
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

   
   


   
   

   
   
	
    
    

   
   


   
   

   
   
	
    
    

   
   

2、代码结构

3、session共享代码
package com.fangxin365.cms.cluster.session;

import java.io.Serializable;
import java.util.Collection;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.listener.CustomSessionListener;
import com.fangxin365.cms.cluster.utils.LoggerUtils;

public class CustomShiroSessionDAO extends AbstractSessionDAO {
	
	private static Logger logger = LoggerFactory.getLogger(CustomSessionListener.class);

	private ShiroSessionRepository shiroSessionRepository;
	
	@Override
	protected Serializable doCreate(Session session) {
		logger.info("CustomShiroSessionDAO =====> doCreate");
		Serializable sessionId = this.generateSessionId(session);
		this.assignSessionId(session, sessionId);
		getShiroSessionRepository().saveSession(session);
		return sessionId;
	}

	@Override
	public void update(Session session) throws UnknownSessionException {
		logger.info("CustomShiroSessionDAO =====> update");
		getShiroSessionRepository().saveSession(session);
	}
	
	@Override
	protected Session doReadSession(Serializable sessionId) {
		logger.info("CustomShiroSessionDAO =====> doReadSession");
		return getShiroSessionRepository().getSession(sessionId);
	}
	
	@Override
	public Collection
     
     
      
       getActiveSessions() {
		logger.info("CustomShiroSessionDAO =====> getActiveSessions");
		return getShiroSessionRepository().getAllSessions();
	}

	@Override
	public void delete(Session session) {
		logger.info("CustomShiroSessionDAO =====> delete");
		if (session == null) {
			LoggerUtils.error(getClass(), "Session 不能为null");
			return;
		}
		Serializable id = session.getId();
		if (id != null)
			getShiroSessionRepository().deleteSession(id);
	}

	// -----------------------//
	// Getter & Setter methods
	// -----------------------//
	public ShiroSessionRepository getShiroSessionRepository() {
		return shiroSessionRepository;
	}

	public void setShiroSessionRepository(ShiroSessionRepository shiroSessionRepository) {
		this.shiroSessionRepository = shiroSessionRepository;
	}
	
}
     
     
package com.fangxin365.cms.cluster.session;

import java.io.Serializable;
import java.util.Collection;

import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.cache.JedisManager;
import com.fangxin365.cms.cluster.session.ShiroSessionRepository;
import com.fangxin365.cms.cluster.utils.LoggerUtils;
import com.fangxin365.cms.cluster.utils.SerializeUtils;

public class JedisShiroSessionRepository implements ShiroSessionRepository {
	
	private static Logger logger = LoggerFactory.getLogger(JedisShiroSessionRepository.class);
    
	public static final String REDIS_SHIRO_SESSION = "fx365-shiro-redis-session:";
    //这里有个小BUG,因为Redis使用序列化后,Key反序列化回来发现前面有一段乱码
    public static final String REDIS_SHIRO_ALL = "*fx365-shiro-redis-session:*";
    
    private static final int SESSION_VAL_TIME_SPAN = 180000;
    private static final int DB_INDEX = 1;

    private JedisManager jedisManager;

    @Override
    public void saveSession(Session session) {
    	logger.info("JedisShiroSessionRepository =====> saveSession");
        if (session == null || session.getId() == null)
            throw new NullPointerException("session is empty");
        try {
            byte[] key = SerializeUtils.serialize(buildRedisSessionKey(session.getId()));
            byte[] value = SerializeUtils.serialize(session);
            long sessionTimeOut = session.getTimeout() / 1000;
            Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);
            
            getJedisManager().saveValueByKey(DB_INDEX, key, value, expireTime.intValue());
        } catch (Exception e) {
        	LoggerUtils.fmtError(getClass(), e, "save session error,id:[%s]",session.getId());
        }
    }
    
    @Override
    public Session getSession(Serializable id) {
		logger.info("JedisShiroSessionRepository =====> getSession");
        if (id == null)
        	 throw new NullPointerException("session id is empty");
        Session session = null;
        try {
            byte[] value = getJedisManager().getValueByKey(DB_INDEX, SerializeUtils.serialize(buildRedisSessionKey(id)));
            session = (Session)SerializeUtils.deserialize(value);
        } catch (Exception e) {
        	LoggerUtils.fmtError(getClass(), e, "获取session异常,id:[%s]",id);
        }
        return session;
    }
    
    @Override
    public Collection
      
      
       
        getAllSessions() {
    	logger.info("JedisShiroSessionRepository =====> getAllSessions");
    	Collection
       
       
        
         sessions = null;
		try {
			sessions = getJedisManager().getAllSession(DB_INDEX,REDIS_SHIRO_SESSION);
		} catch (Exception e) {
			LoggerUtils.fmtError(getClass(), e, "获取全部session异常");
		}
       
        return sessions;
    }

    @Override
    public void deleteSession(Serializable id) {
    	logger.info("JedisShiroSessionRepository =====> deleteSession");
        if (id == null) {
            throw new NullPointerException("session id is empty");
        }
        try {
            getJedisManager().deleteByKey(DB_INDEX, SerializeUtils.serialize(buildRedisSessionKey(id)));
        } catch (Exception e) {
        	LoggerUtils.fmtError(getClass(), e, "删除session出现异常,id:[%s]",id);
        }
    }

    private String buildRedisSessionKey(Serializable sessionId) {
        return REDIS_SHIRO_SESSION + sessionId;
    }

    // -----------------------//
 	// Getter & Setter methods
 	// -----------------------//
    public JedisManager getJedisManager() {
        return jedisManager;
    }

    public void setJedisManager(JedisManager jedisManager) {
        this.jedisManager = jedisManager;
    }
    
}
       
       
      
      
package com.fangxin365.cms.cluster.session;

import org.apache.shiro.session.Session;

import java.io.Serializable;
import java.util.Collection;

/**
 * Session操作
 */
public interface ShiroSessionRepository {

	/**
	 * 存储Session
	 */
	void saveSession(Session session);

	/**
	 * 删除session
	 */
	void deleteSession(Serializable sessionId);

	/**
	 * 获取session
	 */
	Session getSession(Serializable sessionId);

	/**
	 * 获取所有session
	 */
	Collection
      
      
       
        getAllSessions();
}
      
      

4、cache共享代码
package com.fangxin365.cms.cluster.cache.impl;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.Destroyable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.cache.ShiroCacheManager;

public class CustomShiroCacheManager implements CacheManager, Destroyable {

	private static Logger logger = LoggerFactory.getLogger(CustomShiroCacheManager.class);

	private ShiroCacheManager shiroCacheManager;

	@Override
	public 
       
       
        
         Cache
        
        
         
          getCache(String name) throws CacheException {
		logger.info("CustomShiroCacheManager =====> getCache");
		return getShiroCacheManager().getCache(name);
	}

	@Override
	public void destroy() throws Exception {
		logger.info("CustomShiroCacheManager =====> destroy");
		shiroCacheManager.destroy();
	}

	// -----------------------//
	// Getter & Setter methods
	// -----------------------//
	public ShiroCacheManager getShiroCacheManager() {
		return shiroCacheManager;
	}

	public void setShiroCacheManager(ShiroCacheManager shiroCacheManager) {
		this.shiroCacheManager = shiroCacheManager;
	}

}
        
        
       
       
package com.fangxin365.cms.cluster.cache.impl;

import org.apache.shiro.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.cache.JedisManager;
import com.fangxin365.cms.cluster.cache.JedisShiroCache;
import com.fangxin365.cms.cluster.cache.ShiroCacheManager;

public class JedisShiroCacheManager implements ShiroCacheManager {

	private static Logger logger = LoggerFactory.getLogger(JedisShiroCacheManager.class);

	private JedisManager jedisManager;

	@Override
	public 
       
       
        
         Cache
        
        
         
          getCache(String name) {
		logger.info("JedisShiroCacheManager =====> getCache");
		return new JedisShiroCache
         
         
          
          (name, getJedisManager());
	}

	@Override
	public void destroy() {
		logger.info("JedisShiroCacheManager =====> destroy");
		// 如果和其他系统,或者应用在一起就不能关闭
		// getJedisManager().getJedis().shutdown();
	}

	// -----------------------//
	// Getter & Setter methods
	// -----------------------//
	public JedisManager getJedisManager() {
		return jedisManager;
	}

	public void setJedisManager(JedisManager jedisManager) {
		this.jedisManager = jedisManager;
	}
	
}

         
         
        
        
       
       
package com.fangxin365.cms.cluster.cache;

import java.util.Collection;
import java.util.Set;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.utils.LoggerUtils;
import com.fangxin365.cms.cluster.utils.SerializeUtils;

@SuppressWarnings("unchecked")
public class JedisShiroCache
       
       
        
         implements Cache
        
        
         
          {
	
	private static Logger logger = LoggerFactory.getLogger(JedisShiroCache.class);

	/**
	 * 为了不和其他的缓存混淆,采用追加前缀方式以作区分
	 */
	private static final String REDIS_SHIRO_CACHE = "fx365-shiro-redis-cache:";
	
	private static final int DB_INDEX = 1;

	private JedisManager jedisManager;

	private String name;

	@SuppressWarnings("rawtypes")
	static final Class
         
         
          
           SELF = JedisShiroCache.class;

	public JedisShiroCache(String name, JedisManager jedisManager) {
		this.name = name;
		this.jedisManager = jedisManager;
	}

	/**
	 * 自定义relm中的授权/认证的类名加上授权/认证英文名字
	 */
	public String getName() {
		if (name == null)
			return "";
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public V get(K key) throws CacheException {
		logger.info("JedisShiroCache =====> get");
		byte[] byteKey = SerializeUtils.serialize(buildCacheKey(key));
		byte[] byteValue = new byte[0];
		try {
			byteValue = jedisManager.getValueByKey(DB_INDEX, byteKey);
		} catch (Exception e) {
			LoggerUtils.error(SELF, "get value by cache throw exception", e);
		}
		return (V) SerializeUtils.deserialize(byteValue);
	}

	@Override
	public V put(K key, V value) throws CacheException {
		logger.info("JedisShiroCache =====> put");
		V previos = get(key);
		try {
			jedisManager.saveValueByKey(DB_INDEX, SerializeUtils.serialize(buildCacheKey(key)), SerializeUtils.serialize(value), -1);
		} catch (Exception e) {
			LoggerUtils.error(SELF, "put cache throw exception", e);
		}
		return previos;
	}

	@Override
	public V remove(K key) throws CacheException {
		logger.info("JedisShiroCache =====> remove");
		V previos = get(key);
		try {
			jedisManager.deleteByKey(DB_INDEX, SerializeUtils.serialize(buildCacheKey(key)));
		} catch (Exception e) {
			LoggerUtils.error(SELF, "remove cache  throw exception", e);
		}
		return previos;
	}

	@Override
	public void clear() throws CacheException {
		logger.info("JedisShiroCache =====> clear");
	}

	@Override
	public int size() {
		logger.info("JedisShiroCache =====> size");
		if (keys() == null)
			return 0;
		return keys().size();
	}

	@Override
	public Set
          
          
           
            keys() {
		logger.info("JedisShiroCache =====> keys");
		return null;
	}

	@Override
	public Collection
           
           
             values() { logger.info("JedisShiroCache =====> values"); return null; } private String buildCacheKey(Object key) { logger.info("JedisShiroCache =====> buildCacheKey"); return REDIS_SHIRO_CACHE + getName() + ":" + key; } } 
           
          
          
         
         
        
        
       
       
package com.fangxin365.cms.cluster.cache;

import org.apache.shiro.cache.Cache;

public interface ShiroCacheManager {

    
       
       
        
         Cache
        
        
         
          getCache(String name);

    void destroy();

}
        
        
       
       

5、session监听
package com.fangxin365.cms.cluster.listener;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fangxin365.cms.cluster.session.ShiroSessionRepository;

public class CustomSessionListener implements SessionListener {
	
	private static Logger logger = LoggerFactory.getLogger(CustomSessionListener.class);

	private ShiroSessionRepository shiroSessionRepository;

	/**
	 * 一个会话的生命周期开始
	 */
	@Override
	public void onStart(Session session) {
		logger.info("CustomSessionListener =====> onStart");
	}

	/**
	 * 一个会话的生命周期结束
	 */
	@Override
	public void onStop(Session session) {
		logger.info("CustomSessionListener =====> onStop");
	}

	@Override
	public void onExpiration(Session session) {
		logger.info("CustomSessionListener =====> onExpiration");
		shiroSessionRepository.deleteSession(session.getId());
	}

	// -----------------------//
	// Getter & Setter methods
	// -----------------------//
	public ShiroSessionRepository getShiroSessionRepository() {
		return shiroSessionRepository;
	}

	public void setShiroSessionRepository(ShiroSessionRepository shiroSessionRepository) {
		this.shiroSessionRepository = shiroSessionRepository;
	}

}

6、jedis管理
package com.fangxin365.cms.cluster.cache;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

import com.fangxin365.cms.cluster.session.JedisShiroSessionRepository;
import com.fangxin365.cms.cluster.utils.LoggerUtils;
import com.fangxin365.cms.cluster.utils.SerializeUtils;

public class JedisManager {
	
	private static Logger logger = LoggerFactory.getLogger(JedisManager.class);

	private JedisPool jedisPool;

	public Jedis getJedis() {
		Jedis jedis = null;
		try {
			jedis = getJedisPool().getResource();
		} catch (Exception e) {
			throw new JedisConnectionException(e);
		}
		return jedis;
	}

	public void returnResource(Jedis jedis, boolean isBroken) {
		if (jedis == null)
			return;
		jedis.close();
	}
	
	public void saveValueByKey(int dbIndex, byte[] key, byte[] value, int expireTime) throws Exception {
		logger.info("JedisManager =====> saveValueByKey");
		Jedis jedis = null;
		boolean isBroken = false;
		try {
			jedis = getJedis();
			jedis.select(dbIndex);
			jedis.set(key, value);
			if (expireTime > 0)
				jedis.expire(key, expireTime);
		} catch (Exception e) {
			isBroken = true;
			throw e;
		} finally {
			returnResource(jedis, isBroken);
		}
	}

	public byte[] getValueByKey(int dbIndex, byte[] key) throws Exception {
		logger.info("JedisManager =====> getValueByKey");
		Jedis jedis = null;
		byte[] result = null;
		boolean isBroken = false;
		try {
			jedis = getJedis();
			jedis.select(dbIndex);
			result = jedis.get(key);
		} catch (Exception e) {
			isBroken = true;
			throw e;
		} finally {
			returnResource(jedis, isBroken);
		}
		return result;
	}
	
	/**
	 * 获取所有Session
	 */
	public Collection
          
          
           
            getAllSession(int dbIndex, String redisShiroSession) throws Exception {
		logger.info("JedisManager =====> getAllSession");
		Jedis jedis = null;
		boolean isBroken = false;
		Set
           
           
            
             sessions = new HashSet
            
            
             
             ();
		try {
			jedis = getJedis();
			jedis.select(dbIndex);

			Set
             
             
              
               byteKeys = jedis.keys((JedisShiroSessionRepository.REDIS_SHIRO_ALL).getBytes());
			if (byteKeys != null && byteKeys.size() > 0) {
				for (byte[] bs : byteKeys) {
					Session obj = (Session)SerializeUtils.deserialize(jedis.get(bs));
					if (obj instanceof Session) {
						sessions.add(obj);
					}
				}
			}
		} catch (Exception e) {
			isBroken = true;
			throw e;
		} finally {
			returnResource(jedis, isBroken);
		}
		return sessions;
	}

	public void deleteByKey(int dbIndex, byte[] key) throws Exception {
		logger.info("JedisManager =====> deleteByKey");
		Jedis jedis = null;
		boolean isBroken = false;
		try {
			jedis = getJedis();
			jedis.select(dbIndex);
			Long result = jedis.del(key);
			LoggerUtils.fmtDebug(getClass(), "删除Session结果:%s", result);
		} catch (Exception e) {
			isBroken = true;
			throw e;
		} finally {
			returnResource(jedis, isBroken);
		}
	}
	
	// -----------------------//
	// Getter & Setter methods
	// -----------------------//
	public JedisPool getJedisPool() {
		return jedisPool;
	}

	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}
	
}
             
             
            
            
           
           
          
          

7、工具类
package com.fangxin365.cms.cluster.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wjw.kryo.wrapper.KryoSerializer;

public class SerializeUtils {

	private static Logger logger = LoggerFactory.getLogger(SerializeUtils.class);

	public static Object deserialize(byte[] bytes) {
		Object result = null;

		if (isEmpty(bytes)) {
			return null;
		}

		try {
			result = KryoSerializer.read(bytes);
		} catch (Exception e) {
			logger.error("Failed to deserialize", e);
		}
		return result;
	}

	public static byte[] serialize(Object object) {
		byte[] result = null;

		if (object == null) {
			return new byte[0];
		}

		try {
			result = KryoSerializer.write(object);
		} catch (Exception ex) {
			logger.error("Failed to serialize", ex);
		}
		return result;
	}

	public static boolean isEmpty(byte[] data) {
		return (data == null || data.length == 0);
	}

}
package com.fangxin365.cms.cluster.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * Log输出封装
 */
public class LoggerUtils {
	
	/**
	 * 是否开启Debug
	 */
	public static boolean isDebug = Logger.getLogger(LoggerUtils.class).isDebugEnabled();

	/**
	 * Debug 输出
	 * 
	 * @param clazz 目标.Class
	 * @param message 输出信息
	 */
	public static void debug(Class
             
              clazz, String message) {
		if (!isDebug)
			return;
		Logger logger = Logger.getLogger(clazz);
		logger.debug(message);
	}

	/**
	 * Debug 输出
	 * 
	 * @param clazz 目标.Class
	 * @param fmtString 输出信息key
	 * @param value 输出信息value
	 */
	public static void fmtDebug(Class
             
              clazz, String fmtString, Object... value) {
		if (!isDebug)
			return;
		if (StringUtils.isBlank(fmtString)) {
			return;
		}
		if (null != value && value.length != 0) {
			fmtString = String.format(fmtString, value);
		}
		debug(clazz, fmtString);
	}

	/**
	 * Error 输出
	 * 
	 * @param clazz 目标.Class
	 * @param message 输出信息
	 * @param e 异常类
	 */
	public static void error(Class
             
              clazz, String message, Exception e) {
		Logger logger = Logger.getLogger(clazz);
		if (null == e) {
			logger.error(message);
			return;
		}
		logger.error(message, e);
	}

	/**
	 * Error 输出
	 * 
	 * @param clazz 目标.Class
	 * @param message 输出信息
	 */
	public static void error(Class
             
              clazz, String message) {
		error(clazz, message, null);
	}

	/**
	 * 异常填充值输出
	 * 
	 * @param clazz 目标.Class
	 * @param fmtString 输出信息key
	 * @param e 异常类
	 * @param value 输出信息value
	 */
	public static void fmtError(Class
             
              clazz, Exception e, String fmtString, Object... value) {
		if (StringUtils.isBlank(fmtString)) {
			return;
		}
		if (null != value && value.length != 0) {
			fmtString = String.format(fmtString, value);
		}
		error(clazz, fmtString, e);
	}

	/**
	 * 异常填充值输出
	 * 
	 * @param clazz 目标.Class
	 * @param fmtString 输出信息key
	 * @param value 输出信息value
	 */
	public static void fmtError(Class
             
              clazz, String fmtString, Object... value) {
		if (StringUtils.isBlank(fmtString)) {
			return;
		}
		if (null != value && value.length != 0) {
			fmtString = String.format(fmtString, value);
		}
		error(clazz, fmtString);
	}
}

8、存储结果


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值