站长,我找到了一个简便解决方法:
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的开销,性能应该不会下降很多