Spring Boot 3集成EhCache 3部署Tomcat时无法获取默认CacheManager
核心错误分析
报错核心是Cache 'cache' creation in EhcacheManager failed,说明独立Tomcat环境下EhCache无法正常初始化指定缓存实例——内嵌Tomcat正常是因为两者的类加载机制、运行权限、依赖处理逻辑存在差异。
可能的原因及对应解决方法
1. Jakarta EE 与 Java EE 依赖冲突(最可能)
Spring Boot 3 基于 Jakarta EE 9+,你当前使用的javax.cache:cache-api:1.1.1是Java EE时代的包,和Jakarta EE的jakarta.cache包存在类路径冲突。内嵌Tomcat由Spring Boot管控,可能通过类加载隔离掩盖了冲突,但独立Tomcat的类加载规则会触发该问题。
解决方法:
替换Java EE版本的cache-api为Jakarta版本,并升级EhCache到兼容Spring Boot 3的版本:
// 移除旧依赖 // implementation group: 'javax.cache', name: 'cache-api', version: '1.1.1' // 添加Jakarta版本的缓存API implementation group: 'jakarta.cache', name: 'jakarta.cache-api', version: '2.0.1' // 升级EhCache到兼容Spring Boot3的版本 implementation group: 'org.ehcache', name: 'ehcache', version: '3.19.0'
2. 独立Tomcat类加载器冲突
独立Tomcat的全局类加载器(${CATALINA_HOME}/lib)可能存在其他版本的cache-api或EhCache依赖,和你的WEB应用内的依赖版本冲突,导致EhcacheCachingProvider无法正确加载。
解决方法:
- 检查Tomcat的
${CATALINA_HOME}/lib目录,若存在cache-api.jar或ehcache.jar,删除这些全局依赖,让应用使用自身打包的版本。 - 在WAR包的
META-INF/context.xml中添加类加载隔离配置,强制应用优先使用自身WEB-INF/lib下的依赖:
<Context> <Loader delegate="false" /> </Context>
3. EhCache配置文件加载异常
独立Tomcat下,classpath:ehcache.xml的解析路径和内嵌Tomcat不同,可能导致配置文件未被正确加载,进而无法创建指定的cache实例。
解决方法:
- 确认WAR包中
ehcache.xml是否在WEB-INF/classes目录下(正常打包会自动放置在此处)。 - 尝试修改配置路径为Tomcat可识别的绝对路径:
# 替换原配置,将ehcache.xml放到Tomcat的conf目录下 spring.cache.jcache.config=file:${catalina.base}/conf/ehcache.xml
4. 缓存目录权限不足
若EhCache配置了磁盘持久化缓存,独立Tomcat运行的系统用户(通常是tomcat用户)可能没有缓存目录的读写权限,导致缓存实例创建失败。
解决方法:
- 查看
ehcache.xml中的磁盘缓存配置,找到对应的目录:
<persistence directory="/path/to/cache/dir" />
- 确保该目录存在,且Tomcat运行用户拥有读写权限:
mkdir -p /path/to/cache/dir chown tomcat:tomcat /path/to/cache/dir chmod 755 /path/to/cache/dir
5. Spring Boot自动配置的生命周期冲突
独立Tomcat部署时,Spring Boot的自动配置可能和Tomcat的生命周期存在冲突,导致CacheManager在资源未就绪时初始化。
解决方法:
手动配置CacheManager,替代自动配置,明确指定类加载器:
@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager() throws URISyntaxException { URL configUrl = getClass().getResource("/ehcache.xml"); javax.cache.CacheManager jCacheManager = Caching.getCachingProvider() .getCacheManager(configUrl.toURI(), getClass().getClassLoader()); return new JCacheCacheManager(jCacheManager); } }
内容的提问来源于stack exchange,提问作者Biswajit

