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

Java 我可以使用类路径覆盖正在运行的jar中的文件吗?,java,jar,classpath,executable-jar,Java,Jar,Classpath,Executable Jar,我有一个JAR文件,其中包含一个应用程序以及该应用程序的配置文件。应用程序从类路径加载配置文件(使用ClassLoader.getResource()),并使用烘焙到JAR文件中的配置文件完全满足其依赖关系 有时,我希望应用程序以稍微不同的配置运行(特别是我希望覆盖JDBC URL以指向不同的数据库),因此我创建一个新的配置文件,将其存储在正确的目录结构中(这意味着在类路径项的目录/config中),我想这样做: java -cp new-config:. -jar application.ja

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

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

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

但是我不能让类路径在应用程序JAR的内容之前有
newconfig
path条目。JAR的内容总是类路径上的第一件事,这是硬编码的吗?

仅仅使用类路径可能是不可能的。有几种方法可以获取并调用
ClassLoader.getResource()
使用静态路径查找资源。如果这样做,它将绕过类路径。

由-JAR选项指定的JAR存档将覆盖所有其他值

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

我们使用自定义解决方案来解决此问题-我们加载内部属性,如下所示:

final Properties p = new Properties();
p.load(DefaultConfiguration.class.getResourceAsStream("config.properties"));
然后,我们以同样的方式加载外部文件,并用外部值覆盖内部值

有关类加载工作原理的信息,请参见:


为什么不直接调用应用程序而不指定-jar,而是显式命名应用程序主类?这将允许您按所需顺序将新配置和application.jar放在类路径上:

e、 g.(假设“new config”是包含重写属性文件的目录)


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

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

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

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

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

Spring配置片段

<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

您是否尝试过将配置放在de jar之外,放在相对于application.jar(../conf/config.jar)的路径中自己的jar文件中?如果您这样做,我认为您可以在应用程序清单中设置指向该配置jar的类路径,并且您可以设置新的配置来更改config.jar。我希望我有更多的时间做一个演示来确认我的答案,但我不能。。。所以我写它作为一个评论,你的意思是,而不是在JAR中?是的,而不是在与应用程序相同的JAR中,将配置放在第二个JAR中…谢谢,但这并不适用于我的使用-我尝试支持的用户使用构建脚本在他们的工作站上创建JAR,然后手动将其传输到服务器。要求他们传输两个文件将是一个问题。到目前为止,还没有修复一个已知的错误,即不能将-cp和-jar组合起来:主要问题是我实际上没有使用-cp参数,而是在清单文件中指定类路径,由于应用程序需要许多其他外部JAR—提取所有这些JAR将非常容易出错。但我打赌我可以编写一些脚本,从清单中提取类路径并自动构建相关命令行,因此这可能是我将使用的答案。将配置文件作为可选参数传递是一个好主意,但是我的应用程序目前接受了相当多的参数,添加另一个参数对用户来说是有问题的。谢谢你的回答。你是如何启动你的应用程序的?我原以为通过Webstart、.bat或.sh脚本等启动应用程序,传递的参数会对用户隐藏。否-用户自己从命令行启动应用程序,传递所需的参数-日期、要处理的文件,等等。我想你总是可以让用户通过一个脚本或bat文件来启动应用程序,该脚本或bat文件接受JVM参数或参数,并将它们与属性文件一起传递给JVM?在不了解用户的更多上下文等情况下,很难判断这是否是最佳选择。最终,我们使用了更复杂的实现,即更改加载程序逻辑,在返回到类路径加载语义之前,先查看当前工作目录的几个文件夹。这确实是个问题。我知道除了以不同的方式启动应用程序(如alasdairg所建议的)或者编写一些自定义加载代码之外,没有其他方法可以解决这个问题。谢谢
dbServer=MyServer
dbPort=1433
dbName=MyDb
dbUserName=Me
dbPassword=foobar