Весняне завантаження та кілька зовнішніх файлів конфігурації


125

У мене є кілька файлів властивостей, які я хочу завантажити з classpath. Є один набір за замовчуванням, під /src/main/resourcesяким знаходиться частина myapp.jar. Мої springcontextочікують, що файли будуть на уроці. тобто

<util:properties id="Job1Props"
    location="classpath:job1.properties"></util:properties>

<util:properties id="Job2Props"
    location="classpath:job2.properties"></util:properties>

Мені також потрібна можливість змінити ці властивості із зовнішнім набором. У мене зовнішня папка конфігурації cwd. Згідно з папкою config doc до весільного завантаження слід знаходитись на classpath. Але це не зрозуміло з doc, якщо він буде лише заміняти applicaiton.propertiesзвідти або всі властивості в config.

Коли я тестував це, application.propertiesвибираєте лише , а решта властивостей все ще збираються /src/main/resources. Я спробував spring.config.locationпоставити їх як список, розділений комами, але набір за замовчуванням все ще не змінюється.

Як зробити так, щоб багатомовні зовнішні файли конфігурації замінили типові за замовчуванням?

На даний момент я використовував app.config.location(властивість програми), яку я постачаю за допомогою командного рядка. тобто

java -jar myapp.jar app.config.location=file:./config

і я змінив applicationcontextTo

<util:properties id="Job2Props"
    location="{app.config.location}/job2.properties"></util:properties>

Ось так я роблю розділення між файлом і classpath під час завантаження програми.
ЗМІНИ:

//psuedo code

if (StringUtils.isBlank(app.config.location)) {
            System.setProperty(APP_CONFIG_LOCATION, "classpath:");
}

Я дуже хотів би не використовувати вищезгадане вирішення і весна переосмислить всі зовнішні файли конфігурації на classpath, як це робиться для application.propertiesфайлу.


4
application.propertiesЗавжди буде завантажений, з spring.config.locationви можете додати додаткові місця конфігурації, які перевіряються для файлів (тобто , коли він закінчується з /) , однак , якщо ви поставите запитом список там , що вказує на файли ті будуть завантажені. Це також пояснено у Посібнику з весняних завантажень тут
М. Дейнум

Відповіді:


155

При використанні Spring Boot властивості завантажуються в наступному порядку (див. Розширена конфігурація у довіднику Spring Boot).

  1. Аргументи командного рядка.
  2. Властивості системи Java (System.getProperties ()).
  3. Змінні середовища ОС.
  4. Атрибути JNDI від java: comp / env
  5. RandomValuePropertySource, який має властивості лише випадковим чином. *
  6. Властивості програми за межами вашої упакованої банки (application.properties включаючи YAML та варіанти профілю).
  7. Властивості програми, упаковані всередині вашої банки (application.properties, включаючи YAML та варіанти профілю).
  8. @PropertySource анотації на ваших класах @Configuration.
  9. Властивості за замовчуванням (вказано за допомогою SpringApplication.setDefaultProperties).

При вирішенні властивостей (тобто @Value("${myprop}")вирішення виконується в зворотному порядку (так, починаючи з 9).

Щоб додати різні файли, ви можете скористатися spring.config.locationвластивостями, що містить список файлів властивостей або розташування файлів (каталогів), розділених комами.

-Dspring.config.location=your/config/dir/

До цього вище буде додано каталог, з яким можна отримати консультації щодо application.propertiesфайлів.

-Dspring.config.location=classpath:job1.properties,classpath:job2.properties

Це додасть файл 2 властивостей до завантажених файлів.

Файли конфігурації за замовчуванням завантажуються перед вказаними додатково spring.config.location, це означає, що останні завжди змінюватимуть властивості, встановлені в попередніх. (Дивіться також цей розділ Посібника з весняного завантаження).

Якщо spring.config.locationмістяться каталоги (на відміну від файлів), вони повинні закінчуватися в / (і додаватимуться до імен, створених spring.config.nameдо завантаження). Шлях пошуку за замовчуванням classpath:,classpath:/config,file:,file:config/завжди використовується незалежно від значення spring.config.location. Таким чином ви можете встановити значення за замовчуванням для вашої програми у application.properties(або будь-якому іншому базовому імені, яке ви вибрали spring.config.name) та замінити його під час виконання іншим файлом, зберігаючи значення за замовчуванням.

ОНОВЛЕННЯ: Оскільки поведінка spring.config.location тепер замінює типовий, а не додавання до нього. Для збереження значень за замовчуванням потрібно використовувати spring.config.additional-location. Це зміна поведінки від 1.x до 2.x


2
Дякую, але я вже прочитав цей документ ref refc, і наступне мене бентежить "-Dspring.config.location = ваш / config / dir /. Вище буде додано каталог, з яким можна отримати консультації щодо файлів application.properties." Що це означає під файлами application.properties. Це лише один файл. У будь-якому випадку, якщо він може зібрати весь каталог з "/" в кінці, мені не потрібно вказувати кожен як список, розділений комами. Я думаю, що я спробував обидва підходи, як я згадував у своєму дописі, але спробую ще одну спробу
nir

Як зазначено в документі, про це буде обрано довідник, як і інші місця за замовчуванням для application.propertiesта application-[env].properties. Він не враховує файли інших властивостей. Про це також йдеться у довідковому посібнику (у розділі, на який веде посилання, та у цитаті з довідника).
М. Дейнум

1
Так, але це не те, що для мене не має сенсу. Навіщо розглядати лише один вид файлів з каталогу на classpath замість цілого каталогу. Примушує вас використовувати лише один файл властивостей, який не є хорошим. Як і в tomcat, я можу налаштувати common.loader для розміщення конкретного каталогу (і все, на чому це зроблено) на classpath, чому не може завантажувати його завантажувач.
nir

3
Цитування документації не корисне. Якби документація була зрозумілою (достатньо? Особливо потрібного способу?), Тоді питання не було б необхідним. Наприклад, у цьому випадку дійсно не зрозуміло, як config.locationі як config.namesвзаємодіяти, хоча, мабуть, це зрозуміло людям, які вже знають, як вони взаємодіють. Чи можете ви оновити свою відповідь, щоб додати щось до документації?
Нарфанатор

13
Це слід оновити, оскільки поведінка spring.config.locationтепер замінює типовий, а не додавання до нього. Потрібно використовувати spring.config.additional-locationдля збереження значень за замовчуванням. Це зміна поведінки від 1.x до 2.x.
Робін

32

З весняним завантаженням spring.config.location працює, просто надайте файли властивостей, розділені комами.

див. нижче код

@PropertySource(ignoreResourceNotFound=true,value="classpath:jdbc-${spring.profiles.active}.properties")
public class DBConfig{

     @Value("${jdbc.host}")
        private String jdbcHostName;
     }
}

можна помістити версію jdbc.properties за замовчуванням всередині програми. Зовнішні версії можуть бути встановлені так.

java -jar target/myapp.jar --spring.config.location=classpath:file:///C:/Apps/springtest/jdbc.properties,classpath:file:///C:/Apps/springtest/jdbc-dev.properties

На основі значення профілю, встановленого за допомогою властивості spring.profiles.active, буде вибрано значення jdbc.host. Так коли (на windows)

set spring.profiles.active=dev

jdbc.host прийме значення з jdbc-dev.properties.

для

set spring.profiles.active=default

jdbc.host прийме значення з jdbc.properties.


Я не вірю, що перший з блоків коду спрацював. Я знаю, як я застряг у цьому, і дотримувався цієї відповіді . Дивіться jira.springsource.org/browse/SPR-8539, на який посилається у відповідь на гідне пояснення.
Совка

27

Весняне завантаження 1.X та Spring Boot 2.X не забезпечують однакових варіантів та поведінки щодо Externalized Configuration.

Дуже гарна відповідь М. Deinum стосується особливостей Spring Boot 1.
Я оновлю для Spring Boot 2 тут.

Джерела та порядок властивостей навколишнього середовища

Spring Boot 2 використовує дуже особливий PropertySourceпорядок, розроблений для забезпечення розумного переосмислення значень. Властивості розглядаються в наступному порядку:

  • Властивості глобальних налаштувань Devtools у вашому домашньому каталозі (~ / .spring-boot-devtools.properties, коли devtools активний).

  • @TestPropertySource анотації на ваших тестах.

  • @SpringBootTest#propertiesатрибут анотації на ваших тестах. Аргументи командного рядка.

  • Властивості з SPRING_APPLICATION_JSON(вбудований JSON вбудований у змінну середовища або властивість системи).

  • ServletConfig параметри init.

  • ServletContext параметри init.

  • Атрибути JNDI від java:comp/env.

  • Властивості системи Java ( System.getProperties()).

  • Змінні середовища ОС.

  • A, RandomValuePropertySourceщо має властивості лише випадковим чином. *

  • Властивості програми, що стосуються профілю, поза вашою упакованою баночкою ( application-{profile}.propertiesта варіантами YAML).

  • Властивості програми, специфічні для профілю, упаковані всередині вашої банки ( application-{profile}.propertiesта варіанти YAML).

  • Властивості програми за межами вашої упакованої банки ( application.propertiesта варіантів YAML).

  • Властивості програми, упаковані всередині вашої банки ( application.propertiesта варіанти YAML).

  • @PropertySourceанотації на ваших @Configurationзаняттях. Властивості за замовчуванням (задаються налаштуваннями SpringApplication.setDefaultProperties).

Щоб вказати файли зовнішніх властивостей, ці параметри повинні вас зацікавити:

  • Властивості програми, що стосуються профілю, поза вашою упакованою баночкою ( application-{profile}.propertiesта варіантами YAML).

  • Властивості програми за межами вашої упакованої банки ( application.propertiesта варіантів YAML).

  • @PropertySourceанотації на ваших @Configurationзаняттях. Властивості за замовчуванням (задаються налаштуваннями SpringApplication.setDefaultProperties).

Ви можете використовувати лише один із цих 3 варіантів або комбінувати їх відповідно до своїх вимог.
Наприклад, для дуже простих випадків, що використовують лише властивості, характерні для профілю, достатньо, але в інших випадках ви можете використовувати як властивості, характерні для профілю, так і властивості за замовчуванням @PropertySource.

Місце за замовчуванням для файлів application.properties

Про application.propertiesфайли (і варіант) за замовчуванням Spring завантажує їх і додає їх властивості в середовище з них у такому порядку:

  • Підкаталог / config у поточному каталозі

  • Поточний каталог

  • Пакет classpath / config

  • Корінь класового шляху

Вищі пріоритети настільки буквально:
classpath:/,classpath:/config/,file:./,file:./config/ .

Як використовувати файли властивостей із конкретними іменами?

Місце розташування за замовчуванням не завжди достатньо: місця за замовчуванням, такі як назва файлу за замовчуванням ( application.properties), можуть не відповідати. Крім того, як і у запитанні про ОП, вам може знадобитися вказати кілька файлів конфігурації, окрім application.properties(та варіанту).
Такspring.config.name буде недостатньо.

У цьому випадку вам слід вказати чітке розташування, використовуючи spring.config.locationвластивість оточення (що є розділеним комами списком розташування каталогів або шляхів до файлів).
Щоб бути вільним щодо шаблону імен файлів, надайте перевагу списку шляхів файлів над списком каталогів.
Наприклад, так:

java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

Цей спосіб є найбільш багатослівним, що просто вказує папку, але це також спосіб дуже тонко вказати наші конфігураційні файли та чітко задокументувати ефективно використовувані властивості.

spring.config.location замінює місця за замовчуванням замість того, щоб додавати їх

З Spring Boot 1 spring.config.locationаргумент додає вказані місця у середовищі Spring.
Але з Spring Boot 2 spring.config.locationзамінює місця за замовчуванням, які використовує Spring, на вказані місця в середовищі Spring, як зазначено в документації .

Коли налаштовані власні розташування конфігуруються за допомогою spring.config.location, вони замінюють місця за замовчуванням. Наприклад, якщо spring.config.locationналаштований зі значенням classpath:/custom-config/, file:./custom-config/порядок пошуку стає наступним:

  1. file:./custom-config/

  2. classpath:custom-config/

