SpringCache的集成redis序列化格式优化
redis序列化和反序列化
采用Jackson实现【数据库】-【redis】-【客户端】数据结构一致性
public class JacksonRedisSerializer<T> implements RedisSerializer<T> {
private final ObjectMapper objectMapper = new ObjectMapper();
public JacksonRedisSerializer(JavaTimeModule module) {
objectMapper.setSerializationInclusion(Include.NON_NULL);
objectMapper.registerModule(module);
}
@Override
public byte[] serialize(T t) throws SerializationException {
try {
// 序列化时 不写出类型信息,只写出与返回到前端一直的格式, 实现数据库-redis-客户端数据一致性
// 若写出类型信息:如
return objectMapper.writeValueAsBytes(t);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
// 反序列化时,通过获取方法返回值的泛型声明信息构造JavaType,传递给Jackson反序列化
Type returnType = CacheResultTypeContext.getReturnType();
if (returnType == null) {
throw new RuntimeException("请先配置返回值类型");
}
JavaType javaType = objectMapper.constructType(returnType);
try {
return objectMapper.readValue(bytes, javaType);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
携带类型信息的JSON
{
"@class": "cn.dev33.satoken.dao.SaSessionForJacksonCustomized",
"id": "token:login:session:1",
"createTime": 1694179443112,
"dataMap": {
"@class": "java.util.concurrent.ConcurrentHashMap"
},
"tokenSignList": [
"java.util.Vector",
[
{
"@class": "cn.dev33.satoken.session.TokenSign",
"value": "5zcJ4CrzcfqxPH5ODigwhCAbHZYGKo5T",
"device": "default-device"
}
]
]
}
不携带类型信息的JSON
[
{
"id": "1",
"createBy": "1",
"createTime": "2023-08-10 22:50:29.000",
"updateBy": "1",
"updateTime": "2023-08-10 22:50:28.000",
"name": "系统管理员",
"category": "默认",
"orderNo": 1,
"status": 1
}
]
采用AOP拦截并保存方法返回类型信息
@Component
@Aspect
@Order(-1) // 需要比redis serializer 提前执行
public class CacheResultTypeAop {
// CacheResultType用于标识方法返回值类型信息
@Around(value = "@annotation(org.springframework.cache.annotation.Cacheable) || @annotation(org.springframework.cache.annotation.CachePut) || @annotation(org.springframework.cache.annotation.Caching)")
public Object run(JoinPoint joinPoint) throws Throwable {
Type returnType = null;
if (joinPoint.getSignature() instanceof MethodSignature signature) {
// 获取返回类型 并 携带泛型信息
returnType = signature.getMethod().getGenericReturnType();
}
try {
CacheResultTypeContext.setType(returnType);
return ((MethodInvocationProceedingJoinPoint) joinPoint).proceed(joinPoint.getArgs());
} finally {
CacheResultTypeContext.remove();
}
}
}
下一篇: ③优雅的缓存框架:SpringCache增强支持自定义过期时间TTL
以上代码来源: 后端代码:github.com/L1yp/van-te…
点击链接加入群聊:【Van交流群】