Конфигурация и сборка Spring-приложения
Собранный artifact должен быть одинаковым для окружений. Меняются внешние properties, secrets и infrastructure endpoints, а не исходники и не отдельная “production-сборка”.
Конфигурация
Spring Boot собирает properties из нескольких источников с определённым приоритетом: packaged config, profile-specific config, внешние файлы, environment variables, system/command-line properties. При конфликте побеждает источник с более высоким приоритетом.
app:
batch-size: 100
request-timeout: 2s
spring:
datasource:
url: ${DB_URL}
username: ${DB_USER}
password: ${DB_PASSWORD}Environment variable подставляет secret в runtime. В repository храню только имена и безопасные defaults, не реальные credentials.
Типизированные properties
@ConfigurationProperties(prefix = "app")
@Validated
public record AppProperties(
@Min(1) int batchSize,
@NotNull Duration requestTimeout
) {}Типизированная конфигурация даёт binding, validation и единое место контракта. Строковый environment.getProperty оставляю для действительно динамического lookup, а не основной модели настроек.
Profiles
Profile переключает согласованный набор beans/properties, но не должен разрастаться в условное программирование на каждое окружение.
java -jar app.jar --spring.profiles.active=demoИмена и endpoints конкретного окружения лучше передавать значениями. Если prod profile меняет бизнес-логику, tests легко проверят не тот вариант.
Сборка
./mvnw clean verify
./mvnw package
java -jar target/app.jarSpring Boot plugin может упаковать executable JAR с dependencies и launcher. Обычный Maven JAR и bootable JAR имеют разную внутреннюю layout; это проверяю через jar tf.
Диагностика
При ошибке binding читаю полный property path, expected type и источник значения. Для production Actuator/config endpoints могут раскрывать secrets, поэтому доступ и sanitization обязательны.
Для Kafka я вынес bootstrap servers во внешнюю конфигурацию, чтобы один artifact работал в разных окружениях. См. Кейс конфигурация Kafka в разных окружениях.
Типичные сбои
- Закоммитить
application-prod.ymlс паролем. - Переопределить property command-line аргументом и забыть об этом.
- Использовать profile для каждого host.
- Собрать новый JAR для изменения endpoint.
- Не валидировать обязательное значение и упасть при первом request.
- Запустить Maven и IDE на разных JDK.
Вопросы для собеседования
Зачем externalized configuration? Один проверенный artifact запускается в разных окружениях без пересборки.
Чем @ConfigurationProperties лучше набора @Value? Группирует контракт, поддерживает type-safe binding и validation.
Где хранить secrets? Во внешнем secret store/environment с контролем доступа, не в repository и artifact.
Зачем profiles? Включать согласованный вариант beans/config, когда обычных значений недостаточно.
Что делает mvn verify? Выполняет lifecycle до проверки package, включая связанные tests/checks проекта.