Redis实践(4.6)SpringBoot 测试主从数据序列化

Redis
placeholder image
admin 发布于:2023-05-28 14:21:40
阅读:loading

前文中使用SpringBoot Data Redis项目集成了Redis的主从架构接入,本篇主要来测试一下整合后从项目中使用RedisTemplate操作redis相关的API,实现数据存储和读取的序列化实现,前文的工具类提供了基于StringRedisTemplate和RedisTemplate的两种实现,仔细一些会发现《Redis实践(4.5)SpringBoot 测试数据类型读写》中涉及的数据类型多数为简单的字符串类型,虽然任何数据类型在存储时都可以使用String类型存储,取出来自己在用JSON来解析进行类型二次转换,但是这种实现让人感觉到不够优雅,所以本文主要就是基于List<User>结构的数据类型进行序列化,关注对象类型数据的存储和获取的优雅程度,详见下文。

1.Bo定义

   /**
     * 定义User对象,使用多种数据类型
     */
    public static class User {
        private Long id;
        private String name;
        private Short age;
        private Double pi;
        private BigDecimal amount;
        private Boolean flag;
        private SexEnum sex;
        private List<Point> points;
		//getter setter
	}
    }
	
    public enum SexEnum {
        Boy("男"),
        Gril("女"),
        ;
        private String text;
        SexEnum(String text) {
            this.text = text;
        }
        public String getText() {
            return text;
        }
    }

【说明】

上述数据类型定义User包含了多种属性类型,有常见的Long、String、Short、Double、BigDecimal、Boolean、枚举类型、List等多种,几乎可覆盖到全部的数据类型范围;

2.测试代码

@Test
public void listBo() {
    BoundListOperations<String, User> write = this.writeRedisTemplate.boundListOps("listBo");
    {
        User user = new User();
        user.setId(Long.MAX_VALUE - Integer.MAX_VALUE);
        user.setName("陈冬冬");
        user.setAge(Short.MAX_VALUE);
        user.setPi(Math.PI);
        user.setAmount(BigDecimal.TEN);
        user.setFlag(Boolean.TRUE);
        user.setSex(SexEnum.Boy);
        List<Point> points = new ArrayList<>();
        points.add(new Point(1 , 2));
        points.add(new Point(11 , 22));
        user.setPoints(points);
        write.rightPush(user);
    }
    {
        User user = new User();
        user.setId(Long.MIN_VALUE + Integer.MAX_VALUE);
        user.setName("redis");
        user.setAge(Short.MIN_VALUE);
        user.setPi(Math.PI);
        user.setAmount(new BigDecimal("123456.789"));
        user.setFlag(Boolean.FALSE);
        user.setSex(SexEnum.Gril);
        List<Point> points = new ArrayList<>();
        points.add(new Point(111 , 222));
        points.add(new Point(333 , 444));
        user.setPoints(points);
        write.rightPush(user);
    }
    //从读服务中获取数据
    BoundListOperations<String, User> read = this.readRedisTemplate.boundListOps("listBo");
    Long size = read.size();
    List<User> lists = read.range(0, size);
    for (User user : lists) {
        System.out.println(user);
    }
}

3.输出结果

查看序列化数据.gif

(序列化数据)

image.png

(反序列化获取到的数据类型)

4.其它说明

(1)上述序列化截图中可以看到序列化的数据被存储成了JSON格式,且JSON中包含了@type属性,该属性表示的是序列化时的数据类型,用于反序列化时的类型还原;

(2)上述反序列化截图中可以看到反序列化的数据被还原成了实际数据的业务类型,各种各样的数据类型均映射成功;

(3)参考Redis序列化代码如下:

@Bean(READ2_REDIS_TEMPLATE)
public RedisTemplate<String, Object> read2RedisTemplate(@Autowired @Qualifier(READ2_LETTUCE_CONNECTION_FACTORY) RedisConnectionFactory factory) {
    return this.createRedisTemplate(factory);
}

private <T> RedisTemplate<String, Object> createRedisTemplate(RedisConnectionFactory factory) {

    GenericFastJsonRedisSerializer fastjson = new GenericFastJsonRedisSerializer();

    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());

    template.setValueSerializer(fastjson);
    template.setHashValueSerializer(fastjson);
    template.afterPropertiesSet();
    return template;
}

A.使用了fastjson中的GenericFastJsonRedisSerializer来序列化数据,序列化后的数据格式就是上图中的序列化含@type的样式结构;

B.若是使用fastjson中的FastJsonRedisSerializer序列化后的数据是不含@type形式的json格式,即原生json格式,再还原数据时默认会将对象类型还原为JSONObject类型,参考如下:

{
    "age": 32767,
    "amount": 10,
    "flag": true,
    "id": 9223372034707292160,
    "name": "chendd",
    "pi": 3.141592653589793,
    "points": [
        {
            "x": 1,
            "y": 2
        },
        {
            "x": 11,
            "y": 22
        }
    ],
    "sex": "Boy"
}

C.若是使用jackson中的GenericJackson2JsonRedisSerializer序列化的数据则对象类型包含了class,BigDecimal类型被序列化为了数组,List类型也有变形,如下格式,参考如下:

{
    "@class": "cn.chendd.redis.RedisDataTypeListBoTest$User",
    "id": -9223372034707292161,
    "name": "redis",
    "age": -32768,
    "pi": 3.141592653589793,
    "amount": [
        "java.math.BigDecimal",
        123456.789
    ],
    "flag": false,
    "sex": {
        "text": "女"
    },
    "points": [
        "java.util.ArrayList",
        [
            {
                "@class": "java.awt.Point",
                "x": 111,
                "y": 222
            },
            {
                "@class": "java.awt.Point",
                "x": 333,
                "y": 444
            }
        ]
    ]
}


 点赞


 发表评论

当前回复:作者

 评论列表


留言区