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

集成EHCache+Terracotta+Spring时使用@CacheEvict遇UnsupportedOperationException

解决Ehcache 3.4.0集群模式下@CacheEvict(allEntries=true)抛出UnsupportedOperationException的问题

我之前也碰到过一模一样的情况,这个异常在Ehcache 3.x早期集群版本的JSR107集成里是个典型的功能未完善问题,下面给你具体的解决思路和可行方案:

问题根源

Ehcache 3.4.0的JCache(JSR107)实现在**集群存储(ClusteredStore)**场景下,没有完成allEntries=true对应的全量缓存清除逻辑,底层的ClusteredStore类直接抛出了UnsupportedOperationException: Implement me,这是官方当时的功能遗漏。

解决方案

方案1:升级Ehcache到3.5.0及以上版本

官方在Ehcache 3.5.0版本中修复了这个JCache集群下的批量清除问题,升级是最彻底的解决方式。注意要同步升级Terracotta服务器版本,确保和Ehcache版本兼容(比如Ehcache 3.5.0对应Terracotta Server 5.3.0+)。

方案2:不升级版本,改用原生API手动清除

如果暂时无法升级,可以绕过JSR107注解的限制,直接使用Ehcache的原生API来实现全量清除:

  1. 在Spring组件中注入JCache的CacheManager
  2. 将其转换为Ehcache原生的Cache实例,调用clear()方法

示例代码:

import javax.cache.Cache;
import javax.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CacheClearService {

    @Autowired
    private CacheManager jCacheManager;

    public void clearAllEntriesInCache(String cacheName) {
        Cache<Object, Object> jCache = jCacheManager.getCache(cacheName);
        if (jCache != null) {
            // 转换为Ehcache原生Cache实例
            org.ehcache.Cache<Object, Object> ehcache = jCache.unwrap(org.ehcache.Cache.class);
            // 调用原生clear方法,集群环境下可正常执行全量清除
            ehcache.clear();
        }
    }
}

然后在需要清除缓存的业务方法里,直接调用这个服务方法即可,替代@CacheEvict(allEntries=true)的作用。

方案3:核对Spring配置的正确性

虽然你说已经完成集群集成,但还是可以再确认下Spring Cache配置是否正确关联了集群模式的Ehcache实例,避免误用本地缓存实例:

示例正确的集群CacheManager配置:

import org.ehcache.clustered.client.config.ClusteredCacheManagerConfiguration;
import org.ehcache.clustered.client.config.builders.ClusteredCacheManagerConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.core.EhcacheManager;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.cache.Caching;
import java.net.URI;

@Configuration
public class CacheConfig {

    @Bean
    public JCacheCacheManager cacheManager() {
        // 配置Terracotta集群地址
        URI terracottaUri = URI.create("terracotta://localhost:9410/myClusterCacheManager");
        
        ClusteredCacheManagerConfiguration clusterConfig =
            ClusteredCacheManagerConfigurationBuilder.cluster(terracottaUri).build();
            
        // 创建集群模式的EhcacheManager
        EhcacheManager ehcacheManager = (EhcacheManager) CacheManagerBuilder.newCacheManagerBuilder()
            .with(clusterConfig)
            .build(true);
            
        // 转换为Spring兼容的JCacheCacheManager
        return new JCacheCacheManager(Caching.getCachingProvider().getCacheManager(
            ehcacheManager.getURI(), ehcacheManager.getClass().getClassLoader()));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:31:59