08. SDR 自定义序列化-Gzip 压缩

Redis 可以通过客户端命令redis-cli 直接连接, 然后直接操作其中的数据。当使用redis 存储一些敏感数据,或者是数据较大的数据时,我们可以对value进行加密序列化或压缩序列化。对于节省内存而言,采用Gzip压缩也是一个不错的方案。 笔者采用的方案是,先将对象序列化json, 然后再对json进行Gzip 压缩.

1. 自定义压缩序列化

1.1 GzipJsonSerializer

  • 笔者json序列化采用默认的jackson 序列化方式, 所以笔者直接继承GenericJackson2JsonRedisSerializer 即可, 或者实现RedisSerializer 接口
  • 序列化: 先进行jso序列化, 再进行压缩
  • 反序列化: 先进行解压缩, 再进行反序列化
public class GzipJsonSerializer extends GenericJackson2JsonRedisSerializer {

    @Override
    public byte[] serialize(Object source) throws SerializationException {

        // 先序列化java对象为json字节数组
        byte[] bytes = super.serialize(source);

        // 再将json 字节数组进行gzip压缩
        return GzipUtils.compress(bytes);
    }

    @Override
    public Object deserialize(byte[] source) throws SerializationException {

        // 先解压字节数组为json字节数组
        byte[] bytes = GzipUtils.unCompress(source);

        // 在序列化json字节数组为java 对象
        return super.deserialize(bytes);
    }

}

1.2 java Gzip工具类

自定义一个gzip 压缩解压缩工具类, 实现对字节数组的压缩与解压缩.

public class GzipUtils {

    /**
     * @param bytes 字节数组
     * @return byte[]
     * @description 压缩字节数组
     */
    public static byte[] compress(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }

        //将byte数据读入文件流
        ByteArrayOutputStream bos = null;
        GZIPOutputStream gzipos = null;
        try {
            bos = new ByteArrayOutputStream();
            gzipos = new GZIPOutputStream(bos);
            gzipos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeStream(gzipos);
            closeStream(bos);
        }
        return bos.toByteArray();
    }

    /**
     * @param bytes Gzip压缩的字节数组
     * @return byte[]
     * @description 解压缩字节数组
     */
    public static byte[] unCompress(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        ByteArrayOutputStream byteAos = null;
        ByteArrayInputStream byteArrayIn = null;
        GZIPInputStream gzipIn = null;
        try {
            byteArrayIn = new ByteArrayInputStream(bytes);
            gzipIn = new GZIPInputStream(byteArrayIn);
            byteAos = new ByteArrayOutputStream();
            byte[] b = new byte[4096];
            int temp = -1;
            while ((temp = gzipIn.read(b)) > 0) {
                byteAos.write(b, 0, temp);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            closeStream(byteAos);
            closeStream(gzipIn);
            closeStream(byteArrayIn);
        }
        return byteAos.toByteArray();
    }

    /**
     * 关闭流
     *
     * @param oStream
     */
    private static void closeStream(Closeable oStream) {
        if (null != oStream) {
            try {
                oStream.close();
            } catch (IOException e) {
                oStream = null;//赋值为null,等待垃圾回收
                e.printStackTrace();
            }
        }
    }

}

1.3 配置自定义RedisTemplate

@Bean("gzipJsonRedisTemplate")
public RedisTemplate<Object, Object> gzipJsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    RedisTemplate<Object,Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GzipJsonSerializer());
    return template;
}

2. 测试

2.1 测试用例

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestGzipJsonTemplate {

    @Autowired
    private RedisTemplate gzipJsonRedisTemplate;

    @Test
    public void test(){

        UserPO userPO = new UserPO("zhangsan", "123456", 20);

        ValueOperations  ops = this.gzipJsonRedisTemplate.opsForValue();

        ops.set("zhangsan", userPO);

        System.out.println(ops.get("zhangsan"));

    }

}

2.2 redis 中存储

使用redis-cli 命令查看redis 中的存储形式

127.0.0.1:6379> get zhangsan
"\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00\xabVrH\xceI,.V\xb2R\xca/J\xd7\xab\xca\xcfKO\xd3\xcbIM,\xca\xd3+N)\xd2\xcb10\xd4\x0b-N-\n\xf0W\xd2Q*\x052\xf2\x12sS\x81j\xab2\x12\xf3\xd2\x8b\x13\xf3\x80\xa2\x05@\xdd\xe5\xf9E)@QC#c\x13S3\xa0Xb:P\x91\x91A-\x00\xad\xc9v~^\x00\x00\x00"
上一篇:python-->json和pickle模块


下一篇:Lesson 1-2