jedis客户端中提供了设置值、设置失效时间、not exists的原子性方法
可是RedisTemplate设置值setIfAbsent与设置失效时间是两个方法,能不能用RedisTemplate的方法实现jedis的set功能呢?求助
请参考:
使用:redisTemplate.opsForValue().set("name","tom",10, TimeUnit.SECONDS);
结果:redisTemplate.opsForValue().get("name")由于设置的是10秒失效,十秒之内查询有结果,十秒之后返回为null
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)});
}
});
请参考我的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);
}
}
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);
}
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;
});