是否可以有多个application.properties文件?(编辑:注意,这个问题演变成了标题上的问题。)
我试着有两个文件。
- 第一个是在应用程序Jar中的根文件夹上
- 第二个是在类路径中指定的目录上
2个文件都命名为"application.properties"。
是否可以"合并"两个文件的内容?(第二个文件的属性值将覆盖第一个文件)或者,如果我有一个文件,那么另一个文件将被忽略?
更新1:可以"合并"内容。昨天,第一个似乎被忽略了,但似乎是因为当时有东西坏了。现在效果很好。
更新2:它又回来了!同样,只有两个文件中的一个正在应用。这很奇怪。。。它是在我使用Spring Tool Suite构建应用程序jar文件之后开始的。Jar版本似乎总是忽略第二个版本(在类路径中),而在STS上运行的扩展版本的行为各不相同。我从哪里开始调查?
更新3:
事实上,Jar版本的行为是正确的。这是java.exe的规范。当指定-jar选项时,java.exe将忽略-classpath选项和classpath环境变量,并且类路径将只包含jar文件。因此,类路径上的第二个application.properties文件被忽略。
现在,我如何让类路径上的第二个application.properties被加载?
更新4:
在使用-jar选项时,我设法在外部路径中加载了一个application.properties文件。
密钥是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-boot属性启动器无法使用。BTW,In Spring Boot Maven插件文档(http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html),没有提到指定使用PropertiesLauncher的ZIP触发器。(也许在另一份文件中?)
在构建了jar文件之后,我可以通过检查jar中META-INF/MENIFEST.MF中的Main Class属性来使用PropertiesLauncher。
现在,我可以如下运行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文件。
另外,jar也可以访问该目录中的任何文件(例如静态html文件),因为它位于加载程序路径中。
对于UPDATE 2中提到的非jar(扩展)版本,可能存在类路径顺序问题。
(顺便说一句,我更改了问题的标题,使其更具体地针对这个问题。)
如果您没有更改Spring Boot的默认值(意味着您正在使用@EnableAutoConfiguration
或@SpringBootApplication
,并且没有更改任何属性源处理),那么它将按以下顺序查找属性(最高覆盖最低):
- 当前目录的
/config
子目录 - 当前目录
-
类路径
/config
包 - 类路径根
文件的这一部分提到了上述列表
这意味着,如果在src/resources
下找到一个属性(例如application.properties
),它将被在打包jar的"下一个"/config
目录中的application.properties
中找到的同名属性覆盖。
Spring Boot使用的默认顺序允许非常简单的配置外部化,这反过来又使应用程序易于在多个环境(开发、暂存、生产、云等)中配置
要查看Spring Boot为属性读取提供的一整套功能(提示:有比从application.properties
读取更多的功能),请查看这部分文档。
从我上面的简短描述或完整的文档中可以看出,Spring Boot应用程序对DevOps非常友好!
文档中对此进行了解释:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
这解释了这是优先顺序:
- 当前目录的/config子目录
- 当前目录
- classpath/config包
- 类路径根
它还指出,您可以为覆盖定义额外的属性文件,如:
java -jar myproject.jar
--spring.config.location=classpath:/overrides.properties
如果使用spring.config.location
,则还包括application.properties
的所有默认位置。这意味着您可以在application.properties
中设置默认值,并根据特定环境的需要进行覆盖。
在使用-jar选项时,我设法在外部路径中加载了一个application.properties文件。
密钥是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-boot属性启动器无法使用。BTW,In Spring Boot Maven插件文档(http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html),没有提到指定使用PropertiesLauncher的ZIP触发器。(也许在另一份文件中?)
在构建了jar文件之后,我可以通过检查jar中META-INF/MENIFEST.MF中的Main Class属性来使用PropertiesLauncher。
现在,我可以如下运行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文件。
另外,jar也可以访问该目录中的任何文件(例如静态html文件),因为它位于加载程序路径中。
对于UPDATE 2中提到的非jar(扩展)版本,可能存在类路径顺序问题。
您可以使用以下外部属性文件路径启动春季启动应用程序:
java -jar {jar-file-name}.jar
--spring.config.location=file:///C:/{file-path}/{file-name}.properties
<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
java -jar server-0.0.1-SNAPSHOT.jar --spring.config.location=application-prod.properties
我知道这是一个尖锐的问题,操作想要加载不同的属性文件。
我的答案是,做这样的自定义黑客是一个可怕的想法。
如果你在云代工等云提供商那里使用spring-boot,请帮自己一个忙,使用云配置服务
https://spring.io/projects/spring-cloud-config
它加载并合并默认/dev/project-default/project-dev特定的属性,如魔术
再次,Spring boot已经为您提供了足够多的方法来正确执行此操作https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
请不要重新发明轮子。
这可能会在Late出现,但我认为我找到了加载外部配置的更好方法,尤其是当您使用java jar myapp.war
而不是@PropertySource("classpath:some.properties")运行春季启动应用程序时。
配置将从项目的根目录或从运行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("nnnn");
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... nnnn", configFileName));
}
}
}
}
希望能有所帮助。
另一种灵活的方式,使用包含fat jar(-cp fat.jar)或所有jar(-cp"$jars_DIR/*")的类路径和另一个自定义配置类路径或文件夹,其中通常包含jar外的其他配置文件。因此,不要使用有限的java-jar,而是使用更灵活的类路径方式,如下所示:
java
-cp fat_app.jar
-Dloader.path=<path_to_your_additional_jars or config folder>
org.springframework.boot.loader.PropertiesLauncher
请参阅Spring引导可执行jar文档和此链接
如果你有多个常见的MainApps,你可以使用如何告诉SpringBoot可执行jar使用哪个主类?
您可以通过在LOADER.properties(逗号分隔的目录、归档文件或归档文件中的目录列表)中设置环境变量LOADER_PATH或LOADER.PATH来添加其他位置。loader.path基本上适用于java-jar或java-cp方式。
和往常一样,你可以覆盖并准确地指定应用程序。yml它应该用于调试目的
--spring.config.location=/some-location/application.yml --debug
yml文件的解决方案:
1.将yml复制到与jar应用程序相同的目录中
2.运行命令,例如xxx.yml
:
java -jar app.jar --spring.config.location=xxx.yml
它工作正常,但在启动记录器是信息:
No active profile set .........
当您使用maven安装创建spring-boot-jar时,您希望在jar之外创建所有资源,如属性文件和lib文件夹。。。然后在pom.xml中添加以下代码,在这里我定义了输出文件夹,我想在其中提取和存储jar所需的资源。
<build>
<finalName>project_name_Build/project_name</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/project_name_Build/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>write here the qualified or complete path of main class of application</mainClass>
</manifest>
<manifestEntries>
<Class-Path>. resources/</Class-Path>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
<include>log4j.properties</include>
</includes>
<targetPath>${project.build.directory}/ConsentGatewayOfflineBuild/resources</targetPath>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>application.properties</include>
<include>log4j.properties</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<!-- Ignore/Execute plugin execution -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<!-- copy-dependency plugin -->
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[1.0.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
将要外部化的属性放在jar外部的file.properties或yml中。
@Bean
//Reads database properties from the config.yml
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new FileSystemResource(filePath + File.separator +"config.yml"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
return propertySourcesPlaceholderConfigurer;
}