#spring #spring-boot
#весна #пружинный ботинок
Вопрос:
Начиная с Spring Boot 2.4.0, из того, что я почерпнул из справочной документации, я должен иметь возможность привязывать несколько application.yaml
файлов из рабочего каталога к ConfigurationProperties
:
Расположение подстановочных знаков особенно полезно в такой среде, как Kubernetes, когда существует несколько источников свойств конфигурации.
Например, если у вас есть некоторая конфигурация Redis и некоторая конфигурация MySQL, вы можете захотеть сохранить эти две части конфигурации отдельно, требуя при этом, чтобы обе они присутствовали в файле application.properties. Это может привести к тому, что два отдельных файла application.properties будут смонтированы в разных местах, таких как /config/redis/application.properties и /config/mysql/application.properties . В таком случае наличие подстановочного знака config/*/ приведет к обработке обоих файлов.
По умолчанию Spring Boot включает config/*/ в места поиска по умолчанию. Это означает, что будет произведен поиск во всех подкаталогах каталога /config за пределами вашего jar.
Насколько я понимаю, следующий тестовый пример показывает, что это работает не так, как описано:
Иерархия проекта:
config/
first/
application.yaml
second/
application.yaml
src/
main/
kotlin/
test/
Application.kt
test/
kotlin/
test/
TestCase.kt
config/first/application.yaml
composite:
from-first-file:
it: works
config/second/application.yaml
composite:
from-second-file:
it: works
src/main/kotlin/test/Application.kt
@SpringBootApplication(proxyBeanMethods = false)
@EnableConfigurationProperties(CompositeProperties::class)
class Application
fun main(vararg args: String) {
runApplication<Application>(*args)
}
@ConstructorBinding
@ConfigurationProperties("composite")
data class CompositeProperties(
val fromFirstFile: Map<String, String> = mapOf(),
val fromSecondFile: Map<String, String> = mapOf()
)
src/test/kotlin/test/TestCase.kt
@SpringBootTest
class TestCase {
@Autowired
private lateinit var compositeProperties: CompositeProperties
@Test
fun `first file is bound to configuration properties`() {
assertThat(compositeProperties.fromFirstFile).containsEntry("it", "works")
}
@Test
fun `second file is bound to configuration properties`() {
assertThat(compositeProperties.fromSecondFile).containsEntry("it", "works")
}
}
Первый тест пройден, второй не выполняется. Я попробовал несколько вариантов, чтобы исключить крайние случаи, и похоже, что второй файл полностью пропущен. Например, я попытался установить значение spring.application.name
во втором файле, и оно также не учитывается.
Если это действительно ошибка, есть ли обходной путь, который я мог бы использовать, пока это не будет исправлено?
Комментарии:
1. Можете ли вы попробовать
config
каталог внутри/src/main
?2. Я просто предполагаю, но может ли такое поведение быть связано с тем, что spring не объединяет деревья свойств. т.е. если у вас было два
ConfigurationProperties
класса, которые загружали разные деревья yaml базового уровня — composite1 и composite2, это работает?3. конфигурация должна находиться в каталоге рядом с вашим файлом jar, поскольку вы не используете файл jar, это правило не применяется.
4. @Steephen Я мог бы, но какой в этом смысл, поскольку это вообще не мое требование? В любом случае, ничто не привязывается при выполнении того, что вы предлагаете
5. @HopeyOne Как упоминалось в OP, я попытался добавить другое свойство ко второму файлу, и оно также не привязано, так что это должно дать нам четкий намек на то, что ваше предложение не сработает; и действительно, это не так
Ответ №1:
Как я и подозревал, это ошибка в 2.4.0. Пока проблема не будет устранена, ее можно обойти, установив spring.config.use-legacy-processing=true
.