在SpringBoot的redisTemplate在redis当中存入数据的时候,能看到key和value被序列化,我们基本上很难判断这个缓存是干什么用的,所以我们需要修复它:
解决这个问题我们需要自定义一个序列化器RedisJsonSerializerImpl,其中还有一个内部类:
/** * <p> * 序列化对象,将对象存入这个类中然后存入redis * </p> * * @author XiaoHH * @version 1.0 * @date 2021-12-07 星期二 14:45:54 */ static class SerializerObject { /** * 无参构造 */ public SerializerObject() { } /** * 全参构造 * * @param className 对象的类名 * @param jsonObject 将内容对象转换为json字符串之后的结果 */ public SerializerObject(String className, String jsonObject) { this.className = className; this.jsonObject = jsonObject; } /** * 对象的类名 */ private String className; /** * 将内容对象转换为json字符串之后的结果 */ private String jsonObject; public String getClassName() { return className; } public SerializerObject setClassName(String className) { this.className = className; return this; } public String getJsonObject() { return jsonObject; } public SerializerObject setJsonObject(String jsonObject) { this.jsonObject = jsonObject; return this; } /** * 将本对象转换为json格式 * * @return 转换后的json */ @Override public String toString() { return JSON.toJSONString(this); } }
RedisJsonSerializerImpl实现了org.springframework.data.redis.serializer.RedisSerializer,并且实现下面两个方法,serialize方法定义了序列化对象(将对象从Java程序中存入缓存中),deserialize用户反序列化对象(将缓存中读取对象并转换为Java对象):
/** * 将对象序列化成一个 byte 数组 * * @param t 对象的实例 * @return 序列化后的结果 * @throws SerializationException 可能会抛出序列化异常 */ @Override public byte[] serialize(T t) throws SerializationException { // 如果对象为空,那么就返回一个空的byte数组就好了 if (null == t) return new byte[0]; // 获取序列化后的对象 String resultObject = new SerializerObject(t.getClass().getName(), JSON.toJSONString(t)).toString(); return resultObject.getBytes(StandardCharsets.UTF_8); } /** * 将一个已经序列化好后的对象转换为一个真实的对象,并返回它 * * @param bytes 序列化后的结果 * @return 反序列化后的结果 * @throws SerializationException 可能会抛出序列化异常 */ @Override public T deserialize(byte[] bytes) throws SerializationException { if (CollectionUtils.isNull(bytes)) return null; // 将其反序列化成一个字符串 SerializerObject resultObject = JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), SerializerObject.class); try { return JSON.parseObject(resultObject.jsonObject, (Type) Class.forName(resultObject.className)); } catch (ClassNotFoundException e) { log.error("类未找到:" + resultObject.className, e); return null; } }
类完整的代码如下:
package love.xiaohh.cost.utils.storage; import com.alibaba.fastjson.JSON; import love.xiaohh.cost.utils.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; /** * <p> * 存入redis的时候处理对象格式化的问题 * </p> * * @author XiaoHH * @version 1.0 * @date 2021-12-07 星期二 14:33:54 * @file RedisJsonSerializerImpl.java */ public class RedisJsonSerializerImpl<T> implements RedisSerializer<T> { /** * 记录日志的对象 */ private static final Logger log = LoggerFactory.getLogger(RedisJsonSerializerImpl.class); /** * 将对象序列化成一个 byte 数组 * * @param t 对象的实例 * @return 序列化后的结果 * @throws SerializationException 可能会抛出序列化异常 */ @Override public byte[] serialize(T t) throws SerializationException { // 如果对象为空,那么就返回一个空的byte数组就好了 if (null == t) return new byte[0]; // 获取序列化后的对象 String resultObject = new SerializerObject(t.getClass().getName(), JSON.toJSONString(t)).toString(); return resultObject.getBytes(StandardCharsets.UTF_8); } /** * 将一个已经序列化好后的对象转换为一个真实的对象,并返回它 * * @param bytes 序列化后的结果 * @return 反序列化后的结果 * @throws SerializationException 可能会抛出序列化异常 */ @Override public T deserialize(byte[] bytes) throws SerializationException { if (CollectionUtils.isNull(bytes)) return null; // 将其反序列化成一个字符串 SerializerObject resultObject = JSON.parseObject(new String(bytes, StandardCharsets.UTF_8), SerializerObject.class); try { return JSON.parseObject(resultObject.jsonObject, (Type) Class.forName(resultObject.className)); } catch (ClassNotFoundException e) { log.error("类未找到:" + resultObject.className, e); return null; } } /** * <p> * 序列化对象,将对象存入这个类中然后存入redis * </p> * * @author XiaoHH * @version 1.0 * @date 2021-12-12 星期日 09:45:54 */ static class SerializerObject { /** * 无参构造 */ public SerializerObject() { } /** * 全参构造 * * @param className 对象的类名 * @param jsonObject 将内容对象转换为json字符串之后的结果 */ public SerializerObject(String className, String jsonObject) { this.className = className; this.jsonObject = jsonObject; } /** * 对象的类名 */ private String className; /** * 将内容对象转换为json字符串之后的结果 */ private String jsonObject; public String getClassName() { return className; } public SerializerObject setClassName(String className) { this.className = className; return this; } public String getJsonObject() { return jsonObject; } public SerializerObject setJsonObject(String jsonObject) { this.jsonObject = jsonObject; return this; } /** * 将本对象转换为json格式 * * @return 转换后的json */ @Override public String toString() { return JSON.toJSONString(this); } } }
然后我们定义一个RedisConfig,将设置这个序列化对象:
package love.xiaohh.cost.configurations; import love.xiaohh.cost.constants.Constants; import love.xiaohh.cost.utils.storage.RedisJsonSerializerImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * <p> * redis相关的配置类 * </p> * * @author XiaoHH * @version 1.0 * @date 2021-12-12 星期日 09:54:59 * @file RedisConfig.java */ @Configuration public class RedisConfig { /** * 定义redisTemplate对象,用于访问redis * * @param redisConnectionFactory redis的链接工厂,从Spring容器中获取 * @return 自行配置好的redis访问对象 */ @Bean(Constants.REDISTEMPLATE) public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { // 缓存操作对象 RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); // 设置链接工厂 redisTemplate.setConnectionFactory(redisConnectionFactory); // 键的序列化器 redisTemplate.setKeySerializer(new StringRedisSerializer()); // 值的序列化器,这里我们用的是我们自己配置好的 redisTemplate.setValueSerializer(new RedisJsonSerializerImpl<>()); return redisTemplate; }
其中key的序列化器使用自带的 StringRedisSerializer,然后value序列化使用我们自定义的 RedisJsonSerializerImpl,这个类就定义好了,我们运行看看效果:
可以发现key和value的可观测性提高了许多,好了下课