业务场景中常常遇到使用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序列化方式,也有未知的问题,只是目前还没遇到。