You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Redis缓存时@Cacheable/@CachePut序列化失败问题

Redis缓存序列化错误解决方案

问题原因

你的@Cacheable和@CachePut注解标注在Controller层方法上,这些方法返回的是ResponseEntity<AccountDTO>——这是Spring的HTTP响应包装类,默认Redis缓存序列化器(JdkSerializationRedisSerializer)无法正确序列化该类型;另外,若你的AccountDTO未实现Serializable接口,也会触发序列化失败。而@CacheEvict仅执行缓存键删除操作,无需序列化对象,因此功能正常。

解决方案

方案1:将缓存注解移至Service层(推荐)

缓存的核心是业务数据而非HTTP响应,将缓存注解放在Service层,直接缓存AccountDTO对象,更符合业务逻辑:

修改Service层代码

@Service
@AllArgsConstructor
@CacheConfig(cacheNames = "account")
public class AccountService {
    private AccountRepository repository;
    private ModelMapper mapper;

    // 缓存根据用户名查询的AccountDTO
    @Cacheable(key = "#name")
    public AccountDTO getAccount(String name) {
        Account account = repository.findByHolderName(name);
        return mapper.map(account, AccountDTO.class);
    }

    // 更新缓存中的账户数据
    @CachePut(key = "#id")
    public AccountDTO deposit(Long id, Double value) {
        Account account = repository.findById(id)
                .orElseThrow(() -> new RuntimeException("账户不存在"));
        account.setBalance(account.getBalance() + value);
        repository.save(account);
        return mapper.map(account, AccountDTO.class);
    }
}

修改Controller层代码

移除Controller层的@Cacheable和@CachePut注解:

@Controller
@RequestMapping("bank")
@AllArgsConstructor
@CacheConfig(cacheNames = "account")
public class AccountController {
    private AccountService service;

    // ... 其他方法不变

    @GetMapping("holderName/{name}")
    public ResponseEntity<AccountDTO> getAccountByName(@PathVariable String name){
        return new ResponseEntity<>(service.getAccount(name),HttpStatus.ACCEPTED);
    }

    @PutMapping("{id}/deposit")
    public ResponseEntity<AccountDTO> deposit(@PathVariable Long id, @RequestBody Map<String, Double> request){
        Double value = request.get("balance");
        return new ResponseEntity<>(service.deposit(id,value), HttpStatus.ACCEPTED);
    }

    // ... 其他方法不变
}

方案2:配置Redis Jackson序列化器(若坚持在Controller层缓存)

若需在Controller层缓存ResponseEntity<AccountDTO>,需配置Redis使用Jackson序列化器,并确保AccountDTO实现Serializable:

1. 让AccountDTO实现Serializable

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AccountDTO implements Serializable {
    private Long id;
    private String holderName;
    private double balance;
}

2. 添加Redis缓存配置类

@Configuration
@EnableCaching
public class RedisCacheConfig {

    @Bean
    public RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存过期时间
                .entryTtl(Duration.ofMillis(60000))
                // 键使用字符串序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 值使用Jackson序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)))
                // 不缓存null值
                .disableCachingNullValues();
    }
}

额外检查点

  • 确认Redis服务正常运行,端口、主机配置与application.properties一致
  • 若使用Jackson序列化,需确保项目中有com.fasterxml.jackson.core:jackson-databind依赖(Spring Boot starter通常已包含)

内容的提问来源于stack exchange,提问作者Sakib X Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:17:04