我可以使用类路径覆盖正在运行的jar中的文件吗?

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

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

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

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

为什么不在不指定-jar的情况下调用应用程序,而是明确地命名应用程序主类? 这将允许您按所需顺序将new-config和application.jar放在类路径中:

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

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

我相信主类的名字可以在jar里面的MANIFEST.MF文件中找到….

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

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

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

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

Spring配置代码段

       

属性文件片段

 dbServer=MyServer dbPort=1433 dbName=MyDb dbUserName=Me dbPassword=foobar 

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

您通常必须使用外部配置文件或使用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

仅使用CLASSPATH可能无法实现。 有一些方法可以调用ClassLoader.getResource()使用静态路径来查找资源。 如果它正在这样做,它绕过CLASSPATH。