1. ERR value is not an integer or out of range
@Bean
public RedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory){
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//配置序列化方式
redisTemplate.setKeySerializer(new StringRedisSerializer());
//使用GenericFastJsonRedisSerializer 代替 GenericJackson2JsonRedisSerializer
redisTemplate.setValueSerializer(new GenericFastJsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericFastJsonRedisSerializer());
return redisTemplate;
}
RedisScript redisScript = RedisScript.of("local times = redis.call('incr',KEYS[1]) if times == 1 then redis.call('expire',KEYS[1],ARGV[1]) end if times > 5 then return 0 end return 1",Long.class);
List<String> list = new ArrayList<>();
list.add("door3");
Object result = redisTemplate.execute(redisScript,list,"60");
报错 : @user_script:1: ERR value is not an integer or out of range
连接redis,观察lua脚本执行情况。
redis.call('incr',KEYS[1]) 执行成功,key值正确设值
redis.call('expire',KEYS[1],ARGV[1]) , 执行失败 ,并没有设置过期值。说明ARGV[1] 的设值出现问题
——> 观察源码
public <T> T execute(final RedisScript<T> script, final List<K> keys, final Object... args) {
// use the Template's value serializer for args and result
return execute(script, template.getValueSerializer(), (RedisSerializer<T>) template.getValueSerializer(), keys,
args);
}
使用的是 template 设置的ValueSerializer() ,上面我们设置的是GenericFastJsonRedisSerializer。
——> 观察GenericFastJsonRedisSerializer 的序列化方式
public byte[] serialize(Object object) throws SerializationException {
if (object == null) {
return new byte[0];
} else {
try {
return JSON.toJSONBytes(object, new SerializerFeature[]{SerializerFeature.WriteClassName});
} catch (Exception var3) {
throw new SerializationException("Could not serialize: " + var3.getMessage(), var3);
}
}
}
——> 提取JSON.toJSONBytes 观察下列可知转换得的是“5” 的json字符串,不是数值5
byte[] bytes = JSON.toJSONBytes("5", new SerializerFeature[]{SerializerFeature.WriteClassName});
System.out.println(new String(bytes).equals("\"5\""));// "5" true
修改方式,redisTemplate.execute 中自己定义key和arg的序列化方式,我们使用StringRedisSerializer
Object result = redisTemplate.execute(redisScript,new StringRedisSerializer(),new StringRedisSerializer(),list,"60");
2.java.lang.IllegalStateException: null
RedisScript redisScript = RedisScript.of("local times = redis.call('incr',KEYS[1]) if times == 1 then redis.call('expire',KEYS[1],ARGV[1]) end if times > 5 then return 0 end return 1",
Integer.class);
如果上述的RedisScript的ResultType 把Long改为Integer,也会报错。原因在于lua并不支持Integer类型
观察下列源码可以得到lua类型和java类型一个对应关系
// ReturnType.class
public static ReturnType fromJavaType(@Nullable Class<?> javaType) {
if (javaType == null) {
return ReturnType.STATUS;
}
if (javaType.isAssignableFrom(List.class)) {
return ReturnType.MULTI;
}
if (javaType.isAssignableFrom(Boolean.class)) {
return ReturnType.BOOLEAN;
}
if (javaType.isAssignableFrom(Long.class)) {
return ReturnType.INTEGER;
}
return ReturnType.VALUE;
}