0

我有一个 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.java

基本上,servlet 应用程序 servlet-app 将 simple-lib 指定为依赖项。配置文件 config.properties 打包在 simple-lib.jar 的顶层/级别。当我解压servelet-app.war 时,我可以看到WEB_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/Could not initialize package1.Config 错误。我相信这是因为类加载器。

同样有趣的是,这个 package1.Config 被 HelloQuartzJob.java 使用,它是一个由在这个 servlet 应用程序中运行的调度程序实例运行的石英作业。

任何指针?

4

3 回答 3

0

您需要从类加载器实例中请求资源。

从静态上下文:

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 文件夹。

于 2014-04-25T07:59:32.497 回答
0

我看到两个问题:

is = ClassLoader.getSystemResourceAsStream("/"+PROPERTILES_FILE);

is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/"+PROPERTILES_FILE);

直接从类加载器加载资源时不要使用前导“/”字符。

Class.getResourceAsStream()使用前导“/”(否则资源是相对于类的包加载的)但ClassLoader.getResourceAsStream()getSystemResourceAsStream()使用前导“/”。

于 2013-02-16T02:17:16.660 回答
0

你应该替换这一行:

InputStream is = ClassLoader.getSystemResourceAsStream(PROPERTILES_FILE);

和:

InputStream is = Config.class.getClassLoader().getResourceAsStream(PROPERTILES_FILE);

为了使用当前的 webapp 类加载器,它的根是战争的根。

于 2013-02-16T01:07:14.137 回答