Redis之SpringDataRedis对象写入到Redis中

    业务场景中常常遇到使用Redis做为缓存,而将对象写入Redis更是常见的。下面来看下,对象写入Redis的俩种方式(我以前就知道除了JDK,还有其它的诸如Jackson提供序列化功能,可是JDK以外的其它第三方在方序列化的时候提供目标对象class,不过今天我发现Spring-data-redis自带的这个GenericJackson2JsonRedisSerializer解决了个人烦恼)。java

1.公用配置

    List-1 链接池和ConnectionFactory配置redis

<bean id="pool" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxTotal" value="30"/>
    <property name="maxIdle" value="10"/>
    <property name="minEvictableIdleTimeMillis" value="100000"/>
    <property name="numTestsPerEvictionRun" value="1024"/>
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <!--<constructor-arg name="sentinelConfig" ref="redisSentinelConfiguration"/>-->
    <constructor-arg name="poolConfig" ref="pool"/>
    <property name="hostName" value="localhost"/>
    <property name="port" value="6379"/>
    <property name="database" value="7"/>
</bean>

2.用JDK序列化方式

    List-2 使用JDK的序列化方式spring

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory"/>
    <property name="keySerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
</bean>

    如List-2所示,咱们要将keySerializer和valueSerializer的值设置为JdkSerializationRedisSerializer。json

3.用Jackson方式

    List-2 使用Jackson做为序列化缓存

<bean id="jacksonRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory"/>
    <property name="keySerializer">
        <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    </property>
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
    </property>
</bean>

    咱们都知道Jackson反序列化的时候,都须要传入目标对象class,这里咱们并不须要指定目标class,那么问题来了,它是怎么作到在使用者不提供目标class的状况下,方序列化的呢?bash

    先来定义实体类,以下List-3和List-4this

    List-3 Department.javaspa

/**
 * @author dmj1161859184@126.com 2018-09-18 01:21
 * @version 1.0
 * @since 1.0
 */
@Data
public class Department {
    private String name;
    private List<OfficeStaff> officeStaffs;
    private List<String> strings = Collections.emptyList();
    private String other;

    public Department(String name, List<OfficeStaff> officeStaffs, List<String> strings) {
        this.name = name;
        this.officeStaffs = officeStaffs;
        this.strings = strings;
    }
}

    List-4  OfficeStaff.javacode

/**
 * @author dmj1161859184@126.com 2018-09-18 01:22
 * @version 1.0
 * @since 1.0
 */
@Data
@AllArgsConstructor
public class OfficeStaff {
    private String name;
    private Integer age;
}

    以下List-5所示,Jackson序列化方式将Department写入Redis后,对象被转换为json字符串,同时,还有额外的"@class"字段表示对象类型。看到这个"@class",应该明白了,这个在方序列化的时候用到,因为在序列化写入Redis的时候就将对象类型写入到Redis了,因此方序列化的时候不须要提供目标对象class。xml

    List-5 Department对象在Redis中存储的是json

127.0.0.1:6379[7]> get "\"System\""
"{\"@class\":\"com.mjduan.project.objectRedisTemplate.model.Department\",\"name\":\"System\",\"officeStaffs\":[\"java.util.ArrayList\",[{\"@class\":\"com.mjduan.project.objectRedisTemplate.model.OfficeStaff\",\"name\":\"Jack\"}]],\"other\":\"other\"}"
127.0.0.1:6379[7]>

    注:除了引入Spring-data-redis和Jedis,还须要引入jackson的依赖,我使用的版本以下List-6:

    List-6

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.8.8</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.8</version>
</dependency>

3.选型

    在将对象序列化到Redis中时,该选择JDK方式仍是Jackson方式,我会选择使用Jackson的方式,why,由于JDK序列化方式很大的一个限制就是要求对象必须实现Serializable,并且是递归的(好比类A有个属性类B,那么类A和类B都要实现Serializable),特别是对遗留系统,不少存入缓存的对象颇有可能没有实现Serializable,若是使用JDK序列化方式的话,须要确认全部的对象都实现了Serializable,这个很耗时,且不必定能彻底覆盖。固然了,选择Jackson序列化方式,也有未知的问题,只是目前还没遇到。

思考:

  1. List-5中,Department并无名为"@class"的属性,那么它是怎么被添加进去的呢,这个问题暂时不研究了。
相关文章
相关标签/搜索