升级至Java 11后Apache Shiro无法找到默认Ehcache配置
Java 11升级后Shiro无法自动加载默认Ehcache配置的问题
问题背景
将使用Apache Shiro的Web应用从Java 8升级到Java 11(仅Java版本变更,所有依赖包无变动)后,启动服务器时出现Shiro无法找到默认ehcache.xml配置的错误,Java 8环境下运行完全正常。
报错信息
[main] INFO org.apache.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization. [main] ERROR org.apache.shiro.web.env.EnvironmentLoader - Shiro environment initialization failed java.lang.NullPointerException: The url can not be null at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:151) at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:131) at org.ehcache.xml.XmlConfiguration.<init>(XmlConfiguration.java:115) at org.ehcache.integrations.shiro.EhcacheShiroManager.getConfiguration(EhcacheShiroManager.java:176) at org.ehcache.integrations.shiro.EhcacheShiroManager.ensureCacheManager(EhcacheShiroManager.java:149) at org.ehcache.integrations.shiro.EhcacheShiroManager.init(EhcacheShiroManager.java:205) at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:45) at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:40) at org.apache.shiro.config.ReflectionBuilder$BeanConfigurationProcessor.execute(ReflectionBuilder.java:831) at org.apache.shiro.config.ReflectionBuilder.buildObjects(ReflectionBuilder.java:290) at org.apache.shiro.config.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:181) at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:139) at org.apache.shiro.config.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:107) at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:98) at org.apache.shiro.config.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:47) at org.apache.shiro.config.IniFactorySupport.createInstance(IniFactorySupport.java:150) at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:47) at org.apache.shiro.web.env.IniWebEnvironment.createWebSecurityManager(IniWebEnvironment.java:296) at org.apache.shiro.web.env.IniWebEnvironment.configure(IniWebEnvironment.java:121) at org.apache.shiro.web.env.IniWebEnvironment.init(IniWebEnvironment.java:73) at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:45) at org.apache.shiro.util.LifecycleUtils.init(LifecycleUtils.java:40) at org.apache.shiro.web.env.EnvironmentLoader.createEnvironment(EnvironmentLoader.java:313) at org.apache.shiro.web.env.EnvironmentLoader.initEnvironment(EnvironmentLoader.java:139) at org.apache.shiro.web.env.EnvironmentLoaderListener.contextInitialized(EnvironmentLoaderListener.java:58)
现有配置
web.xml配置
<listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener>
该配置自动加载WEB-INF/shiro.ini,其中缓存管理器配置如下:
shiro.ini核心配置
[main] ... cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager securityManager.cacheManager = $cacheManager
依赖信息(无变动)
- shiro-all-1.12.0.jar
- shiro-ehcache3-1.0.0.jar
- 其他依赖:commons-beanutils、commons-logging、log4j、slf4j、ehcache
Java 8下的正常启动日志
[main] INFO org.apache.shiro.web.env.EnvironmentLoader - Starting Shiro environment initialization. [main] INFO org.ehcache.xml.XmlConfiguration - Loading Ehcache XML configuration from file:/path/to/my/app/lib/shiro-ehcache3-1.0.0.jar!/org/ehcache/integrations/shiro/ehcache.xml.
已尝试的无效方案
- 在shiro.ini中添加
cacheManager.cacheManagerConfigFile = /path/to/custom/configuration.xml(使用从shiro-ehcache3 jar中提取的默认配置),报错:org.apache.shiro.ShiroException: java.net.MalformedURLException: no protocol: /path/to/my/app/ehcache.xml - 在代码中手动设置
cacheManagerConfigFile路径,尝试过/path/to/my/app/ehcache.xml、file:///path/to/...、classpath:ehcache.xml,均触发相同的MalformedURLException。
最小复现示例
Java测试代码
import org.apache.shiro.SecurityUtils; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.util.Factory; public class Test { public static void main(String[] args) { Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); } }
配套shiro.ini(放置于类路径根目录)
[main] cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager securityManager.cacheManager = $cacheManager
该示例在Java 8下运行正常,Java 11(Amazon Corretto 11.0.16-amzn、Temurin 11.0.20-tem)及Java 17(17.0.8-amzn)均报相同的"URL can not be null"错误。
解决方案
问题根源
Java 9+ 对JDK内部API的访问限制及类加载机制变化,导致shiro-ehcache3-1.0.0.jar中EhcacheShiroManager类获取默认配置文件的方式失效——该类使用的ClassLoader.getResource()方法在模块化环境下无法正确定位Jar内的默认ehcache.xml,返回null进而触发NPE。
修复步骤
- 优先升级shiro-ehcache3依赖版本:shiro-ehcache3 1.0.0版本存在Java 9+兼容性问题,升级到1.0.1及以上稳定版,该版本已修复类加载相关的兼容性问题,升级后无需额外配置即可自动加载默认配置。
- 若无法升级依赖,手动指定带协议的配置文件路径:
在shiro.ini中配置时必须使用带协议前缀的路径,例如:
注意:必须加上# 使用Jar内的默认配置 cacheManager.cacheManagerConfigFile = classpath:org/ehcache/integrations/shiro/ehcache.xml # 或使用自定义配置文件(需放置在类路径下) cacheManager.cacheManagerConfigFile = classpath:ehcache.xmlclasspath:或file:协议前缀,直接使用文件路径会触发MalformedURLException。
验证
升级依赖或配置正确路径后,Java 11下启动应用,日志将恢复类似Java 8的正常输出,自动加载指定的ehcache.xml配置。
内容的提问来源于stack exchange,提问作者RTF
相关产品推荐
相关产品推荐