spring.config.locationТепер це спосіб переконатися, що будь-який application.propertiesфайл повинен бути чітко вказаний.
Для uber JAR, які не мають пакетуapplication.properties файли, це досить приємно.

Щоб зберегти стару поведінку під spring.config.locationчас використання Spring Boot 2, ви можете використовувати нове spring.config.additional-locationвластивість замість того, spring.config.locationщо все ще додає місця, як зазначено в документації :

Крім того, коли налаштовані власні місця конфігурування налаштовано за допомогою spring.config.additional-location, вони використовуються на додаток до стандартних місць.


На практиці

Отже, припустимо, що як і у запитанні про ОП, у вас є 2 зовнішніх файли властивостей, які потрібно вказати, та 1 файл властивостей, що входить до банку uber.

Щоб використовувати лише вказані файли конфігурації:

-Dspring.config.location=classpath:/job1.properties,classpath:/job2.properties,classpath:/applications.properties   

Щоб додати до них файли конфігурації у місцях за замовчуванням:

-Dspring.config.additional-location=classpath:/job1.properties,classpath:/job2.properties

classpath:/applications.properties в останньому прикладі не потрібно, оскільки локації за замовчуванням мають це, і що типові місця тут не перезаписані, а розширені.


Ваша відповідь справді повна, за винятком одного: де Spring знайде зовнішню конфігурацію job1.properties на диску, якщо ви просто вкажете: "classpath: /job1.properties"? Як ви додали тут свій каталог, що містить зовнішні властивості, до classpath?
Трістан

@ Тристан, в основному, весна може читати один application.propertiesз усіма параметрами і кілька ${file_name}.propertiesз частково визначеними наборами властивостей. Отже, якщо ви використовуєте @PropertySourceчи інші міцні посилання на файли, ви можете створити інший зовнішній файл і змінити ці властивості (Наприклад: з classpath:file.properties).
Mister_Jesus

23

Погляньте на PropertyPlaceholderConfigurer, я вважаю його більш зрозумілим, ніж анотацію.

напр

@Configuration
public class PropertiesConfiguration {


    @Bean
    public PropertyPlaceholderConfigurer properties() {
        final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
//        ppc.setIgnoreUnresolvablePlaceholders(true);
        ppc.setIgnoreResourceNotFound(true);

        final List<Resource> resourceLst = new ArrayList<Resource>();

        resourceLst.add(new ClassPathResource("myapp_base.properties"));
        resourceLst.add(new FileSystemResource("/etc/myapp/overriding.propertie"));
        resourceLst.add(new ClassPathResource("myapp_test.properties"));
        resourceLst.add(new ClassPathResource("myapp_developer_overrides.properties")); // for Developer debugging.

        ppc.setLocations(resourceLst.toArray(new Resource[]{}));

        return ppc;
    }

Дуже дякую за цю відповідь. Чи можете ви, будь ласка, повідомити мені, як я можу досягти того ж у проекті, який має конфігурації XML для різних речей без базового XML-файлу? Ваша відповідь вище допомогла мені в іншому проекті, який базувався на анотації. Ще раз дякую за це.
Четан

8

це один простий підхід із використанням весняного завантаження

TestClass.java

@Configuration
@Profile("one")
@PropertySource("file:/{selected location}/app.properties")
public class TestClass {

    @Autowired
    Environment env;

    @Bean
    public boolean test() {
        System.out.println(env.getProperty("test.one"));
        return true;
    }
}

app.properties контекст, в вашому обраному місці

test.one = 1234

ваш весняний додаток для завантаження

@SpringBootApplication

public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(testApplication.class, args);
    }
}

і заздалегідь заданий контекст application.properties

spring.profiles.active = one

ви можете записати стільки класів конфігурації, скільки вам потрібно, і ввімкнути / вимкнути їх, просто встановивши spring.profiles.active = ім'я / імена профілю {розділені комами}

як ви бачите, весняний черевик - це чудово, що його просто потрібно десь ознайомити, варто згадати, що ви можете використовувати @Value і на своїх полях

@Value("${test.one}")
String str;

7

