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

如何使用Spring Boot Cache与Caffeine缓存异常?

用Caffeine + Spring Boot缓存特定异常的实现方案

当然可以通过Caffeine结合Spring Boot来缓存特定异常(比如404对应的NotFoundException),以此避免重复执行耗时的异常处理逻辑。核心思路是:当方法抛出目标异常时,将该异常存入缓存;后续相同请求进来时,直接从缓存取出异常抛出,跳过耗时的业务处理。

1. 配置Caffeine缓存管理器

首先在Spring Boot中配置Caffeine缓存,指定缓存名称、过期时间和最大容量:

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("exceptionCache");
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterWrite(10, TimeUnit.MINUTES) // 根据业务需求调整过期时间
                .maximumSize(1000)); // 限制缓存条目数量,避免内存溢出
        return cacheManager;
    }
}

2. 业务方法中实现异常缓存逻辑

在业务方法中,先检查缓存中是否存在对应异常,存在则直接抛出;执行业务逻辑时捕获目标异常并存入缓存,同时处理正常返回时的缓存清理:

@Service
public class ResourceService {

    private final CacheManager cacheManager;

    // 构造注入(Spring 4.3+支持)
    public ResourceService(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    public Resource getResource(String resourceId) throws NotFoundException {
        Cache exceptionCache = cacheManager.getCache("exceptionCache");
        String cacheKey = "resource_not_found:" + resourceId;

        // 先检查缓存中是否有对应的异常
        if (exceptionCache != null) {
            NotFoundException cachedEx = exceptionCache.get(cacheKey, NotFoundException.class);
            if (cachedEx != null) {
                throw cachedEx;
            }
        }

        try {
            // 模拟耗时的业务处理:比如调用外部API、复杂数据库查询
            Resource resource = fetchResourceFromExternalSystem(resourceId);
            
            // 正常返回时,清理该key对应的异常缓存(如果存在)
            if (exceptionCache != null) {
                exceptionCache.evict(cacheKey);
            }
            return resource;
        } catch (NotFoundException e) {
            // 将目标异常存入缓存
            if (exceptionCache != null) {
                exceptionCache.put(cacheKey, e);
            }
            throw e;
        }
    }

    private Resource fetchResourceFromExternalSystem(String resourceId) throws NotFoundException {
        // 模拟5秒耗时操作
        try {
            Thread.sleep(5000);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }

        // 模拟资源不存在的情况
        if ("invalid-id".equals(resourceId)) {
            throw new NotFoundException("Resource " + resourceId + " not found");
        }

        return new Resource(resourceId, "Sample Resource");
    }
}

// 自定义NotFoundException对应404场景
class NotFoundException extends Exception {
    public NotFoundException(String message) {
        super(message);
    }
}

class Resource {
    private String id;
    private String content;

    public Resource(String id, String content) {
        this.id = id;
        this.content = content;
    }

    // getter/setter 省略
}

关键注意事项

  • 只缓存指定异常:务必只缓存业务明确的异常(如NotFoundException),不要缓存RuntimeException等系统级异常,避免掩盖真实问题。
  • 合理设置过期时间:对于404这类异常,资源可能后续被创建,所以缓存时间不宜过长(比如10分钟),避免用户无法获取已恢复的资源。
  • 缓存key唯一性:确保cacheKey能唯一标识请求参数(比如资源ID、用户请求路径),防止不同请求的异常互相干扰。
  • 缓存主动清理:如果后续资源被创建(比如之前404的资源已上线),要主动调用exceptionCache.evict(cacheKey)清理对应缓存,保证用户能获取最新数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:50:25