PageImpl 反序列化期间出错:无法构造“org.springframework.data.domain.PageImpl”的实例

Tan*_*lly 13 fasterxml spring-boot spring-cache spring-data-commons jackson2

问题是当将 Spring 缓存与 Redis 缓存管理器一起使用时,由于没有默认构造函数,无法反序列化 Spring Pageable 响应

使用的spring boot版本是2.1.4.RELEASE

使用序列化器的 Redis 配置类

@Bean
public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
    RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues()
        .serializeValuesWith(
            RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));

    redisCacheConfiguration.usePrefix();

    return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
            .cacheDefaults(redisCacheConfiguration).build();
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用 Spring 缓存和 Redis 作为缓存后端在 Redis 缓存中缓存 Spring REST API 页面结果响应

@GetMapping
@Cacheable("Article_Response_Page")
public Page<Article> findAll(Pageable pageable) {
    return articleRepository.findAll(pageable);
}
Run Code Online (Sandbox Code Playgroud)

我可以Page<Article>使用序列化程序在 Redis 缓存中看到以 JSON 形式缓存,RedisSerializer.json()但在下一次调用期间,当从缓存中读取数据时,出现以下异常

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot 
construct instance of `org.springframework.data.domain.PageImpl` (no 
Creators, like default construct, exist): cannot deserialize from Object 
value (no delegate- or property-based Creator)
at [Source: (byte[])" 
{"@class":"org.springframework.data.domain.PageImpl","content": 
["java.util.Collections$UnmodifiableRandomAccessList",[]],"pageable": 
{"@class":"org.springframework.data.domain.PageRequest","sort":{"@class":"org.springframework.data.domain.Sort","sorted":false,"unsorted":true,"empty":true},"offset":0,"pageSize":20,"pageNumber":0,"paged":true,"unpaged":false},"totalPages":0,"totalElements":0,"last":true,"size":20,"number":0,"sort":{"@class":"org.springframework.data.domain.Sort","sorted":false,"uns"[truncated 73 bytes]; line: 1, column: 54]
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.8.jar:2.9.8]
Run Code Online (Sandbox Code Playgroud)

我尝试为 PageImpl 提供自定义序列化程序,然后我得到了 PageRequest 实现和 Sort 实现 Spring 'org.springframework.data.domain' 包的所有部分的异常

必须有更好的方法来解决这个问题,我想知道在 spring 缓存中解决此类问题的最佳方法

这是转移到 SPRING BOOT v2 后的 Jackson 错误吗?

att*_*los 9

创建简单的 REST 接口时我遇到了同样的问题。我的解决方案是扩展 PageImpl 并指定所需的 JsonProperties,同时显式忽略其他属性:

@JsonIgnoreProperties(ignoreUnknown = true, value = {"pageable"})
public class RestPage<T> extends PageImpl<T> {
    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
    public RestPage(@JsonProperty("content") List<T> content,
                     @JsonProperty("number") int page,
                     @JsonProperty("size") int size,
                     @JsonProperty("totalElements") long total) {
        super(content, PageRequest.of(page, size), total);
    }

    public RestPage(Page<T> page) {
        super(page.getContent(), page.getPageable(), page.getTotalElements());
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以按照以下方式编写控制器:

@GetMapping
@Cacheable("Article_Response_Page")
public RestPage<Article> findAll(Pageable pageable) {
    return new RestPage<>(articleRepository.findAll(pageable));
}
Run Code Online (Sandbox Code Playgroud)


Tan*_*lly 1

我暂时使用 JAVA 序列化器解决了这个问题,但想知道如何在打开 JSON 值序列化器的情况下解决这个问题

RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues()
        .serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.java()));
Run Code Online (Sandbox Code Playgroud)