У мене була така ж проблема. Я хотів мати можливість замінити внутрішній файл конфігурації при запуску зовнішнім файлом, подібним до виявлення Spring Boot application.properties. У моєму випадку це файл user.properties, де зберігаються користувачі моїх програм.

Мої вимоги:

Завантажте файл із таких місць (у цьому порядку)

  1. Класовий шлях
  2. A / config підкаталог поточного каталогу.
  3. Поточний каталог
  4. З каталогу або місця розташування, заданого параметром командного рядка при запуску

Я придумав таке рішення:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

import static java.util.Arrays.stream;

@Configuration
public class PropertiesConfig {

    private static final Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

    private final static String PROPERTIES_FILENAME = "user.properties";

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Properties userProperties() throws IOException {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(PROPERTIES_FILENAME),
                new PathResource("config/" + PROPERTIES_FILENAME),
                new PathResource(PROPERTIES_FILENAME),
                new PathResource(getCustomPath())
        };
        // Find the last existing properties location to emulate spring boot application.properties discovery
        final Resource propertiesResource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties userProperties = new Properties();

        userProperties.load(propertiesResource.getInputStream());

        LOG.info("Using {} as user resource", propertiesResource);

        return userProperties;
    }

    private String getCustomPath() {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + PROPERTIES_FILENAME;
    }

}

Тепер програма використовує ресурс classpath, але перевіряє ресурс і в інших місцях. Буде вибраний та використаний останній ресурс, який існує. Я можу запустити свою програму з java -jar myapp.jar --properties.location = / каталог / myproperties.properties, щоб використовувати розташування властивостей, на яких пливе мій човен.

Тут важлива деталь: Використовуйте порожню рядок як значення за замовчуванням для Properties.location в анотації @Value, щоб уникнути помилок, коли властивість не встановлено.

Конвенція для Properties.location: Використовуйте каталог або шлях до файлу властивостей як properties.location.

Якщо ви хочете замінити лише певні властивості, PropertiesFactoryBean з setIgnoreResourceNotFound (true) може бути використаний з масивом ресурсів, встановленим як розташування.

Я впевнений, що це рішення можна розширити для обробки декількох файлів ...

EDIT

Тут моє рішення для декількох файлів :) Як і раніше, це можна поєднувати з PropertiesFactoryBean.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;

@Configuration
class PropertiesConfig {

    private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);
    private final static String[] PROPERTIES_FILENAMES = {"job1.properties", "job2.properties", "job3.properties"};

    @Value("${properties.location:}")
    private String propertiesLocation;

    @Bean
    Map<String, Properties> myProperties() {
        return stream(PROPERTIES_FILENAMES)
                .collect(toMap(filename -> filename, this::loadProperties));
    }

    private Properties loadProperties(final String filename) {
        final Resource[] possiblePropertiesResources = {
                new ClassPathResource(filename),
                new PathResource("config/" + filename),
                new PathResource(filename),
                new PathResource(getCustomPath(filename))
        };
        final Resource resource = stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .reduce((previous, current) -> current)
                .get();
        final Properties properties = new Properties();

        try {
            properties.load(resource.getInputStream());
        } catch(final IOException exception) {
            throw new RuntimeException(exception);
        }

        LOG.info("Using {} as user resource", resource);

        return properties;
    }

    private String getCustomPath(final String filename) {
        return propertiesLocation.endsWith(".properties") ? propertiesLocation : propertiesLocation + filename;
    }

}

приємне подолання. Як і конструкти java8! у будь-якому випадку я не можу використовувати це, як мені потрібно кілька бобів властивостей, а не один. Якщо ви бачите мої редактори EDITS, моє вирішення досить схоже та акуратне для мого використання.
nir

Я опублікував версію для декількох файлів, просто для повноти;)
mxsb

6

весняний завантаження дозволяє нам писати різні профілі для запису для різних середовищ, наприклад, ми можемо мати окремі файли властивостей для виробництва, qa та локальних середовищ

файл application-local.properties з конфігураціями відповідно до моєї локальної машини

spring.profiles.active=local

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=users
spring.data.mongodb.username=humble_freak
spring.data.mongodb.password=freakone

