Кэширование Java 8 (необязательно) с помощью Spring Cache

У меня есть метод:

@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() для сервлета [dispatcherServlet] в контексте с путем [] бросил исключение [Ошибка обработки запроса; вложенным исключением является 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.Необязательно]


person Roi Ezra    schedule 17.01.2016    source источник
comment
Необязательный не является сериализуемым классом. Попробуйте использовать другой тип объекта. Может быть, JobInfo сам? Ваш JobInfo должен реализовать Serializable интерфейс.   -  person RMachnik    schedule 18.01.2016


Ответы (3)


Просто внедрите интерфейс Serializable в свой DTO.

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

    private static final long serialVersionUID = 7156526077883281623L;
person Ishan Ojha    schedule 06.11.2018

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 в производстве таким же образом для кэширования Redis с помощью Spring.

person Cyril    schedule 17.01.2016
comment
этот просто устарел - person aswzen; 18.03.2019

Поскольку ваш сериализованный объект не реализует 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;

....
}

Более подробную информацию и принципы можно найти на странице мой блог

person steven    schedule 06.12.2016