Spring поддержка Redis данных для модулей?

Я использую 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?

1 ответ

Решение

Хорошо, мне удалось это сделать вот так:

Первое продление ModuleCommand и замените все символы '_' на '.':

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,
  ;
}

А теперь самое интересное: я уже интегрировал больше модулей, поэтому мне нужно обобщить часть выполнения:

public abstract class ModuleAbstractManager {

  private static final Logger LOG = LoggerFactory.getLogger(ModuleAbstractManager.class);

  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) {
      LOG.error(String.format("failed to execute command %s with args %s", jsonCommand.name(), Arrays.toString(args)), e);
      return Optional.empty();
    }
    finally {
      LOG.debug("closing redis native connection");
      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";

  private static final Logger LOG = LoggerFactory.getLogger(RedisJsonManager.class);

  public Optional<String> getValue(String key) {
    return getValue(key, ROOT_PATH);
  }

  public Optional<String> getValue(String key, String path) {

    if (StringUtils.isEmpty(path)) {
      LOG.error("Failed to get key {} with empty path", key);
      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)) {
      LOG.error("Failed to get key {} with empty path", key);
      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);
  }
}
Другие вопросы по тегам