spring.rabbitmq.host=localhost
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672

rabbitmq.publish=true

Так само ми можемо записати application-prod.properties та application-qa.properties стільки файлів властивостей, скільки нам потрібно

потім напишіть кілька сценаріїв, щоб запустити програму в різних середовищах, наприклад,

mvn spring-boot:run -Drun.profiles=local
mvn spring-boot:run -Drun.profiles=qa
mvn spring-boot:run -Drun.profiles=prod

5

У мене щойно виникала подібна проблема з цим, і нарешті з'ясував причину: файл application.properties мав неправильні атрибути власності та rwx. Тож, коли tomcat запустив файл application.properties, був у потрібному місці, але належав іншому користувачеві:

$ chmod 766 application.properties

$ chown tomcat application.properties

Я думаю, що у мене є аналогічна проблема. Я встановив tomcat в папці opt. Де ви розмістили файл своєї заявки? Чи слід змінювати також атрибути папки?
anakin59490

3

Змінена версія рішення @mxsb, яка дозволяє нам визначати кілька файлів, і в моєму випадку це файли yml.

У свій додаток-dev.yml я додав цю конфігурацію, яка дозволяє мені вводити всі yml, які мають в них -dev.yml. Це також може бути список конкретних файлів. "classpath: /test/test.yml,classpath: /test2/test.yml"

application:
  properties:
    locations: "classpath*:/**/*-dev.yml"

Це допомагає отримати карту властивостей.

@Configuration

public class PropertiesConfig {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfig.class);

@Value("${application.properties.locations}")
private String[] locations;

@Autowired
private ResourceLoader rl;

@Bean
Map<String, Properties> myProperties() {
    return stream(locations)
            .collect(toMap(filename -> filename, this::loadProperties));
}

private Properties loadProperties(final String filename) {

    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .forEach(propertySource -> {
                    Map source = ((MapPropertySource) propertySource).getSource();
                    properties.putAll(source);
                });

        return properties;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
}

Однак, як у моєму випадку, я хотів би розбити файли yml для кожного профілю та завантажити їх та ввести це безпосередньо у конфігурацію весни перед ініціалізацією бобів.

config
    - application.yml
    - application-dev.yml
    - application-prod.yml
management
    - management-dev.yml
    - management-prod.yml

... Ви отримуєте ідею

Компонент трохи інший

