zoukankan      html  css  js  c++  java
  • spring-data-redis序列化实践笔记

    (一)spring data redis 提供了多种可选择策略(RedisSerializer)
    • JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。

    • StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。

    • JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】

    • OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】



     spring-data-redis提供了多种serializer策略,这对使用jedis的开发者而言,实在是非常便捷。sdr提供了4种内置的serializer:

    • JdkSerializationRedisSerializer:使用JDK的序列化手段(serializable接口,ObjectInputStrean,ObjectOutputStream),数据以字节流存储
    • StringRedisSerializer:字符串编码,数据以string存储
    • JacksonJsonRedisSerializer:json格式存储
    • OxmSerializer:xml格式存储

        其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略,其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。

        RedisTemplate中需要声明4种serializer,默认为“JdkSerializationRedisSerializer”:

        1) keySerializer :对于普通K-V操作时,key采取的序列化策略
        2) valueSerializer:value采取的序列化策略
        3) hashKeySerializer: 在hash数据结构中,hash-key的序列化策略
        4) hashValueSerializer:hash-value的序列化策略

        无论如何,建议key/hashKey采用StringRedisSerializer。

        接下来,通过实例描述如何使用它们,可以首先参考“spring-data-redis特性”:




    (二)尝试其中三种

        @Bean
        public RedisTemplate<String, Object> jdkRedisTemplate(
                RedisConnectionFactory factory) {
            RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
            template.setConnectionFactory(factory);
    
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
                ObjectMapper om = new ObjectMapper();
                om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
                om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
    
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    
            template.setValueSerializer(jdkSerializationRedisSerializer);
            template.setKeySerializer(stringRedisSerializer);
    
            template.setHashKeySerializer(stringRedisSerializer);
            template.setHashValueSerializer(jdkSerializationRedisSerializer);
    
            template.afterPropertiesSet();
            return template;
        }


        @Resource(name = "jdkRedisTemplate")   // if stringRedisTemplate, result in SmsCheck cannot be cast to java.lang.String
        private RedisTemplate<String, Object> jdkRedisTemplate;



        @RequestMapping(value = "testRedis", method = RequestMethod.POST)
        @ResponseBody
        @ApiImplicitParams({})
        @ApiOperation(value="testRedis")
        public Object testRedis() {
    
            SmsCheck smsCheck = new SmsCheck();
            smsCheck.setMobile("xxx");
    
            // 设置缓存
            jdkRedisTemplate.opsForValue().set("test",smsCheck);
    
    
            return null;
        }

    @Entity
    public class SmsCheck implements Serializable {
    	private static final long serialVersionUID = 1L;
    
    	@Id
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	@Column(name = "sms_check_id")
    	private int smsCheckId;
    
    	private String mobile;
    
    	。。。。。。
    



    仅对value操作,保持key为string序列化

    1.jdk序列化方案

    get test 显示

    "xacxedx00x05srx00x1ecom.ilex.xxx.model.SmsCheckx00x00x00x00x00x00x00x01x02x00x05Ix00 smsCheckIdLx00acontenttx00x12Ljava/lang/String;Lx00 createDatetx00x10Ljava/util/Date;Lx00x06mobileqx00~x00x01Lx00x04typeqx00~x00x01xpx00x00x00x00pptx00x03xxxp"


    注意:若这里的SmsCheck未实现Serializable接口,会抛出一个异常



    2.string

    直接抛出异常

    SmsCheck cannot be cast to java.lang.String



    3 json
     

    "["com.xxx.xx.model.SmsCheck",{"smsCheckId":0,"mobile":"xxx","type":null,"content":null,"createDate":null}]"




    然后将key的序列化改为jdk

    1) "xacxedx00x05tx00x04test"

    2) "test"


    显示key也被jdk序列化了



    redistemplate 默认用jdk序列化key和value
    stringredistemplate默认用string序列化key和value


    (三)关于序列化后redis视图主要参考此贴:


    最近在开始在学习Redis以及如何在Java当中去使用Redis,Redis是什么我这里就不说了。

    我主要想说的是Redis和Java当中Spring结合起来的时候,使用到的RedisTemplate和StringRedisTemplate

    他们两者之间的区别,以及该怎么使用。

    RedisTemplate看这个类的名字后缀是Template,如果了解过Spring如何连接关系型数据库的,大概不会难猜出这个类
    是做什么的 ,它跟JdbcTemplate一样封装了对Redis的一些常用的操作,当然StringRedisTemplate跟RedisTemplate功能类似
    那么肯定就会有人问,为什么会需要两个Template呢,一个不就够了吗?
    其实他们两者之间的区别主要在于他们使用的序列化类。
    RedisTemplate使用的是JdkSerializationRedisSerializer
    StringRedisTemplate使用的是StringRedisSerializer

    RedisTemplate使用的序列类在在操作数据的时候,比如说存入数据会将数据先序列化成字节数组
    然后在存入Redis数据库,这个时候打开Redis查看的时候,你会看到你的数据不是以可读的形式
    展现的,而是以字节数组显示,类似下面

    当然从Redis获取数据的时候也会默认将数据当做字节数组转化,这样就会导致一个问题,当需要获取的
    数据不是以字节数组存在redis当中而是正常的可读的字符串的时候,比如说下面这种形式的数据


     

    关于RedisTemplate和StringRedisTemplate




    (四)另外:

    spring-data-redis是对jedis的封装,如果直接使用jedis,需手动
    1序列化对象
    2转为json字符串
    使用,spring自动处理了


  • 相关阅读:
    366. Find Leaves of Binary Tree输出层数相同的叶子节点
    716. Max Stack实现一个最大stack
    515. Find Largest Value in Each Tree Row查找一行中的最大值
    364. Nested List Weight Sum II 大小反向的括号加权求和
    156. Binary Tree Upside Down反转二叉树
    698. Partition to K Equal Sum Subsets 数组分成和相同的k组
    244. Shortest Word Distance II 实现数组中的最短距离单词
    187. Repeated DNA Sequences重复的DNA子串序列
    java之hibernate之基于主键的双向一对一关联映射
    java之hibernate之基于主键的单向一对一关联映射
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106761.html
Copyright © 2011-2022 走看看