war应用程序中的Java类加载器(jar/classloader hell)quartz
我有一个maven项目设置,例如war应用程序中的Java类加载器(jar/classloader hell)quartz,java,tomcat,classloader,quartz-scheduler,Java,Tomcat,Classloader,Quartz Scheduler,我有一个maven项目设置,例如 parent ...pom.xml ...servlet-app ......pom.xml ( specifies simple-lib as a dependency ) ...simple-lib ......src/main/resources/config.properties ......src/main/java/package1/Config.java ......src/main/java/package1/HelloQuartzJob.ja
parent
...pom.xml
...servlet-app
......pom.xml ( specifies simple-lib as a dependency )
...simple-lib
......src/main/resources/config.properties
......src/main/java/package1/Config.java
......src/main/java/package1/HelloQuartzJob.java
基本上,servlet应用程序servlet应用程序将简单库指定为依赖项。配置文件config.properties打包在simple-lib.jar的顶层。当我解包servelet-app.war时,我可以看到WEB\u-INF/lib/simple-lib.jar。所以,一切都很好
Config.java如下所示:
public class Config{
static final String PROPERTILES_FILE = "config.properties";
static Properties props;
static{
log.info("Loading Config properties from {}", PROPERTILES_FILE);
props = new Properties();
try {
InputStream is = ClassLoader.getSystemResourceAsStream(PROPERTILES_FILE);
if (is == null) {
log.info("Loading through ClassLoader as root");
is = ClassLoader.getSystemResourceAsStream("/"+PROPERTILES_FILE);
}
if (is == null) {
log.info("Loading through Config.class. root");
is = Config.class.getResourceAsStream("/"+PROPERTILES_FILE);
}
if (is == null) {
log.info("Loading through Config.class. relative");
is = Config.class.getResourceAsStream(PROPERTILES_FILE);
}
if( is == null ) {
log.info("Thread class loader root");
is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/"+PROPERTILES_FILE);
}
props.load(is);
} catch (Throwable e) {
log.error("Config properties loading error ", e);
throw new RuntimeException(e);
}
}
}
但是,当我在tomcat7中部署它时,我得到一个NoClassDefFound/无法初始化package1.Config错误。我相信这是因为类加载器
另外值得注意的是,HelloQuartzJob.java使用了这个package1.Config,这是一个quartz作业,由在这个servlet应用程序中运行的调度器实例运行
有指针吗?您应该替换此行:
InputStream is = ClassLoader.getSystemResourceAsStream(PROPERTILES_FILE);
与:
为了使用当前的webapp类加载器,其根位于war的根..我发现了两个问题:
is = ClassLoader.getSystemResourceAsStream("/"+PROPERTILES_FILE);
及
直接从类加载器加载资源时,不要使用前导“/”字符
从
Class.getResourceAsStream()
使用前导“/”(因为资源是相对于类的包加载的),但是对于ClassLoader.getResourceAsStream()
和getSystemResourceAsStream()
不使用前导“/”。您需要从ClassLoader实例请求资源
从静态上下文:
String url = Config.class.getClassLoader().getResource("config.properties");
InputStream is = Config.class.getClassLoader().getResourceAsStream("config.properties");
从一个实例:
String url = getClass().getClassLoader().getResource("config.properties");
InputStream is = getClass().getClassLoader().getResourceAsStream("config.properties");
访问webapp上下文中的jar资源时,应该只使用相对路径,而不使用绝对路径(以“/”开头)
昨天我也遇到了同样的问题,这样就很容易解决了:-)
这只是一个简单的类加载器问题,但它非常重要。如果使用绝对路径,加载程序将只查看WEB-INF/classes文件夹。这可能会对您有所帮助:该问题是相关的,但并不确切。在这种情况下,我的类根本没有被初始化,因为它无法通过类加载器找到资源。它的静态作用域。没有“this”。@smartnut007想法仍然是一样的,从this或Config.class获取类的类加载器,重新考虑你的否决票。我认为你没有充分阅读我的问题。我已经尝试过上面相同的方法,至少等效的Config.class.getResourceAsStream(Properties_文件)是不同的。您必须使用Config.class.getClassLoader(),您也可以阅读此主题
String url = Config.class.getClassLoader().getResource("config.properties");
InputStream is = Config.class.getClassLoader().getResourceAsStream("config.properties");
String url = getClass().getClassLoader().getResource("config.properties");
InputStream is = getClass().getClassLoader().getResourceAsStream("config.properties");