简体   繁体   中英

Get Set value from Redis using RedisTemplate

I am able to retrieve values from Redis using 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();
    }

But when I am trying to use Spring's RedisTemplate , I am not getting any data. My data is stored in Redis as a 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 "";
    }

Can someone please point out to me what am I missing?

EDIT : My xml config for 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" />

In short

You have to configure serializers.

Explanation

The Redis template uses serializers for keys, values and hash keys/values. Serializers are used to convert the Java input into the representation that is stored within Redis. If you do not configure anything, the serializer defaults to JdkSerializationRedisSerializer . So if you ask for a key key in your Java code, the serializer converts it to

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

and Spring Data Redis uses those bytes as the key to query Redis.

You can add data with Spring Data Redis and query it using the redis-cli :

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

and then in the 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"

As you see, the String and the Date are serialized into some crazy bytes that represent a Java-serialized object.

Your code suggests you want to store String-based keys and values. Just set the StringRedisSerializer in your RedisTemplate

Java configuration

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

XML configuration

<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"/>

The output after running your code looks like then:

value
key
[value]

Spring Data Redis has some interesting serializers that allow message exchange between various systems. You can choose either from the built-in serializers

  • JacksonJsonRedisSerializer
  • Jackson2JsonRedisSerializer
  • JdkSerializationRedisSerializer (default)
  • OxmSerializer
  • GenericToStringSerializer

or create your own.

I used Spring Data Redis 1.5.1.RELEASE and jedis 2.6.2 to verify the result of your question. HTH, Mark

Further read:

You could do it much easier with Redisson :

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();
}

This framewrok handles serialization and work with connection so you don't need to deal with it each time. Work with Redis as you used to work with Java objects (Set, Map, List ...). It supports many popular codecs too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM