如何仅使用外部private.properties,不在Spring Boot胖Jar中包含该文件?
你的问题核心在于@PropertySource("classpath:/private.properties")的默认行为:它会强制要求类路径下必须存在该文件,哪怕你通过spring.config.additional-location指定了外部配置,Spring还是会先尝试加载类路径中的private.properties——而你打包时已经排除了这个文件,所以才会抛出FileNotFoundException。之前打包时包含空文件能正常运行,是因为类路径里存在这个文件,之后外部配置的优先级更高,会覆盖空文件的内容,所以没报错。
下面给你几个无需硬编码的解决方案:
方案1:修改@PropertySource,允许类路径文件不存在
给@PropertySource添加ignoreResourceNotFound = true属性,同时显式添加外部文件的配置,确保外部配置能被加载:
@PropertySource(value = "classpath:/private.properties", ignoreResourceNotFound = true) @PropertySource(value = "file:./config/private.properties", ignoreResourceNotFound = false) public class PrivateProperties { // 你的属性字段和配置 }
- 第一个
@PropertySource:允许类路径下没有private.properties,避免启动报错 - 第二个
@PropertySource:强制要求外部路径的文件存在,确保你的令牌配置能生效
启动命令保持你原来的即可,甚至可以去掉-Dspring.config.additional-location参数,因为已经通过注解指定了外部路径。
方案2:移除@PropertySource,依赖Spring Boot原生外部配置机制
Spring Boot本身就支持优先级更高的外部配置加载,完全不需要@PropertySource也能实现需求:
- 删掉
PrivateProperties.java中的@PropertySource注解 - 启动命令保持不变:
$ java -Dspring.config.additional-location=file:./config/private.properties -jar target/mytool-1.0.0-SNAPSHOT.jar
或者更灵活的方式:把private.properties放在Jar包同目录的config文件夹下(Spring Boot默认会扫描这个位置),然后在你的application.properties中添加:
spring.config.import=optional:classpath:/private.properties,file:./config/private.properties
这样Spring会先尝试加载类路径的文件(不存在也不报错),再加载外部的配置文件。
方案3:用占位符动态指定配置路径(避免硬编码)
如果你想保留@PropertySource,可以通过占位符让配置路径可配置,不用硬编码:
@PropertySource(value = "${private.config.location:classpath:/private.properties}", ignoreResourceNotFound = true) public class PrivateProperties { // 你的属性配置 }
启动时通过参数指定外部路径:
$ java -Dprivate.config.location=file:./config/private.properties -jar target/mytool-1.0.0-SNAPSHOT.jar
这个方案的好处是既可以默认使用类路径的文件(如果需要的话),也能通过启动参数灵活切换到外部配置。
推荐优先选择方案2,因为它完全利用Spring Boot的原生配置机制,更符合框架的设计理念,也更灵活。
内容的提问来源于stack exchange,提问作者Tristan

