Redis之SpringDataRedis對象寫入到Redis中

    業務場景中經常遇到使用Redis作爲緩存,而將對象寫入Redis更是常見的。下面來看下,對象寫入Redis的倆種方式(我之前就知道除了JDK,還有其它的諸如Jackson提供序列化功能,但是JDK之外的其它第三方在方序列化的時候提供目標對象class,不過今天我發現Spring-data-redis自帶的這個GenericJackson2JsonRedisSerializer解決了我的煩惱)。

1.公用配置

    List-1 連接池和ConnectionFactory配置

<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的序列化方式

<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。

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的情況下,方序列化的呢?

    先來定義實體類,如下List-3和List-4

    List-3 Department.java

/**
 * @author [email protected] 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.java

/**
 * @author [email protected] 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。

    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"的屬性,那麼它是怎麼被添加進去的呢,這個問題暫時不研究了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章