zwq_david9527
2017-12-20 08:11
采纳率: 33.3%
浏览 9.1k

RedisTemplate set方法疑问

jedis客户端中提供了设置值、设置失效时间、not exists的原子性方法
图片说明
可是RedisTemplate设置值setIfAbsent与设置失效时间是两个方法,能不能用RedisTemplate的方法实现jedis的set功能呢?求助

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

5条回答 默认 最新

  • ai2018 2017-12-20 08:35
    已采纳

    请参考:
    使用:redisTemplate.opsForValue().set("name","tom",10, TimeUnit.SECONDS);
    结果:redisTemplate.opsForValue().get("name")由于设置的是10秒失效,十秒之内查询有结果,十秒之后返回为null

    点赞 评论
  • ai2018 2017-12-20 10:24

    RedisTemplate中有一个execute方法,如下图:

     @Override
        public Object execute(String command, byte[]... args) {
            Assert.hasText(command, "a valid command needs to be specified");
            try {
                List<byte[]> mArgs = new ArrayList<>();
                if (!ObjectUtils.isEmpty(args)) {
                    Collections.addAll(mArgs, args);
                }
    
                ReflectionUtils.invokeMethod(SEND_COMMAND, client, Command.valueOf(command.trim().toUpperCase()),
                        mArgs.toArray(new byte[mArgs.size()][]));
                if (isQueueing() || isPipelined()) {
                    Object target = (isPipelined() ? pipeline : transaction);
                    @SuppressWarnings("unchecked")
                    Response<Object> result = (Response<Object>) ReflectionUtils.invokeMethod(GET_RESPONSE, target,
                            new Builder<Object>() {
                                public Object build(Object data) {
                                    return data;
                                }
    
                                public String toString() {
                                    return "Object";
                                }
                            });
                    if (isPipelined()) {
                        pipeline(newJedisResult(result));
                    } else {
                        transaction(newJedisResult(result));
                    }
                    return null;
                }
                return client.getOne();
            } catch (Exception ex) {
                throw convertJedisAccessException(ex);
            }
        }
    

    底层利用了反射原理去间接调用redis.clients.jedis.Client的set方法,在去调用redis.clients.jedis.BinaryClient 的sendCommand方法,所以如果自己要调用底层jedis的

    set(final String key, final String value, final String nxxx, final String expx,
          final long time) 
    

    我们需要对代码进行如下修改,这个是思路,我还没有测试:
    代码的大概逻辑是这样

      RedisTemplate<String, String> template = new StringRedisTemplate(new JedisConnectionFactory());
            template.execute(new RedisCallback<Object>() {
    
                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    return connection.execute("set", new byte[][]{
                            SafeEncoder.encode("key"), SafeEncoder.encode("value"), SafeEncoder.encode("nxxx"),
                            SafeEncoder.encode("expx"), Protocol.toByteArray(10)});
                }
            });
    
    点赞 评论
  • ai2018 2017-12-20 15:52

    请参考我的github项目:
    https://github.com/xiaohu-liu/springboot-app/edit/master/redis-test/src/test/java/com/indi/spring/redis/RedisTest.java

     package com.indi.spring.redis;
    
    
    import com.indi.spring.redis.mapper.impl.RedisServiceImpl;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = App.class)
    @WebAppConfiguration
    public class RedisTest {
    
        @Autowired
        private RedisServiceImpl redisService;
    
    
        @Test
        public void test1() {
            redisService.set("name", "xiaohu-liu");
            redisService.set("nickname2", "xiaohu-liu", "NX", "EX", 10);
        }
    
    
    }
    
    
    点赞 评论
  • 迷途小羔羊678 2017-12-21 07:49

    stringRedisTemplate.opsForValue().set(key, value);
    stringRedisTemplate.expire(key,expires,tu);

    expires是时间数值 tu是单位(TimeUnit),时分秒等,这个是设个存留时间,比如,缓存两小时
    还可以设置到期时间,比如,设置今天晚上十点失效
    public Boolean expire(K key, final long timeout, final TimeUnit unit) {
    final byte[] rawKey = rawKey(key);
    final long rawTimeout = TimeoutUtils.toMillis(timeout, unit);

        return execute(new RedisCallback<Boolean>() {
    
            public Boolean doInRedis(RedisConnection connection) {
                try {
                    return connection.pExpire(rawKey, rawTimeout);
                } catch (Exception e) {
                    // Driver may not support pExpire or we may be running on Redis 2.4
                    return connection.expire(rawKey, TimeoutUtils.toSeconds(timeout, unit));
                }
            }
        }, true);
    }
    
    public Boolean expireAt(K key, final Date date) {
        final byte[] rawKey = rawKey(key);
    
        return execute(new RedisCallback<Boolean>() {
    
            public Boolean doInRedis(RedisConnection connection) {
                try {
                    return connection.pExpireAt(rawKey, date.getTime());
                } catch (Exception e) {
                    return connection.expireAt(rawKey, date.getTime() / 1000);
                }
            }
        }, true);
    }
    
    点赞 评论
  • 崔世兵 2018-09-13 08:14
     Boolean success = redisTemplate.execute((RedisCallback<Boolean>) connection -> {
                RedisSerializer defaultSerializer = redisTemplate.getDefaultSerializer();
                Object result = connection.set(defaultSerializer.serialize("name"),
                        defaultSerializer.serialize("my name"),
                        Expiration.from(1000, TimeUnit.SECONDS),
                        RedisStringCommands.SetOption.ifAbsent());
    
                return (Boolean) result;
            });
    
    点赞 评论

相关推荐 更多相似问题