diff --git a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStore.java b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStore.java index 1ded35b..27cb7c9 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStore.java +++ b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStore.java @@ -30,6 +30,12 @@ import java.util.Set; */ public abstract class RedisCacheStore implements CacheStore { + private final RedisConnectionPool connectionPool; + + protected RedisCacheStore(RedisConnectionPool connectionPool) { + this.connectionPool = connectionPool; + } + /** * 获取 Key 前缀. *

key = getKeyPrefix() + key @@ -49,7 +55,7 @@ public abstract class RedisCacheStore implements CacheStore { @Override public boolean setTimeToLive(CacheKey key, long ttl) { String keyString = getKeyString(key); - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { Long result; if (ttl >= 0) { result = jedis.pexpire(keyString, ttl); @@ -62,7 +68,7 @@ public abstract class RedisCacheStore implements CacheStore { @Override public long getTimeToLive(CacheKey key) { - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { Long ttl = jedis.pttl(getKeyString(key)); return ttl < 0 ? -1 : ttl; }); @@ -70,27 +76,27 @@ public abstract class RedisCacheStore implements CacheStore { @Override public long size() { - return RedisConnectionPool.executeRedis(Jedis::dbSize); + return connectionPool.executeRedis(Jedis::dbSize); } @Override public boolean clear() { - return RedisConnectionPool.executeRedis(jedis -> RedisUtils.isOk(jedis.flushDB())); + return connectionPool.executeRedis(jedis -> RedisUtils.isOk(jedis.flushDB())); } @Override public boolean exists(CacheKey key) { - return RedisConnectionPool.executeRedis(jedis -> jedis.exists(getKeyString(key))); + return connectionPool.executeRedis(jedis -> jedis.exists(getKeyString(key))); } @Override public boolean remove(CacheKey key) { - return RedisConnectionPool.executeRedis(jedis -> jedis.del(getKeyString(key)) == RedisUtils.RETURN_CODE_OK); + return connectionPool.executeRedis(jedis -> jedis.del(getKeyString(key)) == RedisUtils.RETURN_CODE_OK); } @Override public Set keySet() { - Set keys = RedisConnectionPool.executeRedis(jedis -> jedis.keys(RedisUtils.KEY_PATTERN_ALL)); + Set keys = connectionPool.executeRedis(jedis -> jedis.keys(RedisUtils.KEY_PATTERN_ALL)); final int prefixLength = getKeyPrefix().length(); Set newKeys = new HashSet<>(); for (String key : keys) { diff --git a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStoreFactory.java b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStoreFactory.java index c3a28f5..dab1ebd 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStoreFactory.java +++ b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisCacheStoreFactory.java @@ -47,6 +47,8 @@ public class RedisCacheStoreFactory implements CacheStoreFactory { private final static String PROP_DATABASE = "redis.databaseId"; private final static String PROP_CLIENT_NAME = "redis.clientName"; + private final RedisConnectionPool connectionPool = new RedisConnectionPool(); + @Override public void initial(File dataDirectory) { final File propertiesFile = new File(dataDirectory, "redis.properties"); @@ -75,7 +77,7 @@ public class RedisCacheStoreFactory implements CacheStoreFactory { Integer.parseInt(properties.getProperty(PROP_PORT, "6379")), queryString); - RedisConnectionPool.setConnectionUrl(url); + connectionPool.setConnectionUrl(url); } catch (MalformedURLException e) { log.error("构造连接 URL 时发生异常", e); } @@ -83,7 +85,7 @@ public class RedisCacheStoreFactory implements CacheStoreFactory { @Override public SingleCacheStore newSingleCacheStore(String identify, StringConverter converter) { - return new RedisSingleCacheStore<>(identify, converter); + return new RedisSingleCacheStore<>(connectionPool, identify, converter); } @Override @@ -98,11 +100,11 @@ public class RedisCacheStoreFactory implements CacheStoreFactory { @Override public MapCacheStore newMapCacheStore(String identify, StringConverter converter) { - return new RedisMapCacheStore<>(identify, converter); + return new RedisMapCacheStore<>(connectionPool, identify, converter); } @Override public boolean canGetCacheStore() { - return RedisConnectionPool.available(); + return connectionPool.available(); } } diff --git a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisConnectionPool.java b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisConnectionPool.java index be127b7..f2ba3a7 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisConnectionPool.java +++ b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisConnectionPool.java @@ -34,16 +34,17 @@ import java.util.function.Function; class RedisConnectionPool { private final static Logger log = LoggerFactory.getLogger(RedisConnectionPool.class); - private final static AtomicReference POOL = new AtomicReference<>(); - private final static AtomicReference CONNECTION_URL = new AtomicReference<>(); - public static synchronized void setConnectionUrl(URL connectionUrl) { + private final AtomicReference POOL = new AtomicReference<>(); + private final AtomicReference CONNECTION_URL = new AtomicReference<>(); + + public synchronized void setConnectionUrl(URL connectionUrl) { if(CONNECTION_URL.get() != null) { CONNECTION_URL.set(connectionUrl); } } - public static synchronized void reconnectRedis() { + public synchronized void reconnectRedis() { JedisPool jedisPool = POOL.get(); if (jedisPool != null && !jedisPool.isClosed()) { return; @@ -66,7 +67,7 @@ class RedisConnectionPool { *

注意, 需回收 Jedis 对象, 否则可能会耗尽连接池导致后续操作受到影响. * @return 返回可用的 Jedis 连接. */ - public static Jedis getConnection() { + public Jedis getConnection() { JedisPool pool = POOL.get(); if (pool == null || pool.isClosed()) { reconnectRedis(); @@ -85,7 +86,7 @@ class RedisConnectionPool { * @param 返回值类型. * @return 返回 function 返回的内容. */ - public static R executeRedis(Function function) { + public R executeRedis(Function function) { try (Jedis jedis = getConnection()) { return function.apply(jedis); } @@ -95,7 +96,7 @@ class RedisConnectionPool { * 检查 Redis 连接池是否有可用的资源. * @return 如果连接池依然活跃, 返回 true. */ - public static boolean available() { + public boolean available() { JedisPool jedisPool = POOL.get(); if (jedisPool == null || jedisPool.isClosed()) { reconnectRedis(); diff --git a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStore.java b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStore.java index 74c6dc5..bf60aa4 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStore.java +++ b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStore.java @@ -33,8 +33,11 @@ public class RedisMapCacheStore extends RedisCacheStore> imple private final String keyPrefix; private final StringConverter converter; + private final RedisConnectionPool connectionPool; - public RedisMapCacheStore(String keyPrefix, StringConverter converter) { + public RedisMapCacheStore(RedisConnectionPool connectionPool, String keyPrefix, StringConverter converter) { + super(connectionPool); + this.connectionPool = connectionPool; keyPrefix = Strings.nullToEmpty(keyPrefix).trim(); if (!keyPrefix.isEmpty() && keyPrefix.endsWith(RedisUtils.KEY_SEPARATOR)) { this.keyPrefix = keyPrefix; @@ -52,7 +55,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple @Override public int mapSize(CacheKey key) { - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); if (jedis.exists(keyString)) { return jedis.hlen(keyString).intValue(); @@ -63,7 +66,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple @Override public Set mapFieldSet(CacheKey key) { - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); if (jedis.exists(keyString)) { return jedis.hkeys(keyString); @@ -74,7 +77,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple @Override public Set mapValueSet(CacheKey key) { - List rawValueSet = RedisConnectionPool.executeRedis(jedis -> { + List rawValueSet = connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); if (jedis.exists(keyString)) { return jedis.hvals(keyString); @@ -97,7 +100,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple public boolean put(CacheKey key, String field, V value) { Objects.requireNonNull(field); Objects.requireNonNull(value); - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); return jedis.hset(keyString, field, converter.to(value)) == RedisUtils.RETURN_CODE_OK; }); @@ -113,7 +116,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple final Map targetMap = new HashMap<>(map.size()); map.forEach((k, v) -> targetMap.put(k, converter.to(v))); - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); return RedisUtils.isOk(jedis.hmset(keyString, targetMap)); }); @@ -123,7 +126,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple public boolean putIfNotExist(CacheKey key, String field, V value) { Objects.requireNonNull(field); Objects.requireNonNull(value); - return RedisConnectionPool.executeRedis(jedis -> { + return connectionPool.executeRedis(jedis -> { String keyString = getKeyString(key); return jedis.hsetnx(keyString, field, converter.to(value)) == RedisUtils.RETURN_CODE_OK; }); @@ -132,7 +135,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple @Override public V get(CacheKey key, String field) { Objects.requireNonNull(field); - String value = RedisConnectionPool.executeRedis(jedis -> jedis.hget(getKeyString(key), field)); + String value = connectionPool.executeRedis(jedis -> jedis.hget(getKeyString(key), field)); if (value == null) { return null; } @@ -142,14 +145,14 @@ public class RedisMapCacheStore extends RedisCacheStore> imple @Override public boolean removeField(CacheKey key, String field) { Objects.requireNonNull(field); - return RedisConnectionPool.executeRedis(jedis -> + return connectionPool.executeRedis(jedis -> jedis.hdel(getKeyString(key), field) == RedisUtils.RETURN_CODE_OK); } @Override public boolean containsField(CacheKey key, String field) { Objects.requireNonNull(field); - return RedisConnectionPool.executeRedis(jedis -> jedis.hexists(getKeyString(key), field)); + return connectionPool.executeRedis(jedis -> jedis.hexists(getKeyString(key), field)); } @Override @@ -168,7 +171,7 @@ public class RedisMapCacheStore extends RedisCacheStore> imple String[] fieldsArray = new String[fields.size()]; fields.toArray(fieldsArray); - return RedisConnectionPool.executeRedis(jedis -> + return connectionPool.executeRedis(jedis -> jedis.hdel(getKeyString(key), fieldsArray) != RedisUtils.RETURN_CODE_FAILED); } diff --git a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStore.java b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStore.java index 253eb75..6f2f4db 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStore.java +++ b/ContentGrabbingJi-CacheStore-redis/src/main/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStore.java @@ -36,8 +36,11 @@ public class RedisSingleCacheStore extends RedisCacheStore implements Sing private final String keyPrefix; private final StringConverter converter; + private final RedisConnectionPool connectionPool; - public RedisSingleCacheStore(String keyPrefix, StringConverter converter) { + public RedisSingleCacheStore(RedisConnectionPool connectionPool, String keyPrefix, StringConverter converter) { + super(connectionPool); + this.connectionPool = connectionPool; keyPrefix = Strings.nullToEmpty(keyPrefix).trim(); if (!keyPrefix.isEmpty() && keyPrefix.endsWith(RedisUtils.KEY_SEPARATOR)) { this.keyPrefix = keyPrefix; @@ -50,20 +53,20 @@ public class RedisSingleCacheStore extends RedisCacheStore implements Sing @Override public boolean set(CacheKey key, V value) { - return RedisConnectionPool.executeRedis(jedis -> + return connectionPool.executeRedis(jedis -> RedisUtils.isOk(jedis.set(getKeyString(key), converter.to(Objects.requireNonNull(value))))); } @Override public boolean setIfNotExist(CacheKey key, V value) { - return RedisConnectionPool.executeRedis(jedis -> + return connectionPool.executeRedis(jedis -> jedis.setnx(getKeyString(key), converter.to(Objects.requireNonNull(value))) == RedisUtils.RETURN_CODE_OK); } @Override public V get(CacheKey key) { - String value = RedisConnectionPool.executeRedis(jedis -> jedis.get(getKeyString(key))); + String value = connectionPool.executeRedis(jedis -> jedis.get(getKeyString(key))); if (value == null) { return null; } diff --git a/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStoreTest.java b/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStoreTest.java index f577829..dde72d1 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStoreTest.java +++ b/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisMapCacheStoreTest.java @@ -18,6 +18,7 @@ package net.lamgc.cgj.bot.cache.redis; +import com.google.common.base.Throwables; import net.lamgc.cgj.bot.cache.CacheKey; import net.lamgc.cgj.bot.cache.MapCacheStore; import net.lamgc.cgj.bot.cache.convert.StringToStringConverter; @@ -25,7 +26,9 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -34,8 +37,24 @@ import java.util.Map; */ public class RedisMapCacheStoreTest { - private final static MapCacheStore cacheStore = - new RedisMapCacheStore<>("test", new StringToStringConverter()); + private final static RedisCacheStoreFactory factory; + private final static TemporaryFolder tempFolder = TemporaryFolder.builder().build(); + + static { + try { + tempFolder.create(); + } catch (IOException e) { + Assert.fail(Throwables.getStackTraceAsString(e)); + } + factory = new RedisCacheStoreFactory(); + try { + factory.initial(tempFolder.newFolder("cache-redis")); + } catch (IOException e) { + Assert.fail(Throwables.getStackTraceAsString(e)); + } + } + + private final static MapCacheStore cacheStore = factory.newMapCacheStore("test", new StringToStringConverter()); @Before public void before() { diff --git a/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStoreTest.java b/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStoreTest.java index 031487c..9ad56cf 100644 --- a/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStoreTest.java +++ b/ContentGrabbingJi-CacheStore-redis/src/test/java/net/lamgc/cgj/bot/cache/redis/RedisSingleCacheStoreTest.java @@ -17,13 +17,16 @@ package net.lamgc.cgj.bot.cache.redis; +import com.google.common.base.Throwables; import net.lamgc.cgj.bot.cache.CacheKey; import net.lamgc.cgj.bot.cache.SingleCacheStore; import net.lamgc.cgj.bot.cache.convert.StringToStringConverter; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -33,7 +36,24 @@ import java.util.Map; */ public class RedisSingleCacheStoreTest { - private final static SingleCacheStore cacheStore = new RedisSingleCacheStore<>("test", new StringToStringConverter()); + private final static RedisCacheStoreFactory factory; + private final static TemporaryFolder tempFolder = TemporaryFolder.builder().build(); + + static { + try { + tempFolder.create(); + } catch (IOException e) { + Assert.fail(Throwables.getStackTraceAsString(e)); + } + factory = new RedisCacheStoreFactory(); + try { + factory.initial(tempFolder.newFolder("cache-redis")); + } catch (IOException e) { + Assert.fail(Throwables.getStackTraceAsString(e)); + } + } + + private final static SingleCacheStore cacheStore = factory.newSingleCacheStore("test", new StringToStringConverter()); @Before public void before() { @@ -42,8 +62,7 @@ public class RedisSingleCacheStoreTest { @Test public void nullThrowTest() { - final SingleCacheStore tempCacheStore = - new RedisSingleCacheStore<>("test" + RedisUtils.KEY_SEPARATOR, new StringToStringConverter()); + final SingleCacheStore tempCacheStore = factory.newSingleCacheStore("test" + RedisUtils.KEY_SEPARATOR, new StringToStringConverter()); final CacheKey key = new CacheKey("testKey"); // RedisSingleCacheStore