Spring Tips: Переопределение свойств через переменные окружения



Часто в файле 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