Поместите application.properties в папку окружения в ресурсах

Я пишу весеннее загрузочное приложение с тремя средами - локальная, док-станция и рабочая среда. Я хотел бы, чтобы application.properties и несколько других файлов (database.properties и т. Д.) Были выбраны из следующей структуры папок внутри src / main / resources:

src/main/resources
 - local
        - application.properties
        - database.properties
 - dock
        - application.properties
        - database.properties
 - production
        - application.properties
        - database.properties
 - application.properties 

Я использую Maven для создания своего приложения. В профиле Maven я сделал следующую конфигурацию для профилей:

<profiles>
        <!--Local machine configuration-->
        <profile>
            <id>local</id>
            <properties>
                <spring.profiles.active>local</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <build>
                <resources>
                    <resource>
                        <directory>src/main/resources/local</directory>
                        <targetPath>WEB-INF/classes</targetPath>
                        <filtering>true</filtering>
                    </resource>
                </resources>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>2.4</version>
                        <configuration>
                            <webResources>
                                <resource>
                                    <directory>src/main/resources/local</directory>
                                    <targetPath>WEB-INF/classes</targetPath>
                                    <filtering>true</filtering>
                                </resource>
                            </webResources>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <!--Staging docker configuration-->
        <profile>
            <id>dock</id>
            <properties>
                <spring.profiles.active>dock</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>2.4</version>
                        <configuration>
                            <webResources>
                                <resource>
                                    <directory>src/main/resources/dock</directory>
                                    <targetPath>WEB-INF/classes</targetPath>
                                </resource>
                            </webResources>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <!--Production configuration-->
        <profile>
            <id>production</id>
            <properties>
                <spring.profiles.active>production</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>2.4</version>
                        <configuration>
                            <webResources>
                                <resource>
                                    <directory>src/main/resources/production</directory>
                                    <targetPath>WEB-INF/classes</targetPath>
                                </resource>
                            </webResources>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>




<build>
        <finalName>${project.warname}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

В моем основном application.properties я сделал следующую конфигурацию:

spring.profiles.active=@spring.profiles.active@

Когда я запускаю проект, используя mvn spring-boot: run, загружается правильный профиль, но переменные внутри папки application.properties не обнаруживаются Spring. Например, у каждого из моих внутренних application.properties есть переменная, подобная этой:

my.var=This is production.

который я пытаюсь загрузить как

@Value("${my.var}")
private String data;

Я получаю следующее исключение:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'statusController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'my.var' in value "${my.var}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.10.RELEASE.jar:1.5.10.RELEASE]
    at com.onedirect.onedirectemailpushservice.OnedirectEmailPushServiceApplication.main(OnedirectEmailPushServiceApplication.java:10) [classes/:na]
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'my.var' in value "${my.var}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174) ~[spring-core-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:236) ~[spring-core-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210) ~[spring-core-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172) ~[spring-context-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:831) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1086) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.14.RELEASE.jar:4.3.14.RELEASE]
    ... 17 common frames omitted

Я что-то здесь упускаю? Что мне нужно сделать, чтобы сделать эту работу?

PS: я знаю вариант использования application-{env}.properties, который поддерживается весенней загрузкой из коробки, но не хочу его использовать.

1 ответ

Если вашим основным ограничением является структура каталогов, которой вы должны следовать, то вы всегда можете построить свой проект с заданной структурой проекта и использовать spring.config.location свойство среды для настройки расположения файлов свойств, которые вы хотите загрузить. Например:

java -jar my-app.jar --spring.config.location=classpath:local/application.properties,classpath:local/database.properties

Это также рекомендуемый подход в соответствии с документацией по внешней конфигурации:

Если тебе не нравится application.properties в качестве имени файла конфигурации вы можете переключиться на другое, указав spring.config.name свойство окружающей среды. Вы также можете обратиться к явному местоположению, используя spring.config.location свойство среды (разделенный запятыми список каталогов или путей к файлам).

Преимущество использования этого заключается в том, что вы можете предоставить несколько файлов свойств, разделяя их запятой. Это позволяет вам загружать ваши application.properties, database.properties, redis.properties...

Это также позволяет вам удалить конфигурацию Maven, которую вы написали, чтобы изменить ваш путь к классам для каждой среды. Обычно вы не хотите создавать новый JAR-файл для конкретной среды, потому что это означает, что вы в основном создаете новый, непроверенный JAR-файл для производственной среды.


В качестве альтернативы вы можете использовать профили, чтобы убрать это. Например, переименуйте файлы свойств в:

  • application-local.properties
  • application-local-database.properties
  • application-local-redis.properties
  • ...

И запустите ваше приложение с профилями local, local-database и local-redis. Вы можете сделать это, настроив spring.profiles.active, Это также можно сделать во время выполнения, предоставив --spring.profiles.active=local,local-database,local-redis свойство среды:

java -jar --spring.profiles.active=local,local-database,local-redis
Другие вопросы по тегам