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

@Cacheable自定义KeyGenerator不支持响应式类型的问题解决

解决响应式缓存中自定义KeyGenerator返回Mono导致缓存键异常的问题

问题原因

你使用的SimpleKeyGenerator是为同步场景设计的键生成器,它的generate方法要求返回直接的对象实例,但你返回了Mono<SimpleKey>。Spring缓存系统在处理同步KeyGenerator时,会直接调用返回对象的toString()方法,因此MonoMapFuseable这个字符串被当作缓存键的一部分,导致无法识别。

在WebFlux响应式场景下,必须使用专门的ReactiveKeyGenerator接口来生成缓存键——它支持返回响应式类型(如Mono<Object>),Spring的响应式缓存管理器会正确订阅这个流以获取实际的键值。

解决方案

1. 实现ReactiveKeyGenerator接口

替换原有的SimpleKeyGenerator继承逻辑,改用ReactiveKeyGenerator接口,适配响应式场景的键生成需求:

import org.springframework.cache.interceptor.SimpleKey;
import org.springframework.data.redis.cache.ReactiveKeyGenerator;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import java.lang.reflect.Method;
import java.util.Arrays;

public class UserKeyGenerator implements ReactiveKeyGenerator {

    @Override
    public Mono<Object> generate(Object target, Method method, Object... params) {
        return ReactiveSecurityContextHolder.getContext()
                // 获取当前认证上下文
                .map(SecurityContext::getAuthentication)
                // 处理未认证场景,避免空指针
                .defaultIfEmpty(null)
                .map(auth -> {
                    // 合并原方法参数与用户凭证
                    Object[] combinedArgs = Arrays.copyOf(params, params.length + 1);
                    combinedArgs[params.length] = auth != null ? auth.getCredentials() : "anonymous";
                    // 沿用默认SimpleKey的生成逻辑
                    return SimpleKey.of(combinedArgs);
                });
    }
}

2. 注册自定义键生成器为Spring Bean

在配置类中将该键生成器注册为名称为userKeyGenerator的Bean,确保@Cacheable注解能正确引用:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CacheConfig {

    @Bean("userKeyGenerator")
    public ReactiveKeyGenerator userKeyGenerator() {
        return new UserKeyGenerator();
    }
}

3. 确保使用响应式缓存管理器

Spring Boot 3.2.0引入spring-boot-starter-data-redis-reactive后,会自动配置ReactiveRedisCacheManager。如果有自定义缓存配置,需确保使用的是响应式缓存管理器(而非同步的RedisCacheManager),否则无法正确处理ReactiveKeyGenerator。

验证效果

完成配置后,缓存键会按照预期生成,格式为:

"Something::SimpleKey [...(method params), *userCredentials]"

其中userCredentials为当前用户的凭证信息(未认证时为anonymous)。

内容的提问来源于stack exchange,提问作者JasonLaux

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:32:53