@Component
public class PropertiesConfigurer extends     PropertySourcesPlaceholderConfigurer
    implements EnvironmentAware, InitializingBean {

private final static Logger LOG = LoggerFactory.getLogger(PropertiesConfigurer.class);

private String[] locations;

@Autowired
private ResourceLoader rl;
private Environment environment;

@Override
public void setEnvironment(Environment environment) {
    // save off Environment for later use
    this.environment = environment;
    super.setEnvironment(environment);
}

@Override
public void afterPropertiesSet() throws Exception {
    // Copy property sources to Environment
    MutablePropertySources envPropSources = ((ConfigurableEnvironment) environment).getPropertySources();
    envPropSources.forEach(propertySource -> {
        if (propertySource.containsProperty("application.properties.locations")) {
            locations = ((String) propertySource.getProperty("application.properties.locations")).split(",");
            stream(locations).forEach(filename -> loadProperties(filename).forEach(source ->{
                envPropSources.addFirst(source);
            }));
        }
    });
}


private List<PropertySource> loadProperties(final String filename) {
    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
    try {
        final Resource[] possiblePropertiesResources = ResourcePatternUtils.getResourcePatternResolver(rl).getResources(filename);
        final Properties properties = new Properties();
        return stream(possiblePropertiesResources)
                .filter(Resource::exists)
                .map(resource1 -> {
                    try {
                        return loader.load(resource1.getFilename(), resource1);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }).flatMap(l -> l.stream())
                .collect(Collectors.toList());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

}


3

Якщо ви хочете змінити значення, вказані у вашому файлі application.properties, ви можете змінити свій активний профіль під час запуску програми та створити файл властивостей програми для профілю. Так, наприклад, давайте вкажіть активний профіль "переосмислити", а потім, припустивши, що ви створили новий файл властивостей програми під назвою "application-override.properties" під / tmp, тоді ви можете запустити

java -jar yourApp.jar --spring.profiles.active="override" --spring.config.location="file:/tmp/,classpath:/" 

Значення, визначені у розділі spring.config.location, оцінюються у зворотному порядку. Отже, у моєму прикладі спочатку оцінюється classpat, потім значення файлу.

Якщо файл jar та файл "application-override.properties" знаходяться у поточному каталозі, ви можете насправді просто використовувати

java -jar yourApp.jar --spring.profiles.active="override"

оскільки Spring Boot знайде для вас файл властивостей


1
Він навесні скаже використовувати профіль "переосмислення" як активний профіль; він дійсно перевершить значення, вказане у файлі application.yml або application.properties
acaruci

він буде шукати всередині папки для будь-якого конфігураційного файлу .ymal або .properties, у моєму випадку я поставив лише application-profile.yml, то він приймає правильно, Дякую @ Acaruci, це була приємна поїздка
Ахмед Салем

0

Я вважав, що це корисна модель, яку слід дотримуватися:

@RunWith(SpringRunner)
@SpringBootTest(classes = [ TestConfiguration, MyApplication ],
        properties = [
                "spring.config.name=application-MyTest_LowerImportance,application-MyTest_MostImportant"
                ,"debug=true", "trace=true"
        ]
)

Тут ми перекриваємо використання "application.yml" для використання "application-MyTest_LowerImportance.yml", а також "application-MyTest_MostImportant.yml"
(Весна також шукатиме файли .properties)

В якості додаткового бонусу також включені налаштування налагодження та відстеження в окремому рядку, щоб ви могли коментувати їх, якщо потрібно;]

Налагодження / слід є надзвичайно корисним, оскільки Spring скидає імена всіх файлів, які він завантажує, і тих, які він намагається завантажити.
Такі рядки ви побачите на консолі під час виконання:

TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.properties' (file:./config/application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.xml' (file:./config/application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yml' (file:./config/application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant.yaml' (file:./config/application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.properties' (file:./config/application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.xml' (file:./config/application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yml' (file:./config/application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_LowerImportance.yaml' (file:./config/application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.properties' (file:./application-MyTest_MostImportant.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.xml' (file:./application-MyTest_MostImportant.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yml' (file:./application-MyTest_MostImportant.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_MostImportant.yaml' (file:./application-MyTest_MostImportant.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.properties' (file:./application-MyTest_LowerImportance.properties) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.xml' (file:./application-MyTest_LowerImportance.xml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yml' (file:./application-MyTest_LowerImportance.yml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./application-MyTest_LowerImportance.yaml' (file:./application-MyTest_LowerImportance.yaml) resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.xml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/config/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_MostImportant.yml' (classpath:/application-MyTest_MostImportant.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_MostImportant.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.properties' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.xml' resource not found
DEBUG 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/Users/xxx/dev/myproject/target/test-classes/application-MyTest_LowerImportance.yml' (classpath:/application-MyTest_LowerImportance.yml)
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'classpath:/application-MyTest_LowerImportance.yaml' resource not found
TRACE 93941 --- [   main] o.s.b.c.c.ConfigFileApplicationListener  : Skipped config file 'file:./config/application-MyTest_MostImportant-test.properties' (file:./config/application-MyTest_MostImportant-test.properties) resource not found

-1

У мене виникло багато питань, коли я намагався розібратися в цьому. Ось моя настройка,

Dev Env: Windows 10, Java: 1.8.0_25, Spring Boot: 2.0.3.RELEASE, Весна: 5.0.7.RELEASE

Те, що я знайшов, - весна, - це концепція "Розумні за замовчуванням для конфігурації". Це означає, що ви повинні мати усі свої майнові файли як частину свого військового файлу. Потрапивши туди, ви можете змінити їх за допомогою властивості командного рядка "--spring.config.additional-location", щоб вказати на зовнішні файли властивостей. Але це НЕ ПРАЦЮЄ, якщо файли властивостей не входять до вихідного файлу війни.

Демо-код: https://github.com/gselvara/spring-boot-property-demo/tree/master

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.