shiro使用redis实现cache管理

本文详细介绍了如何使用Redis替代Shiro默认的EhCache作为缓存实现,包括自定义ShiroCache、RedisCacheManager的实现过程及配置示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shiro使用redis实现cache

Shiro默认整合了EhCache,来实现缓存,如果我们想用redis替换EhCache来实现缓存怎么做了?我们可以从Shiro的源码来找到一些端倪。

参考代码
https://github.com/gemingyi/shiro_demo

先找到shiro realm类的setCacheManager()方法,可以看到传入参数CacheManager。

到这里我们就知道CacheManager接口就行了。

CacheManager接口,该接口很简单,只有一个方法:

这个接口需要一个Cache,通过name来获取Cache,首先,我们来实现CacheManager这个接口。

public class RedisCacheManager implements CacheManager {
    private long cacheLive;    //cache存活时间
    private String cacheKeyPrefix;      //cache前缀
    private RedisTemplate redisTemplate;

    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        Cache cache = this.caches.get(name);
        if (cache == null) {
            //自定义shiroCache
            cache = new ShiroRedisCache<K, V>(redisTemplate, cacheLive, cacheKeyPrefix);
            this.caches.put(name, cache);
        }
        return cache;
    }

    public void setCacheLive(long cacheLive) {
        this.cacheLive = cacheLive;
    }

    public void setCacheKeyPrefix(String cacheKeyPrefix) {
        this.cacheKeyPrefix = cacheKeyPrefix;
    }

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
}

 我们在看看这个Cache接口:

 

我们使用redis实现(我这里使用的是RedisTemplate),下面是ShiroRedisCache代码:

public class ShiroRedisCache<K, V> implements Cache<K, V> {
    private long cacheLive;
    private String cacheKeyPrefix;
    private RedisTemplate redisTemplate;


    @Override
    public V get(K k) throws CacheException {
        return (V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(k));
    }

    @Override
    public V put(K k, V v) throws CacheException {
        redisTemplate.opsForValue().set(this.getRedisCacheKey(k), v, cacheLive, TimeUnit.MINUTES);
        return v;
    }

    @Override
    public V remove(K k) throws CacheException {
        V obj = (V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(k));
        redisTemplate.delete(this.getRedisCacheKey(k));
        return obj;
    }

    @Override
    public void clear() throws CacheException {
        Set keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
        if (null != keys && keys.size() > 0) {
            Iterator itera = keys.iterator();
            this.redisTemplate.delete(itera.next());
        }
    }

    @Override
    public int size() {
        Set<K> keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
        return keys.size();
    }

    @Override
    public Set<K> keys() {
        return this.redisTemplate.keys(this.cacheKeyPrefix + "*");
    }


    @Override
    public Collection<V> values() {
        Set<K> keys = this.redisTemplate.keys(this.cacheKeyPrefix + "*");
        Set<V> values = new HashSet<V>(keys.size());
        for (K key : keys) {
            values.add((V) this.redisTemplate.opsForValue().get(this.getRedisCacheKey(key)));
        }
        return values;
    }

    private String getRedisCacheKey(K key) {
        Object redisKey = this.getStringRedisKey(key);
        if (redisKey instanceof String) {
            return this.cacheKeyPrefix + redisKey;
        } else {
            return String.valueOf(redisKey);
        }
    }

    private Object getStringRedisKey(K key) {
        Object redisKey;
        if (key instanceof PrincipalCollection) {
            redisKey = this.getRedisKeyFromPrincipalCollection((PrincipalCollection) key);
        } else {
            redisKey = key.toString();
        }
        return redisKey;
    }

    private Object getRedisKeyFromPrincipalCollection(PrincipalCollection key) {
        List realmNames = this.getRealmNames(key);
        Collections.sort(realmNames);
        Object redisKey = this.joinRealmNames(realmNames);
        return redisKey;
    }

    private List<String> getRealmNames(PrincipalCollection key) {
        ArrayList realmArr = new ArrayList();
        Set realmNames = key.getRealmNames();
        Iterator i$ = realmNames.iterator();
        while (i$.hasNext()) {
            String realmName = (String) i$.next();
            realmArr.add(realmName);
        }
        return realmArr;
    }

    private Object joinRealmNames(List<String> realmArr) {
        StringBuilder redisKeyBuilder = new StringBuilder();
        for (int i = 0; i < realmArr.size(); ++i) {
            String s = realmArr.get(i);
            redisKeyBuilder.append(s);
        }
        String redisKey = redisKeyBuilder.toString();
        return redisKey;
    }

    public ShiroRedisCache(RedisTemplate redisTemplate, long cacheLive, String cachePrefix) {
        this.redisTemplate = redisTemplate;
        this.cacheLive = cacheLive;
        this.cacheKeyPrefix = cachePrefix;
    }
}

 

最后贴一下ShiroConfiguration代码:

@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
    RedisCacheManager redisCacheManager = new RedisCacheManager();
    //cache过期时间及前缀
    redisCacheManager.setCacheLive(cacheLive);
    redisCacheManager.setCacheKeyPrefix(cachePrefix);
    redisCacheManager.setRedisTemplate(redisTemplate);
    return redisCacheManager;
}
@Bean(name = "securityManager")
public SecurityManager securityManager(SessionManager sessionManager, RedisCacheManager redisCacheManager) {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    securityManager.setRealm(myRealm());
    // 自定义session管理 使用redis
    securityManager.setSessionManager(sessionManager);
    // 自定义缓存实现 使用redis
    securityManager.setCacheManager(redisCacheManager);
    return securityManager;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值