redis 序列化 支持 PageImpl 既然 Redis 序列化器配置了activateDefaultTyping且不能修改那就只能让PageImpl具备被 Jackson 反序列化的能力。一、核心思路textJackson 反序列化 PageImpl 失败的原因 ↓ PageImpl 没有无参构造器 ↓ 解决方案为 PageImpl 添加反序列化支持不修改 Redis 配置 ↓ 方式1Jackson Mixin推荐 方式2自定义反序列化器并注册到 Redis 的 ObjectMapper 方式3在 Redis 配置中注入自定义 ObjectMapper二、方案一Jackson Mixin推荐最简洁通过 Mixin 为PageImpl提供JsonCreator注解告诉 Jackson 如何构造PageImpl对象。1. 创建 Mixin 类javaimport com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import java.util.List; /** * PageImpl 的 Jackson Mixin用于提供反序列化支持 */ public abstract class PageImplMixinT { JsonCreator public PageImplMixin( JsonProperty(content) ListT content, JsonProperty(page) int page, JsonProperty(size) int size, JsonProperty(total) long total) { // Mixin 方法不需要实现只用于注解 } // 如果 pageable 是完整对象也可以支持 JsonCreator public PageImplMixin( JsonProperty(content) ListT content, JsonProperty(pageable) Pageable pageable, JsonProperty(total) long total) { // 另一个构造方法签名 } }2. 在 Redis 配置中注册 Mixin找到 Redis 序列化器配置的地方添加 MixinjavaConfiguration public class RedisConfig { Bean public RedisCacheManager cacheManager(RedisConnectionFactory factory) { // 1. 创建 ObjectMapper ObjectMapper mapper new ObjectMapper(); // 2. 注册 PageImpl 的 Mixin mapper.addMixIn(PageImpl.class, PageImplMixin.class); // 3. 注册 JavaTimeModule支持 LocalDate/LocalDateTime mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 4. 保留原有的 DefaultTyping 配置 mapper.activateDefaultTyping( mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY ); // 5. 创建序列化器 Jackson2JsonRedisSerializerObject serializer new Jackson2JsonRedisSerializer(Object.class); serializer.setObjectMapper(mapper); // 6. 配置 RedisCacheManager RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)) .entryTtl(Duration.ofHours(1)); return RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); } }三、方案二自定义反序列化器更精细控制如果 Mixin 方式不生效可以编写一个完整的PageImpl反序列化器。1. 创建反序列化器javaimport com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import java.io.IOException; import java.util.List; public class PageImplDeserializer extends StdDeserializerPageImpl? { public PageImplDeserializer() { super(PageImpl.class); } Override public PageImpl? deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node p.getCodec().readTree(p); // 1. 解析 content JsonNode contentNode node.get(content); List? content p.getCodec().treeToValue(contentNode, List.class); // 2. 解析 total JsonNode totalNode node.get(total); long total totalNode ! null ? totalNode.asLong() : 0L; // 3. 解析 pageable JsonNode pageableNode node.get(pageable); Pageable pageable; if (pageableNode null || pageableNode.isNull()) { // 如果 pageable 不存在从 page/size 构建 int page node.has(page) ? node.get(page).asInt() : 0; int size node.has(size) ? node.get(size).asInt() : 20; pageable PageRequest.of(page, size); } else if (pageableNode.isTextual() INSTANCE.equals(pageableNode.asText())) { // 处理 Unpaged.INSTANCE pageable Pageable.unpaged(); } else { // 从 pageable 对象解析 int page pageableNode.has(pageNumber) ? pageableNode.get(pageNumber).asInt() : 0; int size pageableNode.has(pageSize) ? pageableNode.get(pageSize).asInt() : 20; pageable PageRequest.of(page, size); } return new PageImpl(content, pageable, total); } }2. 注册到 Redis ObjectMapperjavaConfiguration public class RedisConfig { Bean public RedisCacheManager cacheManager(RedisConnectionFactory factory) { ObjectMapper mapper new ObjectMapper(); // 注册 PageImpl 反序列化器 SimpleModule module new SimpleModule(); module.addDeserializer(PageImpl.class, new PageImplDeserializer()); mapper.registerModule(module); // 其他配置... mapper.registerModule(new JavaTimeModule()); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); mapper.activateDefaultTyping( mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY ); Jackson2JsonRedisSerializerObject serializer new Jackson2JsonRedisSerializer(Object.class); serializer.setObjectMapper(mapper); RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)) .entryTtl(Duration.ofHours(1)); return RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); } }四、方案三直接修改 Redis 配置类如果可访问如果 Redis 配置类是可访问的直接在你现有的RedisConfig中添加 MixinjavaConfiguration public class RedisConfig { Bean public RedisCacheManager cacheManager(RedisConnectionFactory factory) { // 获取现有的 ObjectMapper ObjectMapper mapper new ObjectMapper(); // ✅ 添加这一行注册 PageImpl 的 Mixin mapper.addMixIn(PageImpl.class, PageImplMixin.class); // 保留原有配置 mapper.activateDefaultTyping( mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY ); // ... 其他配置 } }五、方案对比方案改动量复杂度推荐度Mixin小新增1个类1行配置低⭐⭐⭐⭐⭐自定义反序列化器中新增1个类注册逻辑中⭐⭐⭐⭐修改现有 Redis 配置最小只加1行最低⭐⭐⭐⭐⭐六、最终推荐使用 Mixin 方案这是最简洁、最优雅的方式java// 1. 创建 Mixin 类只需要注解不需要实现 public abstract class PageImplMixinT { JsonCreator public PageImplMixin( JsonProperty(content) ListT content, JsonProperty(page) int page, JsonProperty(size) int size, JsonProperty(total) long total) {} } // 2. 在 Redis 配置中注册 mapper.addMixIn(PageImpl.class, PageImplMixin.class);这样✅ 不需要修改 Redis 序列化器的activateDefaultTyping配置✅ 支持PageImpl的反序列化✅ 不影响其他类型✅ 改动量最小