Jar 中的 @PropertySource 用于类路径上的外部文件

Posted

技术标签:

【中文标题】Jar 中的 @PropertySource 用于类路径上的外部文件【英文标题】:@PropertySource in a Jar for an external file on the classpath 【发布时间】:2015-07-16 17:43:28 【问题描述】:

我正在尝试在 Jar 中使用 Spring 框架的 @PropertySource 注释从 jar 外部加载属性文件,但找不到该文件。

我需要将属性文件放在 Jar 的外部,以便可以对其进行编辑。我不知道文件的确切位置,我想我可以将它放在类路径中的任何位置。

我在 Config 类上使用了以下注释。

@PropertySource('classpath:stc.properties')

并把stc.properties与创建的Jar文件放在同一目录下。我尝试在java 命令中明确指定类路径,但仍然找不到文件:

java -cp . -jar stc.jar
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to load bean class: com.example.stc.Config; nested exception is java.io.FileNotFoundException: class path resource [stc.properties] cannot be opened because it does not exist
        at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:162)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:299)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:609)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
[...]

等等

我也尝试使用 ./ 作为类路径,并尝试在 jar 清单的 Class-Path 属性中指定类路径(具有两个变体),但它总是给出相同的结果。

【问题讨论】:

【参考方案1】:

假设你有两个文件,一个用于本地,一个用于生产

@PropertySources(
        @PropertySource("classpath:application.properties"),
        @PropertySource(value = "$ws.properties", ignoreResourceNotFound = true)

)

在tomcat或者你的jar文件中,传递这个参数

-Dws.properties=file:/path-to.properties

我在 setenv.sh 中添加了这个

APPLICATION_OPTS="-Dlog4j.configurationFile=file:$PATH/log4j2.xml -Dlog4j.debug=true -Dapplication.properties=file:$PATH/application.properties

这仅适用于 Spring 4

【讨论】:

我在tomcat中添加这个“-Dws.properties=file:/path-to.properties” 我在 setenv.sh 中添加了。更新了我的答案【参考方案2】:

使用变量(系统或环境)来获取文件的值,您可以像这样引用您的文件:

@PropertySource("file:$MY_PATH/application.properties")

【讨论】:

【参考方案3】:

我的环境是:

操作系统:Windows |容器:Tomcat |爪哇:7 |春天:4.2.4 | Springboot 1.3.1 | Maven

步骤 1 a(战争)

将文件外部化属性文件添加到 JVM 系统属性。

正如我在 Tomcat 上运行的那样;我通过在<TOMCAT_HOME>/bin/setenv.bat 中创建 setenv.bat 来做到这一点

set CATALINA_OPTS=%CATALINA_OPTS% -Dexternal.app.properties=file:<PATH_TO_EXTERNAL_FILE>\application-prod.properties

步骤 1 b(罐子)

如果您从 jar 中运行,则可以使用:

-Dexternal.app.properties=file:&lt;PATH_TO_EXTERNAL_FILE&gt;\application-prod.properties

注意file:在开头的使用就行了。

第二步:在我的应用启动类中,我使用注解@PropertySource来加载具体环境的应用属性。

@SpringBootApplication
@PropertySources(
        @PropertySource(value = "$external.app.properties.file", ignoreResourceNotFound = true),
        @PropertySource(value = "classpath:application.properties")
)
public class Application extends SpringBootServletInitializer 

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(Application.class);
    


第 3 步

在项目中使用外部属性

external/file/path/application-prod.properties

spring.datasource.url.ext=

/src/main/resources/application.properties

spring.datasource.url=$spring.datasource.url.ext

希望这可以帮助其他遇到同样问题的人。

【讨论】:

【参考方案4】:

尝试给出文件的完整路径:

@PropertySource('file:c:/.../stc.properties')

【讨论】:

那行得通,但它不能解决我的问题。正如我所提到的,我不知道文件的位置。 怎么样:@PropertySource('file:/../stc.properties') 这仍然假设文件位于相对于 jar 的特定位置。 这个想法实际上帮助了我,我使用了@PropertySource 的两个实例,第一个使用类路径:第二个使用 file: 格式并指向,例如:file:./stc.properties .它非常适合我查看类路径中的属性文件以及 jar 的相同路径。【参考方案5】:

您可以在运行 jar 时使用 --spring.config.location=file:/somepath 参数,在其中指定配置文件的路径(可以是相对的)。

更多信息in docs

【讨论】:

【参考方案6】:

假设您有一个 jar,其类路径中有一个默认的 main 和一些默认的 stc.properties

如果在 jar 旁边(实际上在执行目录中)有一个具有该名称的配置文件,则可以选择在该配置中设置的属性与默认配置的属性合并。

如果用户决定不使用外部配置,则不会发生错误。

对于上述场景你需要:

@PropertySources(
        @PropertySource("classpath:stc.properties"),
        @PropertySource(value = "file:./stc.properties", ignoreResourceNotFound = true)

)

例如假设默认的stc.properties(在罐子里)内容是:

propA=valueA
propB=valueB

现在,如果我在 jar 旁边添加一个同名文件,其中包含:

propB=updatedValueB
propC=valueC

执行java -jar stc.jar时有效加载的属性有:

propA=valueA
propB=updatedValueB
propC=valueC

【讨论】:

以上是关于Jar 中的 @PropertySource 用于类路径上的外部文件的主要内容,如果未能解决你的问题,请参考以下文章

spring @value和@@PropertySource注解简单使用

jar弹簧启动属性文件

spring @PropertySource 读取资源文件

[spring] @PropertySource

SpringBoot系列之@PropertySource和@Value注解

Spring——15使用@PropertySource加载配置文件