【问题标题】:Caching Java 8 Optional with Spring Cache使用 Spring Cache 缓存 Java 8 可选
【发布时间】:2016-04-23 00:11:27
【问题描述】:

我有一个方法:

@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 错误 [trace=,span=] http-nio-8021-exec-2 [dispatcherServlet]:182 - Servlet.service() 用于 servlet [dispatcherServlet] 在上下文中的路径[] 抛出异常 [请求处理失败;嵌套异常是 org.springframework.data.redis.serializer.SerializationException: 无法序列化;嵌套异常是 org.springframework.core.serializer.support.SerializationFailedException: 无法使用 DefaultSerializer 序列化对象;嵌套异常是 java.lang.IllegalArgumentException: DefaultSerializer 需要一个可序列化的有效负载,但收到了一个 [java.util.Optional]] 类型的对象,其根本原因 java.lang.IllegalArgumentException:DefaultSerializer 需要一个可序列化的有效负载,但收到了一个 [java.util.Optional] 类型的对象

【问题讨论】:

  • 可选是不可序列化的类。尝试使用不同类型的对象。也许JobInfo 本身?你的JobInfo 应该实现Serializable 接口。

标签: spring spring-cache


【解决方案1】:

只需在你的 DTO 中实现 Serializable 接口

@Document(collection = "document_name")
public class Document implements Serializable {

    private static final long serialVersionUID = 7156526077883281623L;

【讨论】:

    【解决方案2】:

    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;
    }
    

    请注意,这只是一个示例,我没有测试这个实现。但是我在生产环境中使用 Kryo 序列化程序以与 Spring 相同的方式进行 redis 缓存。

    【讨论】:

    • 这个刚刚被弃用
    【解决方案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

    【讨论】:

      猜你喜欢
      • 2016-08-19
      • 1970-01-01
      • 2019-08-08
      • 2017-06-18
      • 1970-01-01
      • 2014-05-01
      • 2014-10-12
      • 1970-01-01
      • 2021-05-10
      相关资源
      最近更新 更多