Подтвердить что ты не робот

Различная переменная свойства для локальной и рабочей среды (Spring)

Я работаю над веб-приложением Spring, где мне нужно иметь переменную, которая будет иметь другое значение в локальной среде и другое значение в рабочей среде.

Для примера (каталог загрузки файлов). Мой каталог загрузки файлов отличается для локальной и prod-среды.

В настоящее время я делаю это, проверяя имя хоста (если "localhost", затем A else B) и применяя этот подход. Есть ли еще один способ решить эту проблему через файлы свойств. Кто-нибудь дает мне указания на подход к этому?

4b9b3361

Ответ 1

Вы можете загрузить свойства на основе текущего профиля или профилей spring. Чтобы установить профиль spring, я в основном устанавливаю системное свойство с именем spring.profiles.active на нужное значение, например. development или production.

Концепция довольно проста. Прочитайте текущий активный профиль из свойства системы. Создайте имя файла и загрузите файл свойств с помощью PropertySourcesPlaceholderConfigurer. Использование PropertySourcesPlaceholderConfigurer упростит доступ к этим свойствам через аннотации @Value. Обратите внимание, что в этих примерах предполагается, что один профиль активен. Возможно, потребуется дополнительная помощь, когда активны несколько профилей.

Конфигурация на основе Java

@Configuration
public class MyApplicationConfiguration {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        String activeProfile = System.getProperty("spring.profiles.active", "production");
        String propertiesFilename = "app-" + activeProfile + ".properties";

        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource(propertiesFilename));

        return configurer;
    }
}

Вы также можете импортировать несколько классов конфигурации, аннотированных с помощью @Profile. spring будет выбирать, какую конфигурацию использовать на основе активных профилей. Каждый класс может добавить свою собственную версию PropertySourcesPlaceholderConfigurer в контекст приложения.

@Configuration
@Import({Development.class, Production.class})
public class MyApplicationConfiguration {}

@Configuration
@Profile("development")
public class Development {}

@Configuration
@Profile // The default
public class Production {}

Как отметил в своем комментарии Эмерсон Фарруджи, подход @Profile для каждого класса немного радикален для выбора PropertySourcesPlaceholderConfigurer. Аннотирование объявления @Bean было бы намного проще.

@Configuration
public class MyApplicationConfiguration {

    @Bean
    @Profile("development")
    public static PropertySourcesPlaceholderConfigurer developmentPropertyPlaceholderConfigurer() {
        // instantiate and return configurer...
    }

    @Bean
    @Profile // The default
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        // instantiate and return configurer...
    }
}

Ответ 2

Одно решение, которое не включает в себя Spring Profiles, - это использовать что-то вроде следующего:

<context:property-placeholder location="classpath*:config.properties,file:/path/config/config.properties"
                              ignore-unresolvable="false" ignore-resource-not-found="true"/>

Это означает, что Spring ищет свойства, используя два файла, файл в вашем банке/войне и тот, который может быть где угодно в файловой системе. Инициатор ignore-resource-not-found означает, что если один из файлов не найден, Spring не будет жаловаться.

Используя эту настройку, второй файл может управляться людьми DevOps и может содержать все, что их выбирает, тем самым переопределяя любые свойства в файле свойств свойств classpath.

ОБНОВЛЕНИЕ:

Вы можете сделать то же самое с конфигурацией Java, используя следующий bean в своем классе конфигурации

@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
    final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();

    Resource[] resources = new Resource[ ] {
            new ClassPathResource( "config.properties" ),
            new FileSystemResource("/path/config/config.properties")
    };

    pspc.setLocations( resources );
    pspc.setIgnoreResourceNotFound(true);
    pspc.setIgnoreUnresolvablePlaceholders(false);
    return pspc;
}

Ответ 3

Я бил головой полдня на этом, и решение, в котором я закончил, - это комбинация других ответов здесь.

Решение Bart имело для меня недостаток использования динамического файла prop, так что моя IDE "забыла" все об этом и не могла предложить мне, какие свойства были использованы и где. Решение Geoand имело для меня недостаток, что конфигурационный файл "должен быть где-то на месте". Я вижу, почему это удобно в определенных сценариях, но я предпочитаю использовать один артефакт для развертывания в любой среде, поэтому мне не нужно "припарковывать" файлы в стратегических местах, чтобы приложение могло забрать.

Таким образом, решение для меня:

- config.properties (default properties, usually local development env)
- config.staging.properties (overrides depending on the env)
- config.prod.properties (overrides depending on the env)

<context:property-placeholder ignore-resource-not-found="true"
                              location="config.properties,
                                        config-${profile}.properties"/>

Магия - это ignore-resource-not-found="true", которая позволяет мне запускать локальную разработку env без установки какой-либо специальной переменной profile. Недопустимый файл будет просто проигнорирован.

Вместо этого я устанавливаю эту переменную в моей различной среде развертывания, например. -Dprofile=staging, а затем файл будет найден и будут применены переопределения.

Ответ 4

В моем случае выше ни одно из решений не сработало, поэтому я немного поработал с Google и, наконец, нашел для него какое-то рабочее решение.

Я изменил вышеуказанный класс следующим образом:

@Configuration
@PropertySource("classpath:application-${spring.profiles.active}.properties")
public class MyApplicationConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    return configurer;
}
}

Вместо определения динамического имени файла внутри метода. Я определяю имя файла, как показано ниже, что делает магию для меня.

@PropertySource("classpath:application-${spring.profiles.active}.properties")

на вершине класса. Следуя решению Барт, я не получил никаких ошибок, но я получил все свойства для значения null, определенного в файлах свойств.

Используя мой подход, Spring может распознавать свойства, определенные в аргументах виртуальной машины и в переменной окружения. Примечание: я использую не загрузочный проект.

Ответ 5

вы можете добавить -Dspring.profile.active = local в ваше приложение загрузки spring, когда вы запустите свой сервер. Он выберет application-local.properties