18

我有一个 JAR 文件,其中包含一个应用程序以及该应用程序的配置文件。应用程序从类路径加载配置文件(使用ClassLoader.getResource()),并使用烘焙到 JAR 文件中的配置文件完全满足其依赖关系。

有时我希望应用程序以稍微不同的配置运行(特别是我想覆盖 JDBC URL 以指向不同的数据库),因此我创建了一个新的配置文件,将其存储在正确的目录结构中(这意味着在类路径条目的目录/config),我想做这样的事情:

java -cp new-config:. -jar application.jar

但是我无法让类new-config路径在应用程序 JAR 的内容之前具有路径条目。JAR 的内容始终是类路径上的第一件事是硬编码的吗?

4

4 回答 4

21

为什么不直接调用应用程序而不指定 -jar 而是显式命名应用程序主类?这将允许您以所需的顺序将 new-config 和 application.jar 放在类路径中:

例如(假设“new-config”是一个包含被覆盖的属性文件的目录)

java -cp new-config:application.jar Application.Main.Class

我相信主类的名称可以在 jar 内的 MANIFEST.MF 文件中找到....

于 2009-11-10T15:15:44.110 回答
13

当您使用 -jar 选项启动应用程序时:

... JAR 文件是所有用户类的来源,其他用户类路径设置被忽略

如此处所述。一种解决方法是在 jar 文件的清单中指定类路径以包含附加路径(在此处描述)。

但是,鉴于您只是在谈论修改配置,您可能希望采用不依赖于类路径的不同方法。例如,我通常使用属性文件通过 Spring 配置我的应用程序以确定数据库的位置等。我的 Spring 配置在测试、QA 和实时环境中是一致的,但我在启动应用程序时将不同的属性文件作为命令行参数传递.

弹簧配置片段

<bean id="MyDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
    <property name="url" value="jdbc:microsoft:sqlserver://${dbServer}:${dbPort};DatabaseName=${dbName}"/>
    <property name="username" value="${dbUserName}"/>
    <property name="password" value="${dbPassword}"/>
    <property name="suppressClose" value="false"/>
</bean>

属性文件片段

dbServer=MyServer
dbPort=1433
dbName=MyDb
dbUserName=Me
dbPassword=foobar
于 2009-11-10T15:19:39.990 回答
3

-jar 选项指定的 JAR 归档覆盖所有其他值。

您通常必须使用外部配置文件或构建您自己的解决方案 withod ClassLoader.getResource()

我们使用自定义解决方案来解决这个问题 - 我们像这样加载内部属性:

final Properties p = new Properties();
p.load(DefaultConfiguration.class.getResourceAsStream("config.properties"));

然后我们以相同的方式加载外部文件并用外部值覆盖内部值。

有关类加载如何工作的信息,请参阅:

http://java.sun.com/javase/6/docs/technotes/tools/findingclasses.html

于 2009-11-10T15:11:52.883 回答
1

仅使用 CLASSPATH 可能是不可能的。有一些方法可以调用 ClassLoader.getResource()使用静态路径来查找资源。如果它这样做,它就绕过了 CLASSPATH。

于 2009-11-10T15:05:22.790 回答