我有一个方法:
@Cacheable(key = "#jobId")
public Optional<JobInfo> getJobById(String jobId) {
log.info("Querying for job " + jobId);
counterService.increment("queryJobById");
Job job = jobsRepository.findOne(jobId);
if (job != null) {
return Optional.of(createDTOFromJob(job));
}
return Optional.empty();
}
当我尝试检索缓存的项目时,我收到以下异常:
2016-01-18 00:01:10 ERROR [trace =,span =] http-nio-8021-exec-2 [dispatcherServlet]:182 - Servlet [dispatcherServlet]的Servlet.service()与路径的上下文[]引发异常[请求处理失败;嵌套异常是org.springframework.data.redis.serializer.SerializationException:无法序列化;嵌套异常是org.springframework.core.serializer.support.SerializationFailedException:无法使用DefaultSerializer序列化对象;嵌套异常是java.lang.IllegalArgumentException:DefaultSerializer需要Serializable有效负载但是收到了一个带有根本原因的[java.util.Optional]类型的对象 java.lang.IllegalArgumentException:DefaultSerializer需要Serializable有效负载,但收到类型为[java.util.Optional]的对象
答案 0 :(得分:6)
Spring支持缓存可选。问题是您的Redis序列化程序(可能是JdkSerializationRedisSerializer)。它使用基于Java的序列化,要求类可以序列化。您可以通过将RedisCacheManager配置为使用没有此限制的其他序列化程序来解决此问题。例如,您可以使用Kryo(com.esotericsoftware:kryo:3.0.3):
@Bean
RedisCacheManager redisCacheManager (RedisTemplate<Object, Object> redisOperations) {
// redisOperations will be injected if it is configured as a bean or create it: new RedisTemplate()...
redisOperations.setDefaultSerializer(new RedisSerializer<Object>() {
//use a pool because kryo instances are not thread safe
KryoPool kryoPool = new KryoPool.Builder(Kryo::new).build();
@Override
public byte[] serialize(Object o) throws SerializationException {
ByteBufferOutput output = new ByteBufferOutput();
Kryo kryo = kryoPool.borrow();
try {
kryo.writeClassAndObject(output, o);
} finally {
kryoPool.release(kryo);
output.close();
}
return output.toBytes();
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if(bytes.length == 0) return null;
Kryo kryo = kryoPool.borrow();
Object o;
try {
o = kryo.readClassAndObject(new ByteBufferInput(bytes));
} finally {
kryoPool.release(kryo);
}
return o;
}
});
RedisCacheManager redisCacheManager = new RedisCacheManager(redisOperations);
redisCacheManager.setCachePrefix(new DefaultRedisCachePrefix("app"));
redisCacheManager.setTransactionAware(true);
return redisCacheManager;
}
请注意,这只是一个例子,我没有测试这个imeplementation。但我在生产中使用Kryo序列化程序以相同的方式使用Spring进行redis缓存。
答案 1 :(得分:3)
因为你的序列化对象没有实现RedisSerializer,或者你可以扩展类JdkSerializationRedisSerializer,它们已经实现了RedisSerializer。
示例代码:
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class YourDTOObject extends JdkSerializationRedisSerializer implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
....
}
更多详情和原则,请访问my blog
答案 2 :(得分:3)
只需在DTO中实现Serializable接口
@Document(collection = "document_name")
public class Document implements Serializable {
private static final long serialVersionUID = 7156526077883281623L;