Spring Загрузка и несколько внешних файлов конфигурации
У меня есть несколько файлов свойств, которые я хочу загрузить из 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
. Согласно spring папка конфигурации загрузочного doc должна находиться в пути к классам. Но это не ясно из документа, если он будет только отменять applicaiton.properties
оттуда или все свойства в config.
Когда я его протестировал, будет получен только application.properties
, а остальные свойства по-прежнему будут получены из /src/main/resources
. Я попытался предоставить их как список, разделенный запятыми, на spring.config.location
, но набор по умолчанию все еще не переоценивается.
Как сделать mulitiple внешние файлы конфигурации переопределить стандартные?
В качестве обходного пути я в настоящее время использовал app.config.location
(свойство приложения), которое я предоставляю через командную строку. iee
java -jar myapp.jar app.config.location=file:./config
и я изменил свой applicationcontext
на
<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:");
}
Мне бы очень хотелось не использовать вышеупомянутое обходное решение и spring переопределить все внешние файлы конфигурации в пути к классам, как это делается для файла application.properties
.
Ответы
Ответ 1
При использовании Spring Boot свойства загружаются в следующем порядке (см. Внешняя конфигурация в справочном руководстве Spring Boot).
- Аргументы командной строки.
- Свойства системы Java (System.getProperties()).
- Переменные среды ОС.
- Атрибуты JNDI из Java: comp/env
- RandomValuePropertySource, который имеет свойства только в случайном порядке. *.
- Свойства приложения вне вашего упакованного фляги (application.properties, включая YAML и варианты профиля).
- Свойства приложения, упакованные внутри вашего jar (application.properties, включая YAML и варианты профиля).
- Аннотации @PropertySource для ваших классов @Configuration.
- Свойства по умолчанию (задаются с помощью 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 Boot).
Если spring.config.location
содержит каталоги (в отличие от файлов), они должны заканчиваться на/(и будут добавлены с именами, сгенерированными из spring.config.name
перед загрузкой). Путь поиска по умолчанию classpath:,classpath: /config,file:,file:config/
всегда используется, независимо от значения spring.config.location
. Таким образом, вы можете установить значения по умолчанию для вашего приложения в application.properties
(или любом другом spring.config.name
имени, которое вы выберете с помощью spring.config.name
) и переопределить его во время выполнения другим файлом, сохраняя значения по умолчанию.
ОБНОВЛЕНИЕ: Поскольку поведение spring.config.location теперь переопределяет значение по умолчанию вместо добавления к нему. Вам нужно использовать spring.config.additional-location для сохранения значений по умолчанию. Это изменение в поведении с 1.x до 2.x
Ответ 2
При загрузке Spring 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.
Поэтому, когда (на окнах)
set spring.profiles.active=dev
jdbc.host будет принимать значения из jdbc-dev.properties.
для
set spring.profiles.active=default
jdbc.host будет принимать значения из jdbc.properties.
Ответ 3
Взгляните на 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;
}
Ответ 4
Spring boot 1.X и Spring Boot 2.X не предоставляют одинаковые параметры и поведение для Externalized Configuration
.
Очень хороший ответ M. 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
.
-
Параметры инициализации ServletContext
.
-
Атрибуты JNDI из java:comp/env
.
-
Свойства системы Java (System.getProperties()
).
-
Переменные среды ОС.
-
RandomValuePropertySource
который имеет свойства только в случайном порядке. *.
-
Специфичные для профиля свойства приложения вне вашего упакованного jar (application-{profile}.properties
и YAML варианты).
-
Специфичные для профиля свойства приложения, упакованные внутри вашего jar (application-{profile}.properties
и YAML варианты).
-
Свойства приложения за пределами вашего упакованного фляги (application.properties
и YAML варианты).
-
Свойства приложения, упакованные внутри вашего jar (application.properties
и YAML варианты).
-
Аннотации @PropertySource
для ваших классов @Configuration
. Свойства по умолчанию (задаются установкой SpringApplication.setDefaultProperties
).
Чтобы указать файлы внешних свойств, эти параметры должны вас заинтересовать:
-
Специфичные для профиля свойства приложения вне вашего упакованного jar (application-{profile}.properties
и YAML варианты).
-
Свойства приложения за пределами вашего упакованного фляги (application.properties
и YAML варианты).
-
Аннотации @PropertySource
для ваших классов @Configuration
. Свойства по умолчанию (задаются установкой SpringApplication.setDefaultProperties
).
Вы можете использовать только один из этих 3 вариантов или комбинировать их в соответствии с вашими требованиями.
Например, для очень простых случаев достаточно использовать только специфичные для профиля свойства, но в других случаях вы можете использовать как специфичные для профиля свойства, свойства по умолчанию, так и @PropertySource
.
Расположение по умолчанию для файлов application.properties
О файлах application.properties
(и их варианте) по умолчанию Spring загружает их и добавляет их свойства в среду в следующем порядке:
Высшие приоритеты так буквально:
classpath:/,classpath: /config/,file:./,file:./config/
.
Как использовать файлы свойств с конкретными именами?
Расположение по умолчанию не всегда достаточно: расположение по умолчанию, такое как имя файла по умолчанию (application.properties
), может не подходить. Кроме того, как и в вопросе OP, вам может потребоваться указать несколько файлов конфигурации, отличных от application.properties
(и его варианта).
Так что spring.config.name
будет недостаточно.
В этом случае вы должны spring.config.location
явное местоположение с помощью spring.config.location
среды 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/
, порядок поиска становится следующим:
-
file:./custom-config/
-
classpath:custom-config/
spring.config.location
- теперь способ убедиться, что любой файл application.properties
должен быть явно указан.
Для UAR JAR, которые не должны упаковывать файлы application.properties
, это довольно хорошо.
Чтобы сохранить прежнее поведение spring.config.location
при использовании Spring Boot 2, вы можете использовать новое spring.config.additional-location
вместо spring.config.location
которое по-прежнему добавляет местоположения, как указано в документации:
Кроме того, когда настраиваемые расположения конфигурации настраиваются с помощью spring.config.additional-location
, они используются в дополнение к расположениям по умолчанию.
На практике
Итак, предположим, что, как и в вопросе OP, у вас есть 2 внешних файла свойств для указания и 1 файл свойств, включенный в uber jar.
Чтобы использовать только указанные вами файлы конфигурации:
-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
в последнем примере не требуется, поскольку местоположения по умолчанию имеют это и что местоположения по умолчанию здесь не перезаписываются, а расширяются.
Ответ 5
У меня была та же проблема. Я хотел иметь возможность перезаписать внутренний файл конфигурации при запуске с помощью внешнего файла, аналогичного обнаружению Spring Boot application.properties.
В моем случае это файл user.properties, в котором хранятся мои приложения.
Мои требования:
Загрузите файл из следующих мест (в этом порядке)
- Путь к классам
- Подкаталог A/config текущего каталога.
- Текущий каталог
- Из каталога или местоположения файла, заданного параметром командной строки при запуске
Я придумал следующее решение:
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 =/directory/myproperties.properties, чтобы использовать местоположение свойств, которое плавает на моей лодке.
Важная деталь здесь: используйте пустую строку в качестве значения по умолчанию для свойства .location в аннотации @Value, чтобы избежать ошибок, когда свойство не установлено.
Соглашение для свойства .location: Используйте каталог или путь к файлу свойств как property.location.
Если вы хотите переопределить только определенные свойства, свойство PropertiesFactoryBean с setIgnoreResourceNotFound (true) можно использовать с массивом ресурсов, установленным в качестве местоположений.
Я уверен, что это решение может быть расширено для обработки нескольких файлов...
ИЗМЕНИТЬ
Здесь мое решение для нескольких файлов:) Как и раньше, это можно комбинировать с 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;
}
}
Ответ 6
spring boot позволяет нам писать разные профили для записи в разных средах, например, мы можем иметь отдельные файлы свойств для производства, 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
Ответ 7
У меня возникла аналогичная проблема и, наконец, выяснил причину: файл application.properties имел неправильные атрибуты собственности и rwx. Поэтому, когда tomcat запущен, файл application.properties находился в нужном месте, но принадлежал другому пользователю:
$ chmod 766 application.properties
$ chown tomcat application.properties
Ответ 8
это простой подход с использованием spring boot
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
ваше приложение spring для загрузки
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(testApplication.class, args);
}
}
и предопределенный контекст application.properties
spring.profiles.active = one
вы можете написать столько классов конфигурации, сколько хотите, и включить/отключить их, установив spring.profiles.active = имя/имена профиля {разделенные запятыми}
поскольку вы можете видеть, что spring загрузится, просто нужно когда-нибудь ознакомиться, стоит упомянуть, что вы также можете использовать @Value в своих полях
@Value("${test.one}")
String str;
Ответ 9
Я обнаружил, что это полезный шаблон для подражания:
@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"
(Spring также будет искать файлы.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
Ответ 10
Модифицированная версия решения @mxsb, которая позволяет нам определять несколько файлов, и в моем случае это файлы yml.
В моем приложении -dev.yml я добавил эту конфигурацию, которая позволяет мне вводить все yml, в которых есть -dev.yml. Это также может быть список определенных файлов. "Путь к классам: /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 файлы для каждого профиля, загрузить их и внедрить их непосредственно в конфигурацию Spring перед инициализацией bean-компонентов.
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);
}
}
}
Ответ 11
Если вы хотите переопределить значения, указанные в файле 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 найдет файл свойств для вас
Ответ 12
Я столкнулся с множеством проблем, пытаясь понять это. Вот моя установка,
Dev Env: Windows 10, Java: 1.8.0_25, Spring Boot: 2.0.3.RELEASE, Spring: 5.0.7.RELEASE
Я обнаружил, что пружина придерживается концепции "Разумные настройки по умолчанию". Это означает, что все ваши файлы свойств должны быть частью вашего боевого файла. Оказавшись там, вы можете затем переопределить их, используя свойство командной строки "--spring.config.additional-location" для указания на внешние файлы свойств. Но это НЕ РАБОТАЕТ, если файлы свойств не являются частью исходного файла war.
Демонстрационный код: https://github.com/gselvara/spring-boot-property-demo/tree/master