業務場景中常常遇到使用Redis做爲緩存,而將對象寫入Redis更是常見的。下面來看下,對象寫入Redis的倆種方式(我以前就知道除了JDK,還有其它的諸如Jackson提供序列化功能,可是JDK以外的其它第三方在方序列化的時候提供目標對象class,不過今天我發現Spring-data-redis自帶的這個GenericJackson2JsonRedisSerializer解決了個人煩惱)。java
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>
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
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>
在將對象序列化到Redis中時,該選擇JDK方式仍是Jackson方式,我會選擇使用Jackson的方式,why,由於JDK序列化方式很大的一個限制就是要求對象必須實現Serializable,並且是遞歸的(好比類A有個屬性類B,那麼類A和類B都要實現Serializable),特別是對遺留系統,不少存入緩存的對象頗有可能沒有實現Serializable,若是使用JDK序列化方式的話,須要確認全部的對象都實現了Serializable,這個很耗時,且不必定能徹底覆蓋。固然了,選擇Jackson序列化方式,也有未知的問題,只是目前還沒遇到。