由于最近在做商城秒杀这块的业务,因此使用到了redis中提供的incrBy 自增方法和decrBy自减方法。但是今天在项目中使用发现当我们使用到fst或者jdk的序列化与反序列化时,如果我们使用上面两个api 往redis 里面存数据是没有任何问题的。但是如果直接调用redis api中的get方法去取值的时候,系统抛出空指针异常了。下面我们来看代码测试
public static void main(String[] args) { try { RedisPlugin redisPlugin = new RedisPlugin("MAIN", "127.0.0.1", 6379, "123456"); FstSerializer fstSerializer = new FstSerializer(); redisPlugin.setSerializer(fstSerializer); redisPlugin.start(); Redis.use("MAIN").incrBy("test1223", 1); byte[] bytes = Redis.use("MAIN").getJedis().get(fstSerializer.keyToBytes("test1223")); FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); System.out.println("fastJson解析" + fastJsonRedisSerializer.deserialize(bytes)); // 使用fastJson反序列化 System.out.println("fst解析" + fstSerializer.valueFromBytes(bytes));// 使用fst反序列化 System.out.println("JdkSerializer解析" + new JdkSerializer().valueFromBytes(bytes));// 使用Jdk反序列化 } catch (Exception e) { e.printStackTrace(); } }
下面是运行结果
可以看到只有使用fastJson可以反序列化成功。最后我经过阅读源码发现,当我们调用incrBy 自增方法和decrBy自减方法这两个api 时,存储的value不会经过fst进行序列化,而是直接将数值存储到redis。而当我们调用get 方法取值的时候首先取出来的是byte数组,然后在经过fst进行反序列化。而这个时候由于value 没有经过fst进行序列化存储,所以使用fst无法经byte数组解析成Integer类型,因此导致了空指针异常。这可能是fst框架存在的一个小问题。在jfinal 的官方文档中发现波总另外写了一个方法getCounter方法去获取redis中计数器的值。在这里我在分享一个方法,欢迎大家在下方留言
创建一个类FstJsonSerializer,此类继承FstSerializer
public class FstJsonSerializer extends FstSerializer { // 使用FastJsonRedisSerializer 代理 private final FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); /** * 重写valueFromBytes * @param bytes * @return */ @Override public Object valueFromBytes(byte[] bytes) { try { return super.valueFromBytes(bytes); } catch (Exception e) { try { LogKit.warn(e.getMessage(), e); return fastJsonRedisSerializer.deserialize(bytes); } catch (Exception exception) { throw new RuntimeException(exception); } } } }
解决的思路就是如果Fst反序列化异常,就是用FastJson反序列化,如果还不能成功的话则抛出异常。通过使用以上代码,我们就可以调用get方法直接获取redis中计数器的值了。
注意:使用 incr、incrBy、decr、decrBy 方法操作的计数器,需要使用 getCounter(key) 进行读取而不能使用 get(key),否则会抛反序列化异常。同理:incrBy(key, value) 操作不能使用 set(key, value) 。