春季启动:是否有可能使用外部application.properties文件在任何目录与胖胖的jar?

是否有可能有多个application.properties文件? ( 编辑 :请注意,这个问题演变为标题上的问题。)

我试图有2个文件。

  • 第一个是应用程序Jar中的根文件夹。
  • 第二个是在classpath中指定的目录。

2个文件都被命名为“application.properties”。

是否有可能“合并”这两个文件的内容? (和第二个的属性值覆盖第一个)或者,如果我有一个文件,那么其他文件被忽略?

更新1 :可以“合并”内容。 昨天好像第一个被忽略了,但是好像是因为那个东西被打破了。 现在它运作良好。

更新2 :它又回来了! 同样,只有两个文件中的一个正在被应用。 这很奇怪…它是在我使用Spring Tool Suite创build应用程序jar文件之后开始的。 而且Jar版本似乎总是忽略第二个(在classpath中),而在STS上运行的扩展版本的行为却不尽相同。 从哪里可以开始调查?

更新3

Jar版本的行为其实是正确的。 这是java.exe的规范。 当指定-jar选项时,java.exe忽略-classpath选项和CLASSPATH环境variables,而类path将仅包含jar文件。 因此,classpath上的第二个application.properties文件将被忽略。

现在,我该如何让classpath上的第二个application.properties被加载?

更新4

我设法加载一个application.properties文件在外部path中使用-jar选项。

关键是PropertiesLauncher。

要使用PropertiesLauncher,必须像这样更改pom.xml文件:

<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- added --> <layout>ZIP</layout> <!-- to use PropertiesLaunchar --> </configuration> </plugin> </plugins> </build> 

为此,我引用了下面的StackOverflow问题: spring启动属性启动器无法使用 。 顺便说一句,在Spring Boot Maven插件文档( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html )中,没有提到指定ZIP触发器使用了PropertiesLauncher。 (也许在另一个文件?)

在build立jar文件之后,我可以看到使用了PropertiesLauncher来检查jar中的META-INF / MENIFEST.MF中的Main-Class属性。

现在,我可以如下运行jar(在Windows中):

 java -Dloader.path=file:///C:/My/External/Dir,MyApp-0.0.1-SNAPSHOT.jar -jar MyApp-0.0.1-SNAPSHOT.jar 

请注意,应用程序jar文件包含在loader.path中。

现在在C:\ My \ External \ Dir \ config中加载一个application.properties文件。

作为奖励,该目录中的任何文件(例如,静态html文件)也可以由jar在加载path中访问。

至于在UPDATE 2中提到的非jar(扩展)版本,可能有一个类path顺序问题。

(顺便说一下,我把这个问题的标题更改为这个问题的更具体的内容。)

如果您没有更改Spring Boot的默认值(意思是使用@EnableAutoConfiguration@SpringBootApplication并且没有更改任何属性源处理),那么它将按照以下顺序(最高覆盖最低)查找属性:

  1. 当前目录的A /config子目录
  2. 当前目录
  3. 一个classpath /config
  4. 类path根

上面的列表在本文档的这一部分中提到

这意味着如果find一个属性,例如src/resources下的application.properties将被在包装jar的“next”下的/config目录中的application.properties中的同名属性覆盖。

Spring Boot使用的默认顺序允许非常简单的configuration外部化,这使得应用程序易于在多个环境(dev,staging,production,cloud等)中configuration

要查看Spring Boot提供的属性读取的全部function(提示:比从application.properties读取更多的可用内容),请查看这部分文档。

从上面的简短描述或完整的文档可以看出,Spring Boot应用程序对DevOps非常友好!

这里所有的文档都是在这里解释的:

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

这就解释了这是优先顺序:

  • 当前目录的A / config子目录。
  • 当前目录
  • 一个classpath / config包
  • 类path根

它还指出,你可以定义额外的属性文件覆盖如下所示:

 java -jar myproject.jar --spring.config.location=classpath:/overrides.properties 

如果使用spring.config.location ,则还包含application.properties所有默认位置。 这意味着您可以在application.properties设置默认值,并根据需要覆盖特定环境。

我自己在这个问题上的更新4实际上是答案。 其他答案和评论有助于find答案。

谢谢。

您将能够使用外部属性文件path启动您的Spring引导应用程序,如下所示:

 java -jar {jar-file-name}.jar --spring.config.location=file:///C:/{file-path}/{file-name}.properties 

这可能会在晚些时候,但我想我想出了一个更好的方法来加载外部configuration,特别是当你使用java jar myapp.war 而不是@PropertySource(“classpath:some.properties”)运行你的spring-boot应用程序时

该configuration将从项目的根目录或war / jar文件的运行位置加载

 public class Application implements EnvironmentAware { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } @Override public void setEnvironment(Environment environment) { //Set up Relative path of Configuration directory/folder, should be at the root of the project or the same folder where the jar/war is placed or being run from String configFolder = "config"; //All static property file names here List<String> propertyFiles = Arrays.asList("application.properties","server.properties"); //This is also useful for appending the profile names Arrays.asList(environment.getActiveProfiles()).stream().forEach(environmentName -> propertyFiles.add(String.format("application-%s.properties", environmentName))); for (String configFileName : propertyFiles) { File configFile = new File(configFolder, configFileName); LOGGER.info("\n\n\n\n"); LOGGER.info(String.format("looking for configuration %s from %s", configFileName, configFolder)); FileSystemResource springResource = new FileSystemResource(configFile); LOGGER.log(Level.INFO, "Config file : {0}", (configFile.exists() ? "FOund" : "Not Found")); if (configFile.exists()) { try { LOGGER.info(String.format("Loading configuration file %s", configFileName)); PropertiesFactoryBean pfb = new PropertiesFactoryBean(); pfb.setFileEncoding("UTF-8"); pfb.setLocation(springResource); pfb.afterPropertiesSet(); Properties properties = pfb.getObject(); PropertiesPropertySource externalConfig = new PropertiesPropertySource("externalConfig", properties); ((ConfigurableEnvironment) environment).getPropertySources().addFirst(externalConfig); } catch (IOException ex) { LOGGER.log(Level.SEVERE, null, ex); } } else { LOGGER.info(String.format("Cannot find Configuration file %s... \n\n\n\n", configFileName)); } } } } 

希望能帮助到你。

 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <layout>ZIP</layout> </configuration> </plugin> </plugins> </build> java -Dloader.path=file:///absolute_path/external.jar -jar example.jar