Spring数据redis对模块的支持?
Posted
技术标签:
【中文标题】Spring数据redis对模块的支持?【英文标题】:Spring data redis support for modules? 【发布时间】:2020-07-18 14:11:20 【问题描述】:我正在使用带有 lettuce 驱动程序的 Spring data Redis(2.1.1RELEASE 版本)(5.1.3RELEASE 版本) 我想用这个模块:https://oss.redislabs.com/redisjson/ 但是驱动好像不支持。
我尝试使用execute
方法:
Object response = redisTemplate.execute((RedisCallback<String>) connection ->
return (String) connection.execute("JSON.GET foo");
);
得到一个错误:
java.lang.IllegalArgumentException: 没有枚举常量 io.lettuce.core.protocol.CommandType.JSON.GET FOO
有没有办法做到这一点?如何使用 Redis 模块?
【问题讨论】:
你克服了吗? @GuyKorland 我做了,但它需要一些基础设施,我将在下面发布解决方案 【参考方案1】:好的,所以我设法做到了:
首先扩展 ProtocolKeyword
并将所有 '_' 字符替换为 '.':
public interface ModuleCommand extends ProtocolKeyword
@Override
default byte[] getBytes()
return name().replaceAll("_", ".").getBytes(LettuceCharsets.ASCII);
其次,使用您希望实现的命令类型创建一个枚举:
public enum JsonCommand implements ModuleCommand
JSON_GET,
JSON_MGET,
JSON_SET,
JSON_ARRAPPEND,
JSON_DEL,
// other commands you wish to implement
;
现在是有趣的部分,我已经集成了更多模块,所以我必须概括执行部分:
public abstract class ModuleAbstractManager
protected ByteArrayCodec codec = ByteArrayCodec.INSTANCE;
@Autowired
private LettuceConnectionFactory connectionFactory;
protected <T> Optional<T> execute(String key, ModuleCommand jsonCommand, CommandOutput<byte[], byte[], T> output, String... args)
List<byte[]> extraArgs = Arrays.stream(args)
.filter(arg -> !StringUtils.isEmpty(arg))
.map(String::getBytes)
.collect(Collectors.toList());
CommandArgs<byte[], byte[]> commandArgs = new CommandArgs<>(codec)
.addKey(key.getBytes())
.addValues(extraArgs);
LettuceConnection connection = (LettuceConnection) connectionFactory.getConnection();
try
RedisFuture<T> future = connection.getNativeConnection().dispatch(jsonCommand, output, commandArgs);
return Optional.ofNullable(future.get());
catch (InterruptedException | ExecutionException e)
return Optional.empty();
finally
connection.close();
最后是执行本身:
@Service
public class RedisJsonManager extends ModuleAbstractManager
public static final String ROOT_PATH = ".";
public static final String OK_RESPONSE = "OK";
public static final String SET_IF_NOT_EXIST_FLAG = "NX";
public Optional<String> getValue(String key)
return getValue(key, ROOT_PATH);
public Optional<String> getValue(String key, String path)
if (StringUtils.isEmpty(path))
return Optional.empty();
return execute(key, JsonCommand.JSON_GET, new ValueOutput<>(codec), path)
.map(String::new);
public Optional<String> getValue(String key, List<String> multiPath)
if (CollectionUtils.isEmpty(multiPath))
return Optional.empty();
String[] args = multiPath.toArray(new String[0]);
return execute(key, JsonCommand.JSON_GET, new ValueOutput<>(codec), args)
.map(String::new);
public boolean setValueIfNotExist(String key, String json)
return setValue(key, json, ROOT_PATH, true);
public boolean setValueIfNotExist(String key, String json, String path)
return setValue(key, json, path, true);
public boolean setValue(String key, String json)
return setValue(key, json, ROOT_PATH, false);
public boolean setValue(String key, String json, String path)
return setValue(key, json, path, false);
private boolean setValue(String key, String json, String path, boolean setIfNotExist)
return execute(key, JsonCommand.JSON_SET, new StatusOutput<>(codec), path, json, setIfNotExist ? SET_IF_NOT_EXIST_FLAG : "")
.map(OK_RESPONSE::equals)
.orElse(false);
public Long addToArray(String key, String json)
return addToArray(key, json, ROOT_PATH);
public Long addToArray(String key, String json, String path)
return execute(key, JsonCommand.JSON_ARRAPPEND, new IntegerOutput<>(codec), path, json).orElse(0L);
public Long delete(String key)
return delete(key, ROOT_PATH);
public Long delete(String key, String path)
return execute(key, JsonCommand.JSON_DEL, new IntegerOutput<>(codec), path).orElse(0L);
【讨论】:
以上是关于Spring数据redis对模块的支持?的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot在Spring boot中Redis的使用
Spring Boot 对rabbitmq批量处理数据的支持