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

Spring Boot 3中无法使用EhCacheCacheManager的解决方案咨询

Spring Boot 3迁移EhCache解决方案

一、兼容旧版EhCache 2.x(最小改动)

Spring Boot 3依赖的Spring Framework 6已移除官方对net.sf.ehcache(EhCache 2.x)的集成类(如EhCacheCacheManager),若要保留原有EhCache 2.7.4配置,需手动实现Spring Cache适配类:

1. 自定义Cache适配类

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.springframework.cache.support.AbstractValueAdaptingCache;
import org.springframework.lang.Nullable;

public class EhCache2Cache extends AbstractValueAdaptingCache {

    private final Cache ehcache;

    public EhCache2Cache(Cache ehcache) {
        super(true);
        this.ehcache = ehcache;
    }

    @Override
    protected Object lookup(Object key) {
        Element element = this.ehcache.get(key);
        return (element != null ? element.getObjectValue() : null);
    }

    @Override
    public String getName() {
        return this.ehcache.getName();
    }

    @Override
    public Object getNativeCache() {
        return this.ehcache;
    }

    @Override
    public void put(Object key, @Nullable Object value) {
        this.ehcache.put(new Element(key, value));
    }

    @Override
    @Nullable
    public ValueWrapper putIfAbsent(Object key, @Nullable Object value) {
        Element existing = this.ehcache.putIfAbsent(new Element(key, value));
        return toValueWrapper(existing != null ? existing.getObjectValue() : null);
    }

    @Override
    public void evict(Object key) {
        this.ehcache.remove(key);
    }

    @Override
    public void clear() {
        this.ehcache.removeAll();
    }
}

2. 自定义CacheManager适配类

import net.sf.ehcache.CacheManager;
import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractCacheManager;

import java.util.Collection;
import java.util.stream.Collectors;

public class EhCache2CacheManager extends AbstractCacheManager {

    private final CacheManager ehcacheManager;

    public EhCache2CacheManager(CacheManager ehcacheManager) {
        this.ehcacheManager = ehcacheManager;
    }

    @Override
    protected Collection<? extends Cache> loadCaches() {
        return this.ehcacheManager.getCacheNames().stream()
                .map(name -> new EhCache2Cache(this.ehcacheManager.getCache(name)))
                .collect(Collectors.toList());
    }
}

3. 修改原有配置类

仅替换cacheManager()方法的实现,保留原有EhCache配置逻辑:

import net.sf.ehcache.config.CacheConfiguration;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@EnableCaching
public class AppConfig implements CachingConfigurer {

    private static final List<String> CACHE_LIST = List.of("entity1", "entity2", "entity3");

    @Bean(destroyMethod = "shutdown")
    public net.sf.ehcache.CacheManager ehCacheManager() {
        final net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration();
        for (final String cacheComponent : CACHE_LIST) {
            final CacheConfiguration cacheConfiguration = new CacheConfiguration();
            cacheConfiguration.setName(cacheComponent);
            cacheConfiguration.setMemoryStoreEvictionPolicy("LFU");
            cacheConfiguration.setMaxEntriesLocalHeap(10000);
            cacheConfiguration.setOverflowToOffHeap(false);
            cacheConfiguration.setEternal(false);
            configuration.addCache(cacheConfiguration);
        }
        return net.sf.ehcache.CacheManager.newInstance(configuration);
    }

    @Bean
    @Override
    public org.springframework.cache.CacheManager cacheManager() {
        return new EhCache2CacheManager(ehCacheManager());
    }
}

二、升级至EhCache 3.x(无XML配置方案)

若无法兼容旧版本,推荐升级到EhCache 3.x,Spring Boot 3对其有原生支持,无XML配置步骤如下:

1. 更新依赖

移除net.sf.ehcache依赖,引入Spring Boot缓存starter和EhCache 3:

<!-- Maven依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

2. 新配置类实现

使用EhCache 3的API构建缓存配置:

import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.expiry.Duration;
import org.ehcache.expiry.Expirations;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class AppConfig implements CachingConfigurer {

    private static final List<String> CACHE_LIST = List.of("entity1", "entity2", "entity3");

    @Bean(destroyMethod = "close")
    public javax.cache.CacheManager jCacheManager() {
        CacheManagerBuilder<org.ehcache.CacheManager> cacheManagerBuilder = CacheManagerBuilder.newCacheManagerBuilder();

        for (String cacheName : CACHE_LIST) {
            cacheManagerBuilder.withCache(cacheName,
                    CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
                                    ResourcePoolsBuilder.newResourcePoolsBuilder()
                                            .heap(10000, EntryUnit.ENTRIES))
                            // 替代原eternal=false,设置TTL为永不过期可改用Duration.INFINITE
                            .withExpiry(Expirations.timeToLiveExpiration(Duration.of(30, TimeUnit.MINUTES)))
                            // 配置LFU淘汰策略
                            .withEvictionPolicy(org.ehcache.config.EvictionPolicy.LFU));
        }

        org.ehcache.CacheManager ehcacheManager = cacheManagerBuilder.build(true);
        return javax.cache.Caching.getCachingProvider().getCacheManager(ehcacheManager.getURI(), ehcacheManager.getClassLoader());
    }

    @Bean
    @Override
    public org.springframework.cache.CacheManager cacheManager() {
        return new JCacheCacheManager(jCacheManager());
    }
}

配置说明

  • heap(10000, EntryUnit.ENTRIES)对应原配置的maxEntriesLocalHeap=10000
  • withExpiry替代原eternal=false,示例设置30分钟TTL,需根据业务调整
  • withEvictionPolicy直接配置LFU淘汰策略,比旧版更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:59:50