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

Spring缓存:生成缓存键时忽略可选参数的实现方法

解决@Cacheable忽略可选user-agent参数生成缓存键的方法

嘿,这个场景我经常碰到!要让Spring的@Cacheable生成缓存键时跳过那个可选的user-agent参数,有几个实用的方案,我给你一一拆解:

方案1:直接用SpEL指定缓存键(最简单)

如果你的方法里只有user-agent这一个参数,或者你明确知道哪些参数需要纳入缓存键,直接在@Cacheable的key属性里写死或者指定需要的参数就行。比如:

@Cacheable(value="bookCache", key = "'all-books'")
public Book getBooks(@RequestHeader(value = "user-agent", required = false) String userAgent) {
    // 方法逻辑
}

要是方法还有其他需要区分缓存的参数(比如bookId),就把这些参数加入key,完全忽略user-agent:

@Cacheable(value="bookCache", key = "#bookId")
public Book getBooks(String bookId, @RequestHeader(value = "user-agent", required = false) String userAgent) {
    // 方法逻辑
}

这种方式适合单个方法的简单场景,不用额外写代码。

方案2:自定义KeyGenerator(灵活通用)

如果你有多个方法都需要忽略user-agent参数,自定义一个全局的KeyGenerator会更高效。步骤如下:

1. 实现自定义KeyGenerator

import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component("ignoreUserAgentKeyGenerator")
public class IgnoreUserAgentKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object target, Method method, Object... params) {
        // 获取方法的所有参数名称
        List<String> paramNames = Arrays.stream(method.getParameters())
                .map(param -> param.getName())
                .collect(Collectors.toList());
        
        // 过滤掉名为userAgent的参数值
        List<Object> filteredParams = Arrays.stream(params)
                .filter((param, index) -> !"userAgent".equals(paramNames.get(index)))
                .collect(Collectors.toList());
        
        // 用类名、方法名+过滤后的参数生成唯一缓存键
        return target.getClass().getSimpleName() + "_" + method.getName() + "_" + filteredParams;
    }
}

2. 开启参数名编译支持

要让method.getParameters().getName()能正确获取参数名,需要在编译时开启参数名保留。比如Maven的pom.xml里配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source> <!-- 对应你的JDK版本 -->
                <target>1.8</target>
                <compilerArgs>
                    <arg>-parameters</arg> <!-- 关键参数 -->
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

3. 在@Cacheable中使用自定义KeyGenerator

@Cacheable(value="bookCache", keyGenerator = "ignoreUserAgentKeyGenerator")
public Book getBooks(@RequestHeader(value = "user-agent", required = false) String userAgent) {
    // 方法逻辑
}

方案3:用SpEL排除指定位置的参数

如果user-agent是方法的第一个参数,也可以通过#root.args来排除它。比如方法只有这一个参数时:

@Cacheable(value="bookCache", key = "'static-key'")

如果有多个参数,比如user-agent是第一个,第二个是bookType,就用:

@Cacheable(value="bookCache", key = "#root.args[1]")

这种方式适合参数位置固定的场景,但可读性不如前两种,参数位置变化时容易出错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:00:19