Spring Boot: 뚱뚱한 항아리가 있는 임의의 디렉토리에서 외부 application.properties 파일을 사용할 수 있습니까?
여러 application.properties 파일을 가질 수 있습니까? ( 편집 : 이 질문은 제목에 있는 질문으로 발전했습니다.)
2개의 파일을 만들려고 했습니다.
- 첫 번째는 응용 프로그램 Jar의 루트 폴더에 있습니다.
- 두 번째는 classpath에 지정된 디렉토리에 있습니다.
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 질문을 참조했습니다. 스프링 부트 속성 런처를 사용할 수 없습니다 . BTW, Spring Boot Maven Plugin 문서( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html )에는 ZIP 트리거를 지정한다는 언급이 없습니다. PropertiesLauncher가 사용됩니다. (아마도 다른 문서에서?)
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 파일이 로드됩니다.
보너스로 해당 디렉토리의 모든 파일(예: 정적 html 파일)은 로더 경로에 있으므로 jar에서도 액세스할 수 있습니다.
UPDATE 2에서 언급한 non-jar(확장) 버전의 경우 클래스 경로 순서 문제가 있을 수 있습니다.
(BTW, 이 문제에 대해 보다 구체적으로 질문의 제목을 변경했습니다.)
Spring Boot의 기본값을 변경하지 않은 경우(즉 , 속성 소스 처리를 사용 중이 @EnableAutoConfiguration
거나 @SpringBootApplication
변경하지 않은 경우) 다음 순서로 속성을 찾습니다(가장 높은 값이 가장 낮은 값보다 우선 적용됨).
/config
현재 디렉토리 의 하위 디렉토리- 현재 디렉토리
- 클래스 경로
/config
패키지 - 클래스 경로 루트
위의 목록 은 문서의 이 부분에 언급되어 있습니다.
이것이 의미하는 바는 예를 들어 application.properties
아래 src/resources
에 속성이 있는 경우 패키지된 jar의 "옆에" application.properties
있는 /config
디렉토리 에서 찾은 동일한 이름을 가진 속성에 의해 무시 된다는 것입니다.
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 하위 디렉토리.
- 현재 디렉토리
- 클래스 경로 /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 질문을 참조했습니다. 스프링 부트 속성 런처를 사용할 수 없습니다 . BTW, Spring Boot Maven Plugin 문서( http://docs.spring.io/spring-boot/docs/1.1.7.RELEASE/maven-plugin/repackage-mojo.html )에는 ZIP 트리거를 지정한다는 언급이 없습니다. PropertiesLauncher가 사용됩니다. (아마도 다른 문서에서?)
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 파일이 로드됩니다.
보너스로 해당 디렉토리의 모든 파일(예: 정적 html 파일)은 로더 경로에 있으므로 jar에서도 액세스할 수 있습니다.
UPDATE 2에서 언급한 non-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
이것은 늦게 올 수도 있지만 특히 @PropertySource("classpath:some.properties") 대신 사용하여 스프링 부트 앱을 실행할 때 외부 구성을 로드하는 더 좋은 방법을 java jar myapp.war
찾은 것 같습니다.
구성은 프로젝트의 루트 또는 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));
}
}
}
}
도움이 되기를 바랍니다.
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-boot 실행 가능한 jar 문서 및 이 링크를 참조하십시오.
일반적인 MainApp이 여러 개 있는 경우 실행 가능한 jar에 사용할 기본 클래스를 Spring Boot에 알리는 방법 을 사용할 수 있습니다 .
loader.properties에서 환경 변수 LOADER_PATH 또는 loader.path를 설정하여 추가 위치를 추가할 수 있습니다(아카이브 내의 디렉토리, 아카이브 또는 디렉토리의 쉼표로 구분된 목록). 기본적으로 loader.path는 java -jar 또는 java -cp 방식 모두에서 작동합니다.
그리고 항상 그렇듯이 디버깅 목적으로 선택해야 하는 application.yml을 재정의하고 정확하게 지정할 수 있습니다.
--spring.config.location=/some-location/application.yml --debug
yml 파일에 대한 솔루션:
1. jar 응용 프로그램과 동일한 디렉토리에 yml 복사
2. 명령 실행, 예 xxx.yml
:
java -jar app.jar --spring.config.location=xxx.yml
잘 작동하지만 시작 로거에서 INFO:
No active profile set .........
maven 설치를 사용하여 스프링 부트 jar를 생성하고 속성 파일 및 lib 폴더와 같은 모든 리소스를 jar 외부에서 생성하려는 경우 ... 그런 다음 내가 원하는 출력 폴더를 정의하는 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>
나는 그것이 뾰족한 질문이라는 것을 알고 있으며 op는 다른 속성 파일을로드하기를 원했습니다.
내 대답은 이와 같은 맞춤 해킹을 하는 것은 끔찍한 생각이라는 것입니다.
클라우드 파운드리와 같은 클라우드 공급자와 함께 spring-boot를 사용하고 있다면 스스로에게 호의를 베풀고 클라우드 구성 서비스를 사용하십시오
https://spring.io/projects/spring-cloud-config
마술과 같은 default/dev/project-default/project-dev 특정 속성을 로드하고 병합합니다.
다시 말하지만, Spring 부트는 이미 이를 수행할 수 있는 충분한 방법을 제공합니다. https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
바퀴를 재발명하지 마십시오.
java -jar server-0.0.1-SNAPSHOT.jar --spring.config.location=application-prod.properties
ReferenceURL : https://stackoverflow.com/questions/26140784/spring-boot-is-it-possible-to-use-external-application-properties-files-in-arbi
'IT이야기' 카테고리의 다른 글
Java 8의 새로운 java.util.Arrays 메소드가 모든 기본 유형에 대해 오버로드되지 않는 이유 (0) | 2021.10.07 |
---|---|
Spring과 Spring MVC 프레임워크의 차이점 (0) | 2021.10.07 |
Collection 또는 Iterable의 모든 요소가 단일 특정 Matcher와 일치한다고 주장하는 Hamcrest "for each" Matcher가 있을까 (0) | 2021.10.07 |
Redux 사용 (0) | 2021.10.07 |
새로운 FragmentTransaction commitNow()는 내부 작동 원리 (0) | 2021.10.07 |