1. 程式人生 > >我的shiro之旅-session共享-redis

我的shiro之旅-session共享-redis


import org.apache.shiro.ShiroException;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MapCache;
import org.apache.shiro.util.Destroyable;
import org.apache.shiro.util.Initializable;
import org.apache.shiro.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedisPool;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;




public class RedisCacheManager implements CacheManager, Destroyable {
    private static final Logger logger = LoggerFactory.getLogger(RedisCacheManager.class);


    // fast lookup by name map
    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();


    private RedisManager redisManager;


    /**
     * The Redis key prefix for caches
     */
    private String keyPrefix = "shiro_redis_cache:";


    /**
     * Returns the Redis session keys
     * prefix.
     *
     * @return The prefix
     */
    public String getKeyPrefix() {
        return keyPrefix;
    }


    /**
     * Sets the Redis sessions key
     * prefix.
     *
     * @param keyPrefix The prefix
     */
    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }


    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        logger.debug("獲取名稱為: " + name + " 的RedisCache例項");


        Cache c = caches.get(name);


        if (c == null) {


            // initialize the Redis manager instance
            redisManager.init();


            // create a new cache instance
            c = new RedisCache<K, V>(redisManager, keyPrefix);


            // add it to the cache collection
            caches.put(name, c);
        }
        return c;
    }


    public RedisManager getRedisManager() {
        return redisManager;
    }


    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;
    }


    @Override
    public void destroy() throws Exception {
        this.redisManager.destroy();
    }
}

RedisCache.java
package com.zte.alm.cs.ui.shiro.redis;
package com.zte.alm.cs.ui.shiro.redis;


import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.SerializationUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;


import java.util.*;


public class RedisCache<K, V> implements Cache<K, V> {
    private Logger logger = LoggerFactory.getLogger(this.getClass());


    /**
     * The wrapped Jedis instance.
     */
    private RedisManager cache;


    /**
     * The Redis key prefix for the sessions
     */
    private String keyPrefix = "shiro_session:";


    /**
     * Returns the Redis session keys
     * prefix.
     * @return The prefix
     */
    public String getKeyPrefix() {
        return keyPrefix;
    }


    /**
     * Sets the Redis sessions key
     * prefix.
     * @param keyPrefix The prefix
     */
    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }


    /**
     * 通過一個JedisManager例項構造RedisCache
     */
    public RedisCache(RedisManager cache) {
        if (cache == null) {
            throw new IllegalArgumentException("Cache argument cannot be null.");
        }
        this.cache = cache;
    }


    /**
     * Constructs a cache instance with the specified
     * Redis manager and using a custom key prefix.
     * @param cache The cache manager instance
     * @param prefix The Redis key prefix
     */
    public RedisCache(RedisManager cache, String prefix) {


        this(cache);


        // set the prefix
        this.keyPrefix = prefix;
    }


    /**
     * 獲得byte[]型的key
     * @param key
     * @return
     */
    private byte[] getByteKey(K key) {
        if (key instanceof String) {
            String preKey = this.keyPrefix + key;
            return preKey.getBytes();
        } else if(key instanceof PrincipalCollection){
            String preKey = this.keyPrefix + key.toString();
            return preKey.getBytes();
        }else{
            return SerializationUtils.serialize(key);
        }
    }


    @Override
    public V get(K key) throws CacheException {
        logger.debug("根據key從Redis中獲取物件 key [" + key + "]");
        try {
            if (key == null) {
                return null;
            } else {
                byte[] rawValue = cache.get(getByteKey(key));
                @SuppressWarnings("unchecked")
                V value = (V) SerializationUtils.deserialize(rawValue);
                return value;
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }


    }
    public String getStr(String key) throws CacheException {
        logger.debug("根據key從Redis中獲取物件 key [" + key + "]");
        try {
            if (key == null) {
                return null;
            } else {
                return cache.get(key);
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }


    }


    @Override
    public V put(K key, V value) throws CacheException {
        logger.debug("根據key從儲存 key [" + key + "]");
        try {
            cache.set(getByteKey(key), SerializationUtils.serialize(value));
            return value;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    public String putStr(String key, String value) throws CacheException {
        logger.debug("根據key從儲存 key [" + key + "]");
        try {
            cache.set(key, value);
            return value;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    public String put(String key,String value, int expire) throws CacheException {
        logger.debug("根據key從儲存 key [" + key + "]");
        try {
            cache.set(key, value, expire);
            return value;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    public String removeString(String key) throws CacheException {
        logger.debug("從redis中刪除 key [" + key + "]");
        try {
            String previous = cache.get(key);
            cache.del(key);
            return previous;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    @Override
    public V remove(K key) throws CacheException {
        logger.debug("從redis中刪除 key [" + key + "]");
        try {
            V previous = get(key);
            cache.del(getByteKey(key));
            return previous;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    @Override
    public void clear() throws CacheException {
        logger.debug("從redis中刪除所有元素");
        try {
            cache.flushDB();
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    @Override
    public int size() {
        try {
            Long longSize = new Long(cache.dbSize());
            return longSize.intValue();
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    @SuppressWarnings("unchecked")
    @Override
    public Set<K> keys() {
        try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (CollectionUtils.isEmpty(keys)) {
                return Collections.emptySet();
            } else {
                Set<K> newKeys = new HashSet<K>();
                for (byte[] key : keys) {
                    newKeys.add((K) key);
                }
                return newKeys;
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


    @Override
    public Collection<V> values() {
        try {
            Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
            if (!CollectionUtils.isEmpty(keys)) {
                List<V> values = new ArrayList<V>(keys.size());
                for (byte[] key : keys) {
                    @SuppressWarnings("unchecked") V value = get((K) key);
                    if (value != null) {
                        values.add(value);
                    }
                }
                return Collections.unmodifiableList(values);
            } else {
                return Collections.emptyList();
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }


}