修改RedisTemplate的默认序列化配置,默认是使用JDK的序列化,经过本身实现RedisSerializer接口编写须要的序列化方式。java
package cc.xuepeng.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import org.springframework.data.redis.serializer.RedisSerializer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; /** * 使用Alibaba的FastJson做为Json序列化的工具。 * * @param <T> * @author xuepeng */ public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { /** * 默认的转换编码。 */ private static final Charset DEFAULT_CHARSET = Charset.forName(StandardCharsets.UTF_8.name()); /** * 要转换的类的Class对象。 */ private Class<T> clazz; /** * 构造函数。 * * @param clazz 设置要序列化的对象的Class对象。 */ public FastJsonRedisSerializer(Class<T> clazz) { super(); this.clazz = clazz; } /** * 序列化对象。 * * @param object 要被序列化的对象。 * @return 序列化成字节数组。 */ @Override public byte[] serialize(T object) { if (object == null) { return new byte[0]; } return JSON.toJSONString(object, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } /** * 反序列化对象。 * * @param bytes 字节数组。 * @return 要序列化的对象。 */ @Override public T deserialize(byte[] bytes) { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return JSON.parseObject(str, clazz); } }
package cc.xuepeng.config; import com.alibaba.fastjson.JSON; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; /** * 自定义StringRedisSerializer列化器。 * 原生的StringRedisSerializer在使用@Cacheable注解时,当key不是String类型会发生错误。 * 由于原生的StringRedisSerializer只支持String。 * * @author xuepeng */ public class StringRedisSerializer implements RedisSerializer<Object> { /** * 默认的转换编码。 */ private final Charset charset; /** * 反斜杠符号。 */ private static final String TARGET = "\""; /** * 空格符号。 */ private static final String REPLACEMENT = ""; /** * 构造函数。 */ public StringRedisSerializer() { this(Charset.forName(StandardCharsets.UTF_8.name())); } /** * 构造函数。 * * @param charset 转换编码。 */ public StringRedisSerializer(Charset charset) { Assert.notNull(charset, "Charset must not be null!"); this.charset = charset; } @Override public byte[] serialize(Object object) { String string = JSON.toJSONString(object); if (StringUtils.isEmpty(string)) { return new byte[0]; } string = string.replace(TARGET, REPLACEMENT); return string.getBytes(charset); } @Override public Object deserialize(byte[] bytes) { if (bytes != null) { return new String(bytes, charset); } return null; } }
/** * Redis配置类。 * * @author xuepeng */ @Configuration @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfig { /** * 重写Redis序列化方式,使用Json方式: * 当咱们的数据存储到Redis的时候,咱们的键(key)和值(value)都是经过Spring提供的Serializer序列化到数据库的。 * RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。 * 在此咱们将本身配置RedisTemplate并定义Serializer。 * * @param redisConnectionFactory redis链接工厂。 * @return redisTemplate对象。 */ @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); // 全局开启AutoType,不建议使用 // ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 建议使用这种方式,小范围指定白名单 ParserConfig.getGlobalInstance().addAccept("cc.xuepeng."); // 设置键(key)的序列化采用StringRedisSerializer。 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // 设置值(value)的序列化采用FastJsonRedisSerializer。 redisTemplate.setValueSerializer(fastJsonRedisSerializer); redisTemplate.setHashValueSerializer(fastJsonRedisSerializer); return redisTemplate; } }
@RunWith(SpringRunner.class) @SpringBootTest public class RedisHelloWorldTest { private RedisTemplate<String, Object> redisTemplate; @Autowired void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } @Test public void testGetEntFileById() { redisTemplate.opsForValue().set("hello", "world"); String ret = (String) redisTemplate.opsForValue().get("hello"); Assert.assertEquals("world", ret); } @Test public void testGetUser() { Department department = new Department(); department.setName("总部"); User user = new User("jack", 22, LocalDate.now()); department.getUsers().add(user); Department children = new Department(); children.setName("分部"); department.getChildren().add(children); redisTemplate.opsForHash().put("depts", "01", department); redisTemplate.opsForHash().put("depts", "02", department); redisTemplate.opsForHash().put("depts", "03", department); Department dept1 = (Department) redisTemplate.opsForHash().get("depts", "01"); System.out.println(dept1); Map<Object, Object> map = redisTemplate.opsForHash().entries("depts"); Department d = (Department) map.get("01"); System.out.println(d.getName()); } }
输出:redis
Department(name=总部, users=[User(name=jack, age=22, birthday=2019-12-23)], children=[Department(name=分部, users=[], children=[])]) 总部