shiro
提供基于ehcache
的缓存实现,参照相关的实现类,我们可以自定义基于redis
的缓存实现。
ehcache实现
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.0</version>
</dependency>
自定义cacheManager
/**
* 缓存管理器
*
* @param jdkRedisTemplate shiro的对象总是有这样那样的问题,所以 redisTemplate 使用 {@link org.springframework.data.redis.serializer.JdkSerializationRedisSerializer} 序列化值
* @return object
*/
@Bean
public CacheManager shiroRedisCacheManager(JdkRedisTemplate jdkRedisTemplate) {
return new CacheManager() {
@Override
public <K, V> Cache<K, V> getCache(String s) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache manager get cache. name={} ", s);
}
return new Cache<K, V>() {
@Override
public V get(K k) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache get.{} K={}", s, k);
}
return ((V) jdkRedisTemplate.opsForValue().get(generateCacheKey(s, k)));
}
/**
* put
* 设置默认过期时间
*
* @param k k
* @param v v
* @return object
* @throws CacheException cacheexception
*/
@Override
public V put(K k, V v) throws CacheException {
log.debug("shiro redis cache put.{} K={} V={}", s, k, v);
V result = (V) jdkRedisTemplate.opsForValue().get(generateCacheKey(s, k));
jdkRedisTemplate.opsForValue().set(generateCacheKey(s, k), v, 1800000, TimeUnit.MILLISECONDS);
return result;
}
@Override
public V remove(K k) throws CacheException {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache remove.{} K={}", s, k);
}
V result = (V) jdkRedisTemplate.opsForValue().get(generateCacheKey(s, k));
jdkRedisTemplate.delete(generateCacheKey(s, k));
return result;
}
/**
* clear
* <p>
*
* @throws CacheException cacheexception
*/
@Override
public void clear() throws CacheException {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache clear.{}", s);
}
RedisConnection redisConnection = jdkRedisTemplate.getConnectionFactory().getConnection();
Assert.notNull(redisConnection, "redisConnection is null");
try (Cursor<byte[]> cursor = redisConnection.scan(ScanOptions.scanOptions()
.match(generateCacheKey(s, "*"))
.count(Integer.MAX_VALUE)
.build())) {
while (cursor.hasNext()) {
redisConnection.del(cursor.next());
}
} catch (IOException e) {
log.error("shiro redis cache clear exception", e);
}
}
@Override
public int size() {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache size.{}", s);
}
AtomicInteger count = new AtomicInteger(0);
RedisConnection redisConnection = jdkRedisTemplate.getConnectionFactory().getConnection();
Assert.notNull(redisConnection, "redisConnection is null");
try (Cursor<byte[]> cursor = redisConnection.scan(ScanOptions.scanOptions()
.match(generateCacheKey(s, "*"))
.count(Integer.MAX_VALUE)
.build())) {
while (cursor.hasNext()) {
count.getAndIncrement();
}
} catch (IOException e) {
log.error("shiro redis cache size exception", e);
}
return count.get();
}
@Override
public Set<K> keys() {
if (log.isDebugEnabled()) {
log.debug("shiro redis cache keys.{}", s);
}
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
Set<K> keys = new HashSet<>();
RedisConnection redisConnection = jdkRedisTemplate.getConnectionFactory().getConnection();
Assert.notNull(redisConnection, "redisConnection is null");
try (Cursor<byte[]> cursor = redisConnection.scan(ScanOptions.scanOptions()
.match(generateCacheKey(s, "*"))
.count(Integer.MAX_VALUE)
.build())) {
while (cursor.hasNext()) {
keys.add((K) stringRedisSerializer.deserialize(cursor.next()));
}
} catch (IOException e) {
log.error("shiro redis cache keys exception", e);
}
return keys;
}
@Override
public Collection<V> values() {
return null;
}
};
}
};
}