Получить значение Set из Redis с помощью RedisTemplate

Я могу получить значения из Redis с помощью Jedis:

public static void main(String[] args) {
        Jedis jedis = new Jedis(HOST, PORT);
        jedis.connect();
        Set<String> set = jedis.smembers(KEY);
        for (String s : set) {
            System.out.println(s);
        }
        jedis.disconnect();
        jedis.close();
    }

Но когда я пытаюсь использовать Spring RedisTemplate, я не получаю никаких данных. Мои данные хранятся в Redis как Set.

      // inject the actual template 
      @Autowired
      private RedisTemplate<String, Object> template;

      // inject the template as SetOperations
      @Resource(name="redisTemplate")
      private SetOperations<String,String> setOps;

public String logHome() {       
        Set<String> set =  setOps.members(KEY);
        for(String str:set){
            System.out.println(str); //EMPTY
        }       
        Set<byte[]> keys = template.getConnectionFactory().getConnection().keys("*".getBytes());
        Iterator<byte[]> it = keys.iterator();
        while(it.hasNext()){
            byte[] data = (byte[])it.next();
            System.out.println(new String(data, 0, data.length)); //KEYS are printed.
        }
        Set<Object> mySet = template.boundSetOps(KEY).members();        
        System.out.println(mySet); //EMPTY      
        return "";
    }

Может кто-нибудь, пожалуйста, укажите мне, что мне не хватает?

EDIT: My xml config для RedisTemplate.

 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
    p:connection-factory-ref="jedisConnectionFactory"/>

     <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
        p:host-name="myhostname" p:port="6379" />

Ответ 1

Вкратце

Вам необходимо настроить сериализаторы.

объяснение

Шаблон Redis использует сериализаторы для ключей, значений и хеш-ключей/значений. Сериализаторы используются для преобразования входа Java в представление, которое хранится в Redis. Если вы ничего не сконфигурируете, по умолчанию для serializer используется JdkSerializationRedisSerializer. Поэтому, если вы запрашиваете ключевой key в своем Java-коде, сериализатор преобразует его в

"\xac\xed\x00\x05t\x00\x03key"

и Spring Data Redis использует эти байты в качестве ключа для запроса Redis.

Вы можете добавить данные с помощью Spring Data Redis и запросить его с помощью redis-cli:

template.boundSetOps("myKey").add(new Date());

а затем в redis-cli

127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x05myKey"
127.0.0.1:6379> SMEMBERS "\xac\xed\x00\x05t\x00\x05myKey"
1) "\xac\xed\x00\x05sr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x01N\xcf#\x9cHx"

Как вы видите, String и Date сериализуются в некоторые сумасшедшие байты, представляющие объект, сериализованный Java.

Ваш код подсказывает, что вы хотите хранить клавиши и значения на основе String. Просто установите StringRedisSerializer в свой RedisTemplate

Конфигурация Java

redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());

Конфигурация XML

<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" 
    p:connection-factory-ref="jedisConnectionFactory">
    <property name="keySerializer" ref="stringSerializer"/>
    <property name="valueSerializer" ref="stringSerializer"/>
</bean>

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" 
    p:host-name="myhostname" p:port="6379"/>

Результат после запуска вашего кода выглядит следующим образом:

value
key
[value]

Spring Data Redis имеет несколько интересных сериализаторов, которые позволяют обмен сообщениями между различными системами. Вы можете выбрать либо из встроенных сериализаторов

  • JacksonJsonRedisSerializer
  • Jackson2JsonRedisSerializer
  • JdkSerializationRedisSerializer (по умолчанию)
  • OxmSerializer
  • GenericToStringSerializer

или создать свой собственный.

Я использовал Spring Data Redis 1.5.1.RELEASE и jedis 2.6.2, чтобы проверить результат вашего вопроса. HTH, Mark

Далее читайте:

Ответ 2

Вы можете сделать это намного проще с Редиссоном:

public static void main(String[] args) {
    Config conf = new Config();
    conf.useSingleServer().setAddress(host + ":" + port);

    RedissonClient redisson = Redisson.create(conf);
    RSet<String> set = redisson.getSet(KEY)
    for (String s : set.readAllValues()) {
        System.out.println(s);
    }
    redisson.shutdown();
}

Этот framewrok обрабатывает сериализацию и работу с соединением, поэтому вам не нужно обращаться с ним каждый раз. Работайте с Redis, когда вы использовали для работы с объектами Java (Set, Map, List...). Он поддерживает многие популярные кодеки.