修改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=[])]) 總部