在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的可观测性提高了许多,好了下课