站长,我找到了一个简便解决方法:
cache中所有的方法都是用了ISerializer进行序列化,默认使用的是FstSerializer,但是使用FstSerializer序列化时就会遇到
hmset(Object key, Map<Object, Object> hash)和
hincrBy(Object key, Object field, long value)方法冲突问题
问题详情:http://www.jfinal.com/feedback/1801
问题原因:
hmset设置的value为序列化后的value,hincrBy()获取与field对应的value时无法将其转换为integer,出错
即使使用原始jedis操作,导致所有的hash键必须使用jedis.hmset(key,hash)设置,则所有与此key相关的方法都需要使用jedis,而不能使用cache,就丧失了JFinal框架封装jedis的意义,代码也大量充斥着重复代码:
Cache cache=Redis.user(); Jedis jedis=cache.getJedis(); ... cache.close(jedis);
不仅不美观,而且难以维护
解决方案:
编写自定义的ISerializer,再FstSerializer上做了一层简单封装,只有value为Integer时,才不使用FstSerializer
代码如下:
/**
* 由于使用FstSerializer导致hmset与hincrBy冲突,当value为Integer时,转换为使用keyToBytes()
*/
public class MyFstSerializer implements ISerializer {
@Override
public byte[] keyToBytes(String key) {
return FstSerializer.me.keyToBytes(key);
}
@Override
public String keyFromBytes(byte[] bytes) {
return FstSerializer.me.keyFromBytes(bytes);
}
@Override
public byte[] fieldToBytes(Object field) {
return valueToBytes(field);
}
@Override
public Object fieldFromBytes(byte[] bytes) {
return valueFromBytes(bytes);
}
@Override
public byte[] valueToBytes(Object value) {
if (value instanceof String) {
return keyToBytes((String) value);
}
if (value instanceof Integer) {
return keyToBytes(String.valueOf(value));
}
return FstSerializer.me.valueToBytes(value);
}
@Override
public Object valueFromBytes(byte[] bytes) {
return FstSerializer.me.valueFromBytes(bytes);
}
}而后在
public void configPlugin(Plugins me)
方法中加入
redisPlugin.setSerializer(new MyFstSerializer());
即可
缺点:由于使用jedis存放的数据中多数类型为非Integer,加了一次判断可能会导致性能有点下降,但是多了一个instanceof判断的开销,少了一个使用FstSerializer序列化Integer的开销,性能应该不会下降很多