Часто в файле
application.properties
(или application.yml)
объявляются свойства, значения которых содержат переменные вида ${ENV_PROPERTY_KEY:defaultValue}
:
spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST:localhost}/${POSTGRES_DB_NAME:local_dev_db}
spring.datasource.username=${POSTGRES_USERNAME:root}
spring.datasource.password=${POSTGRES_PASSWORD:root}
spring.datasource.driver-class-name=org.postgresql.Driver
Такой подход позволяет переопределять свойства при запуске приложения в разных средах (local, test, prod и т.д.).
Например, если мы решили запустить наше приложение через Docker Compose, предварительно собрав его в Docker образ, то передача значений для объявленных нами переменных окружения будет выглядеть следующим образом:
spring_test_app:
image: spring_test_app:latest
build:
context: .
dockerfile: docker/Dockerfile
args:
DOCKER_BUILDKIT: 1
restart: "no"
# задаём конкретные значения тем самым переменным окружения
environment:
POSTGRES_HOST: postgres:5432
POSTGRES_DB_NAME: test_stand_db
POSTGRES_USERNAME: admin
POSTGRES_PASSWORD: admin
ports:
- "8080:8080"
В этом примере переменные из
application.properties
переопределяются через переменные окружения при запуске Docker контейнера.Переопределение свойств напрямую
Но на самом деле, можно обойтись без дополнительных переменных в
application.properties
, переопределив Spring-свойства напрямую.Теперь
application.properties
выглядит следующим образом:
spring.datasource.url=jdbc:postgresql://localhost:5432/local_dev_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=org.postgresql.Driver
А код сервиса нашего приложения в Docker Compose следующим образом:
spring_test_app:
image: spring_test_app:latest
build:
context: .
dockerfile: docker/Dockerfile
args:
DOCKER_BUILDKIT: 1
restart: "no"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres/test_stand_db
SPRING_DATASOURCE_USERNAME: admin
SPRING_DATASOURCE_PASSWORD: admin
ports:
- "8080:8080"
Для
spring.datasource.url
, spring.datasource.username
и spring.datasource.password
будут использованы те значения, которые мы указали в Docker Compose файле. За счёт чего это становится возможным?
Spring Boot использует определенный порядок загрузки свойств приложения, чтобы обеспечить разумное переопределение значений. Переменные окружения загружаются позже и перезаписывают свойства, заданные в
application.properties
. Полный порядок загрузки можно найти в документации.Relaxed Binding в Spring Boot
Кстати, обратите внимание на стиль написания названий свойств. Spring Boot использует концепцию Relaxed Binding, которая позволяет указать название свойства без полного совпадения. Например:
@ConfigurationProperties(prefix = "my.main-project.person")
class MyPersonProperties {
var firstName: String? = null
}
Для этого класса можно использовать следующие стили именования свойств:
-
my.main-project.person.first-name
— Kebab стиль для .properties
/.yaml
файлов-
my.main-project.person.firstName
— CamelCase стиль-
my.main-project.person.first_name
— Underscore стиль-
MY_MAINPROJECT_PERSON_FIRSTNAME
— Uppercase + Underscore стиль для переменных окружения. При использовании Uppercase + Underscore стиля следует учитывать, что многие операционные системы ограничивают имена переменных окружения. Например, в Linux переменные могут содержать только буквы (a
-z
, A
-Z
), цифры (0
-9
) и символ подчеркивания (_
). Подробнее читайте в документации.В приведённом выше примере с Docker Compose файлом мы как раз воспользовались Uppercase + Underscore стилем, чтобы указать значения для нужных нам свойств. Именно такой вариант именования переменных окружения является негласным для Linux.
Ставь 🔥 если знал про это и 🤔 если слышишь впервые)
#SpringBoot #SpringTips