我有一个使用 Apache Shiro 的 Web 应用程序。我正在从 Java 8 升级到 11。这是唯一的更改,但是当我尝试启动我的服务器时,shiro 似乎找不到默认的 ehcache.xml 配置。我收到以下错误:
[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 配置,其中包含(除其他外):
[main]
...
...
cacheManager = org.ehcache.integrations.shiro.EhcacheShiroManager
securityManager.cacheManager = $cacheManager
当我使用java 8编译并运行时,找到ehcache配置没有问题并且服务器正常启动:
[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.
正如我提到的,唯一的变化是我使用 java 11 进行编译和运行。所有相同的 jar 可用于两个版本,并且这些 shiro 特定的 jar 是:
我还尝试按照
此处文档的建议将
cacheManager.cacheManagerConfigFile = /path/to/custom/configuration.xml
添加到我的shiro.ini中,方法是从ehcache jar中提取默认的ehcache.xml配置文件,但无论我在ini文件中使用什么路径,服务器启动总是失败并显示 org.apache.shiro.ShiroException: java.net.MalformedURLException: no protocol: /path/to/my/app/ehcache.xml
。
我还尝试在应用程序入口点中以编程方式设置 ehcache xml 配置的
cacheManagerConfigFile
路径,但是我提供的任何字符串都会出现 MalformedURLException,例如“/path/to/my/app/ehcache.xml”、“file:///path/to...”或“classpath:ehcache.xml”。
默认的 ehcache.xml 配置提取实际上只是一种解决方法(我无法工作),所以理想情况下,我想了解并修复为什么 shiro 没有使用 java 11 找到默认配置本身。
我通过像下面这样以编程方式初始化 ini 文件并将 ini 文件放入类路径的根目录中,用一个最小的示例重现了这个问题:
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 失败并出现“URL 不能为空”错误。为了使示例正常工作,您还需要:
...以及我之前提到的 2 个 shiro 罐子。我尝试使用失败的特定 java 11 版本是 Amazon Coretto (11.0.16-amzn) 和 Temeric (11.0.20-tem),适用于我的 java 8 版本是 8.0.332-tem 和 8.0 .382-amzn。
我还尝试使用 Java 17 (17.0.8-amzn) 进行编译和运行,但失败并出现相同的错误。
我的问题是,我正在使用 shiro-ehcache 包的预构建 maven 工件,因此我通过使用 Java 11 从源代码构建包来解决这个问题。由于 jaxb 已从 java 11 中删除,所以我也设法解决了这个问题。需要以下包: