org.iherus.shiro.cache.redis.RedisCacheManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of shiro-redis Show documentation
Show all versions of shiro-redis Show documentation
Shiro cache Integration Adapter.
/**
* Copyright (c) 2016-2019, Bosco.Liao ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.iherus.shiro.cache.redis;
import static org.iherus.shiro.cache.redis.Constant.DEFAULT_CACHE_EXPIRATION;
import static org.iherus.shiro.cache.redis.Constant.DEFAULT_CACHE_KEY_PREFIX;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
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.util.Destroyable;
import org.apache.shiro.util.Initializable;
import org.iherus.shiro.cache.redis.AbstractRedisOperations.DefaultRedisOperations;
import org.iherus.shiro.cache.redis.connection.BatchOptions;
import org.iherus.shiro.cache.redis.connection.RedisConnectionFactory;
import org.iherus.shiro.cache.redis.connection.jedis.JedisConnectionFactory;
import org.iherus.shiro.cache.redis.connection.lettuce.LettuceConnectionFactory;
import org.iherus.shiro.cache.redis.connection.redisson.RedissonConnectionFactory;
import org.iherus.shiro.cache.redis.connection.spring.CompatibleRedisConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 缓存管理器
* Description:管理缓存池的初始化、获取当前缓存对象和销毁缓存池
*
* @author Bosco.Liao
* @since 1.0.0
*/
public class RedisCacheManager implements CacheManager, Initializable, Destroyable {
private static final Logger logger = LoggerFactory.getLogger(RedisCacheManager.class);
@SuppressWarnings("rawtypes")
private static final ConcurrentHashMap LOCAL_CACHE = new ConcurrentHashMap<>();
@SuppressWarnings("serial")
private static final Map SCOPE_MAPPER = new HashMap() {{
put("Session", "session:");
put("Authorization", "authz:");
put("Authentication", "authc:");
}};
private final BatchOptions.Builder optionsBuilder = BatchOptions.builder();
/**
* Set a Default key prefix for all caches.
*/
private String keyPrefix = DEFAULT_CACHE_KEY_PREFIX;
/**
* Cache object expiration time.
*/
private Duration expiration = DEFAULT_CACHE_EXPIRATION;
/**
* The cached object is stored in this database, but this property is invalid in {@literal Redis-Cluster}.
*/
private Integer database;
/**
* RedisConnectionFactory instance.
*
* @see JedisConnectionFactory
* @see LettuceConnectionFactory
* @see RedissonConnectionFactory
* @see CompatibleRedisConnectionFactory
*/
private RedisConnectionFactory connectionFactory;
public String getKeyPrefix() {
return keyPrefix;
}
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
public Duration getExpiration() {
return expiration;
}
public void setExpiration(Duration expiration) {
this.expiration = expiration;
}
public void setExpirationMillis(long expiration) {
this.expiration = Duration.ofMillis(expiration);
}
public RedisConnectionFactory getConnectionFactory() {
return connectionFactory;
}
protected RedisConnectionFactory getRequiredConnectionFactory() {
RedisConnectionFactory factory = getConnectionFactory();
if (factory == null) {
throw new CacheException("RedisConnectionFactory must not be null.");
}
return factory;
}
/**
* Setting RedisConnectionFactory instance.
*
* @param connectionFactory RedisConnectionFactory instance.
*
* @see JedisConnectionFactory
* @see LettuceConnectionFactory
* @see CompatibleRedisConnectionFactory
*/
public void setConnectionFactory(RedisConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public Integer getDatabase() {
return database;
}
/**
* Sets shiro's cache to store the database.
*/
public void setDatabase(Integer database) {
if (getRequiredConnectionFactory() instanceof CompatibleRedisConnectionFactory) {
throw new UnsupportedOperationException(
"CompatibleRedisConnectionFactory instance does not support this method.");
}
this.database = database;
}
public BatchOptions.Builder setScanBatchSize(int size) {
return optionsBuilder.scanSize(size);
}
public BatchOptions.Builder setDeleteBatchSize(int size) {
return optionsBuilder.deleteSize(size);
}
public BatchOptions.Builder setFetchBatchSize(int size) {
return optionsBuilder.fetchSize(size);
}
@Override
public void init() throws ShiroException {
if (logger.isInfoEnabled()) {
logger.info("Shiro CacheManager initializing...");
}
RedisConnectionFactory factory = getRequiredConnectionFactory();
/**
* Bug fixed.
*/
BatchOptions options = this.optionsBuilder.build();
if (!BatchOptions.defaulted.equals(options)) {
factory.setBatchOptions(options);
}
try {
if (connectionFactory instanceof org.iherus.shiro.cache.redis.connection.Initializable) {
((org.iherus.shiro.cache.redis.connection.Initializable) connectionFactory).init();
}
} catch (Exception e) {
throw new CacheException(e);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Cache getCache(String name) throws CacheException {
Cache cache = LOCAL_CACHE.get(name);
if (cache == null) {
String scope = tryGetScope();
DefaultRedisOperations operations = new DefaultRedisOperations(getRequiredConnectionFactory());
cache = new RedisCache(name, operations, keyPrefix + scope, expiration, database);
LOCAL_CACHE.put(name, cache);
}
return cache;
}
@Override
public void destroy() throws Exception {
if (logger.isInfoEnabled()) {
logger.info("Shiro CacheManager destroying...");
}
try {
if (connectionFactory instanceof org.iherus.shiro.cache.redis.connection.Destroyable) {
((org.iherus.shiro.cache.redis.connection.Destroyable) connectionFactory).destroy();
}
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Unable to destroy connectionFactory instance gracefully and ignore it. (shutting down) ");
}
throw new CacheException(e);
}
}
/**
* Since 2.2.0
*/
private static String tryGetScope() {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
if (elements.length < 4) {
return "";
}
String methodName = elements[3].getMethodName();
for (Entry entry : SCOPE_MAPPER.entrySet()) {
if (methodName.contains(entry.getKey())) {
return entry.getValue();
}
}
return "";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy