|
@@ -1,17 +1,24 @@
|
|
|
package com.takai.common.core.redis;
|
|
package com.takai.common.core.redis;
|
|
|
|
|
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.data.redis.connection.Message;
|
|
|
|
|
+import org.springframework.data.redis.connection.MessageListener;
|
|
|
|
|
+import org.springframework.data.redis.core.BoundSetOperations;
|
|
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
|
+import org.springframework.data.redis.listener.ChannelTopic;
|
|
|
|
|
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
|
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
|
+
|
|
|
|
|
+import javax.annotation.PreDestroy;
|
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
|
import java.util.Iterator;
|
|
import java.util.Iterator;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
-import org.springframework.data.redis.core.BoundSetOperations;
|
|
|
|
|
-import org.springframework.data.redis.core.HashOperations;
|
|
|
|
|
-import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
|
-import org.springframework.data.redis.core.ValueOperations;
|
|
|
|
|
-import org.springframework.stereotype.Component;
|
|
|
|
|
|
|
+import java.util.function.Consumer;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* spring redis 工具类
|
|
* spring redis 工具类
|
|
@@ -25,244 +32,232 @@ public class RedisCache
|
|
|
@Autowired
|
|
@Autowired
|
|
|
public RedisTemplate redisTemplate;
|
|
public RedisTemplate redisTemplate;
|
|
|
|
|
|
|
|
|
|
+ // 手动创建的监听器容器
|
|
|
|
|
+ private RedisMessageListenerContainer listenerContainer;
|
|
|
|
|
+
|
|
|
|
|
+ // 存储订阅关系
|
|
|
|
|
+ private final Map<String, MessageListener> listeners = new ConcurrentHashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 订阅线程池(核心:解决subscriptionExecutor为null问题)
|
|
|
|
|
+ private ThreadPoolTaskExecutor subscriptionExecutor;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
- * 缓存基本的对象,Integer、String、实体类等
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存的键值
|
|
|
|
|
- * @param value 缓存的值
|
|
|
|
|
|
|
+ * 初始化订阅线程池(Spring风格,避免硬编码)
|
|
|
*/
|
|
*/
|
|
|
- public <T> void setCacheObject(final String key, final T value)
|
|
|
|
|
- {
|
|
|
|
|
- redisTemplate.opsForValue().set(key, value);
|
|
|
|
|
|
|
+ private void initSubscriptionExecutor() {
|
|
|
|
|
+ if (subscriptionExecutor == null) {
|
|
|
|
|
+ subscriptionExecutor = new ThreadPoolTaskExecutor();
|
|
|
|
|
+ // 线程池核心参数(可根据业务调优)
|
|
|
|
|
+ subscriptionExecutor.setCorePoolSize(5); // 核心线程数
|
|
|
|
|
+ subscriptionExecutor.setMaxPoolSize(10); // 最大线程数
|
|
|
|
|
+ subscriptionExecutor.setQueueCapacity(20); // 队列容量
|
|
|
|
|
+ subscriptionExecutor.setKeepAliveSeconds(60); // 空闲线程存活时间
|
|
|
|
|
+ subscriptionExecutor.setThreadNamePrefix("redis-sub-"); // 线程名前缀
|
|
|
|
|
+ subscriptionExecutor.setRejectedExecutionHandler((r, executor) -> {
|
|
|
|
|
+ // 拒绝策略:打印日志 + 重试提交
|
|
|
|
|
+ System.err.println("Redis订阅任务被拒绝,任务:" + r.toString());
|
|
|
|
|
+ try {
|
|
|
|
|
+ executor.getQueue().offer(r, 1, TimeUnit.SECONDS);
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ // 初始化线程池(必须调用,否则线程池未启动)
|
|
|
|
|
+ subscriptionExecutor.initialize();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 缓存基本的对象,Integer、String、实体类等
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存的键值
|
|
|
|
|
- * @param value 缓存的值
|
|
|
|
|
- * @param timeout 时间
|
|
|
|
|
- * @param timeUnit 时间颗粒度
|
|
|
|
|
|
|
+ * 发布消息(使用 Redis 发布订阅)
|
|
|
*/
|
|
*/
|
|
|
- public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
|
|
|
|
|
- {
|
|
|
|
|
- redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
|
|
|
|
|
|
+ public <T> void publish(String channelKey, T msg) {
|
|
|
|
|
+ redisTemplate.convertAndSend(channelKey, msg);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 设置有效时间
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param timeout 超时时间
|
|
|
|
|
- * @return true=设置成功;false=设置失败
|
|
|
|
|
|
|
+ * 发布消息,并执行回调
|
|
|
*/
|
|
*/
|
|
|
- public boolean expire(final String key, final long timeout)
|
|
|
|
|
- {
|
|
|
|
|
- return expire(key, timeout, TimeUnit.SECONDS);
|
|
|
|
|
|
|
+ public <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
|
|
|
|
|
+ redisTemplate.convertAndSend(channelKey, msg);
|
|
|
|
|
+ if (consumer != null) {
|
|
|
|
|
+ consumer.accept(msg);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 设置有效时间
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param timeout 超时时间
|
|
|
|
|
- * @param unit 时间单位
|
|
|
|
|
- * @return true=设置成功;false=设置失败
|
|
|
|
|
|
|
+ * 订阅频道
|
|
|
*/
|
|
*/
|
|
|
- public boolean expire(final String key, final long timeout, final TimeUnit unit)
|
|
|
|
|
- {
|
|
|
|
|
- return redisTemplate.expire(key, timeout, unit);
|
|
|
|
|
|
|
+ public <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
|
|
|
|
|
+ // 1. 先初始化线程池
|
|
|
|
|
+ initSubscriptionExecutor();
|
|
|
|
|
+ // 2. 初始化监听器容器(含线程池配置)
|
|
|
|
|
+ if (listenerContainer == null) {
|
|
|
|
|
+ initListenerContainer();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MessageListener listener = new MessageListener() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void onMessage(Message message, byte[] pattern) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Object value = redisTemplate.getValueSerializer().deserialize(message.getBody());
|
|
|
|
|
+ if (clazz.isInstance(value)) {
|
|
|
|
|
+ T typedValue = clazz.cast(value);
|
|
|
|
|
+ consumer.accept(typedValue);
|
|
|
|
|
+ } else if (value instanceof String && clazz.equals(String.class)) {
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
|
+ T typedValue = (T) value;
|
|
|
|
|
+ consumer.accept(typedValue);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ System.err.println("处理消息异常: " + e.getMessage());
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ // 现在添加监听器不会报subscriptionExecutor null了
|
|
|
|
|
+ listenerContainer.addMessageListener(listener, new ChannelTopic(channelKey));
|
|
|
|
|
+ String listenerKey = channelKey + "_" + System.currentTimeMillis();
|
|
|
|
|
+ listeners.put(listenerKey, listener);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 获取有效时间
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @return 有效时间
|
|
|
|
|
|
|
+ * 取消订阅
|
|
|
*/
|
|
*/
|
|
|
- public long getExpire(final String key)
|
|
|
|
|
- {
|
|
|
|
|
- return redisTemplate.getExpire(key);
|
|
|
|
|
|
|
+ public void unsubscribe(String channelKey) {
|
|
|
|
|
+ if (listenerContainer == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ listeners.entrySet().removeIf(entry -> {
|
|
|
|
|
+ if (entry.getKey().startsWith(channelKey + "_")) {
|
|
|
|
|
+ listenerContainer.removeMessageListener(entry.getValue());
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 判断 key是否存在
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 键
|
|
|
|
|
- * @return true 存在 false不存在
|
|
|
|
|
|
|
+ * 初始化监听器容器(核心:配置线程池 + 连接工厂)
|
|
|
*/
|
|
*/
|
|
|
- public Boolean hasKey(String key)
|
|
|
|
|
- {
|
|
|
|
|
- return redisTemplate.hasKey(key);
|
|
|
|
|
|
|
+ private synchronized void initListenerContainer() {
|
|
|
|
|
+ if (listenerContainer == null) {
|
|
|
|
|
+ listenerContainer = new RedisMessageListenerContainer();
|
|
|
|
|
+ // 1. 设置连接工厂(原有)
|
|
|
|
|
+ listenerContainer.setConnectionFactory(redisTemplate.getConnectionFactory());
|
|
|
|
|
+ // 2. 设置订阅线程池(解决null问题的核心)
|
|
|
|
|
+ listenerContainer.setSubscriptionExecutor(subscriptionExecutor);
|
|
|
|
|
+ // 3. 可选:设置任务执行器(处理消息的线程池)
|
|
|
|
|
+ listenerContainer.setTaskExecutor(subscriptionExecutor);
|
|
|
|
|
+ // 4. 启动容器(必须在所有属性设置完成后调用)
|
|
|
|
|
+ listenerContainer.start();
|
|
|
|
|
+ System.out.println("RedisMessageListenerContainer 初始化成功(含线程池配置)");
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 获得缓存的基本对象。
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存键值
|
|
|
|
|
- * @return 缓存键值对应的数据
|
|
|
|
|
|
|
+ * 清理资源(优雅关闭线程池 + 容器)
|
|
|
*/
|
|
*/
|
|
|
- public <T> T getCacheObject(final String key)
|
|
|
|
|
- {
|
|
|
|
|
- ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
|
|
|
|
- return operation.get(key);
|
|
|
|
|
|
|
+ @PreDestroy
|
|
|
|
|
+ public void destroy() throws Exception {
|
|
|
|
|
+ // 1. 关闭监听器容器
|
|
|
|
|
+ if (listenerContainer != null) {
|
|
|
|
|
+ listenerContainer.stop();
|
|
|
|
|
+ listenerContainer.destroy();
|
|
|
|
|
+ }
|
|
|
|
|
+ // 2. 关闭订阅线程池
|
|
|
|
|
+ if (subscriptionExecutor != null) {
|
|
|
|
|
+ subscriptionExecutor.shutdown();
|
|
|
|
|
+ }
|
|
|
|
|
+ System.out.println("RedisCache 资源已清理");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 删除单个对象
|
|
|
|
|
- *
|
|
|
|
|
- * @param key
|
|
|
|
|
- */
|
|
|
|
|
- public boolean deleteObject(final String key)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ // ========== 以下为原有Redis操作方法(无需修改) ==========
|
|
|
|
|
+ public <T> void setCacheObject(final String key, final T value) {
|
|
|
|
|
+ redisTemplate.opsForValue().set(key, value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
|
|
|
|
|
+ redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public boolean expire(final String key, final long timeout) {
|
|
|
|
|
+ return expire(key, timeout, TimeUnit.SECONDS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public boolean expire(final String key, final long timeout, final TimeUnit unit) {
|
|
|
|
|
+ return redisTemplate.expire(key, timeout, unit);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public long getExpire(final String key) {
|
|
|
|
|
+ return redisTemplate.getExpire(key);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public Boolean hasKey(String key) {
|
|
|
|
|
+ return redisTemplate.hasKey(key);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public <T> T getCacheObject(final String key) {
|
|
|
|
|
+ return (T) redisTemplate.opsForValue().get(key);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public boolean deleteObject(final String key) {
|
|
|
return redisTemplate.delete(key);
|
|
return redisTemplate.delete(key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 删除集合对象
|
|
|
|
|
- *
|
|
|
|
|
- * @param collection 多个对象
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public boolean deleteObject(final Collection collection)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public boolean deleteObject(final Collection collection) {
|
|
|
return redisTemplate.delete(collection) > 0;
|
|
return redisTemplate.delete(collection) > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 缓存List数据
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存的键值
|
|
|
|
|
- * @param dataList 待缓存的List数据
|
|
|
|
|
- * @return 缓存的对象
|
|
|
|
|
- */
|
|
|
|
|
- public <T> long setCacheList(final String key, final List<T> dataList)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> long setCacheList(final String key, final List<T> dataList) {
|
|
|
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
|
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
|
|
return count == null ? 0 : count;
|
|
return count == null ? 0 : count;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获得缓存的list对象
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存的键值
|
|
|
|
|
- * @return 缓存键值对应的数据
|
|
|
|
|
- */
|
|
|
|
|
- public <T> List<T> getCacheList(final String key)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> List<T> getCacheList(final String key) {
|
|
|
return redisTemplate.opsForList().range(key, 0, -1);
|
|
return redisTemplate.opsForList().range(key, 0, -1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 缓存Set
|
|
|
|
|
- *
|
|
|
|
|
- * @param key 缓存键值
|
|
|
|
|
- * @param dataSet 缓存的数据
|
|
|
|
|
- * @return 缓存数据的对象
|
|
|
|
|
- */
|
|
|
|
|
- public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
|
|
|
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
|
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
|
|
Iterator<T> it = dataSet.iterator();
|
|
Iterator<T> it = dataSet.iterator();
|
|
|
- while (it.hasNext())
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ while (it.hasNext()) {
|
|
|
setOperation.add(it.next());
|
|
setOperation.add(it.next());
|
|
|
}
|
|
}
|
|
|
return setOperation;
|
|
return setOperation;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获得缓存的set
|
|
|
|
|
- *
|
|
|
|
|
- * @param key
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public <T> Set<T> getCacheSet(final String key)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> Set<T> getCacheSet(final String key) {
|
|
|
return redisTemplate.opsForSet().members(key);
|
|
return redisTemplate.opsForSet().members(key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 缓存Map
|
|
|
|
|
- *
|
|
|
|
|
- * @param key
|
|
|
|
|
- * @param dataMap
|
|
|
|
|
- */
|
|
|
|
|
- public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
|
|
|
if (dataMap != null) {
|
|
if (dataMap != null) {
|
|
|
redisTemplate.opsForHash().putAll(key, dataMap);
|
|
redisTemplate.opsForHash().putAll(key, dataMap);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获得缓存的Map
|
|
|
|
|
- *
|
|
|
|
|
- * @param key
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- public <T> Map<String, T> getCacheMap(final String key)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> Map<String, T> getCacheMap(final String key) {
|
|
|
return redisTemplate.opsForHash().entries(key);
|
|
return redisTemplate.opsForHash().entries(key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 往Hash中存入数据
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param hKey Hash键
|
|
|
|
|
- * @param value 值
|
|
|
|
|
- */
|
|
|
|
|
- public <T> void setCacheMapValue(final String key, final String hKey, final T value)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
|
|
|
redisTemplate.opsForHash().put(key, hKey, value);
|
|
redisTemplate.opsForHash().put(key, hKey, value);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获取Hash中的数据
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param hKey Hash键
|
|
|
|
|
- * @return Hash中的对象
|
|
|
|
|
- */
|
|
|
|
|
- public <T> T getCacheMapValue(final String key, final String hKey)
|
|
|
|
|
- {
|
|
|
|
|
- HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
|
|
|
|
- return opsForHash.get(key, hKey);
|
|
|
|
|
|
|
+ public <T> T getCacheMapValue(final String key, final String hKey) {
|
|
|
|
|
+ return (T) redisTemplate.opsForHash().get(key, hKey);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获取多个Hash中的数据
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param hKeys Hash键集合
|
|
|
|
|
- * @return Hash对象集合
|
|
|
|
|
- */
|
|
|
|
|
- public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
|
|
|
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
|
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 删除Hash中的某条数据
|
|
|
|
|
- *
|
|
|
|
|
- * @param key Redis键
|
|
|
|
|
- * @param hKey Hash键
|
|
|
|
|
- * @return 是否成功
|
|
|
|
|
- */
|
|
|
|
|
- public boolean deleteCacheMapValue(final String key, final String hKey)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public boolean deleteCacheMapValue(final String key, final String hKey) {
|
|
|
return redisTemplate.opsForHash().delete(key, hKey) > 0;
|
|
return redisTemplate.opsForHash().delete(key, hKey) > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 获得缓存的基本对象列表
|
|
|
|
|
- *
|
|
|
|
|
- * @param pattern 字符串前缀
|
|
|
|
|
- * @return 对象列表
|
|
|
|
|
- */
|
|
|
|
|
- public Collection<String> keys(final String pattern)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ public Collection<String> keys(final String pattern) {
|
|
|
return redisTemplate.keys(pattern);
|
|
return redisTemplate.keys(pattern);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|