Различная переменная свойства для локальной и рабочей среды (Spring)
Я работаю над веб-приложением Spring, где мне нужно иметь переменную, которая будет иметь другое значение в локальной среде и другое значение в рабочей среде.
Для примера (каталог загрузки файлов). Мой каталог загрузки файлов отличается для локальной и prod-среды.
В настоящее время я делаю это, проверяя имя хоста (если "localhost", затем A else B) и применяя этот подход. Есть ли еще один способ решить эту проблему через файлы свойств. Кто-нибудь дает мне указания на подход к этому?
Ответы
Ответ 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