如何使用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
相关产品推荐
相关产品推荐

