Как сделаешь, чтобы стартер не запустился при отсутствии логина, пароля и URL в application.properties
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Предотвращение запуска приложения при отсутствии обязательных параметров
Это важная задача валидации конфигурации на этапе старта приложения. Есть несколько способов решения в Spring Boot.
Способ 1: @ConfigurationProperties с валидацией (РЕКОМЕНДУЕТСЯ)
Это самый современный и чистый способ. Используем @ConfigurationProperties с @Validated и JSR-303 аннотациями:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Component
@ConfigurationProperties(prefix = "app.database")
public class DatabaseProperties {
@NotBlank(message = "Database URL must not be blank")
private String url;
@NotBlank(message = "Database username must not be blank")
private String login;
@NotBlank(message = "Database password must not be blank")
private String password;
public DatabaseProperties() {}
// Getters
public String getUrl() { return url; }
public String getLogin() { return login; }
public String getPassword() { return password; }
// Setters
public void setUrl(String url) { this.url = url; }
public void setLogin(String login) { this.login = login; }
public void setPassword(String password) { this.password = password; }
}
В application.properties:
app.database.url=jdbc:mysql://localhost:3306/mydb
app.database.login=root
app.database.password=secret
Почему это работает: Spring автоматически валидирует properties при создании бина. Если какое-то поле не заполнено или не соответствует условиям, приложение не запустится с ошибкой BindValidationException.
Способ 2: Проверка через @Bean с @Conditional
Для более сложной логики можно использовать условное создание beans:
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DatabaseConfig {
@Bean
@ConditionalOnProperty(
name = "app.database.url",
name = "app.database.login",
name = "app.database.password",
havingValue = "true" // все три должны быть присутствуют
)
public DataSource dataSource(DatabaseProperties props) {
// Создание DataSource только если все параметры есть
return new DataSourceBuilder()
.url(props.getUrl())
.username(props.getLogin())
.password(props.getPassword())
.build();
}
}
Способ 3: ApplicationListener для проверки при старте
Проверка конфигурации при событии ContextRefreshedEvent:
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
@Component
public class ConfigurationValidator implements ApplicationListener<ContextRefreshedEvent> {
private final Environment env;
public ConfigurationValidator(Environment env) {
this.env = env;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
validateDatabaseConfiguration();
}
private void validateDatabaseConfiguration() {
String url = env.getProperty("app.database.url");
String login = env.getProperty("app.database.login");
String password = env.getProperty("app.database.password");
if (url == null || url.isBlank() ||
login == null || login.isBlank() ||
password == null || password.isBlank()) {
throw new IllegalStateException(
"Missing required database configuration: " +
"app.database.url, app.database.login, app.database.password"
);
}
}
}
Способ 4: PostConstruct проверка в компоненте
Проверка сразу после создания бина:
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class DatabaseService {
@Value("${app.database.url:}")
private String url;
@Value("${app.database.login:}")
private String login;
@Value("${app.database.password:}")
private String password;
@PostConstruct
public void validateConfiguration() {
if (url.isBlank() || login.isBlank() || password.isBlank()) {
throw new IllegalArgumentException(
"Database configuration is incomplete. Required: " +
"app.database.url, app.database.login, app.database.password"
);
}
}
}
Способ 5: Custom Starter с автоконфигурацией
Для переиспользуемого решения создайте автоконфигурацию:
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@AutoConfiguration
@EnableConfigurationProperties(DatabaseProperties.class)
public class DatabaseAutoConfiguration {
@Bean
public DatabaseConfigurationValidator databaseValidator(DatabaseProperties props) {
return new DatabaseConfigurationValidator(props);
}
}
// Сам валидатор
@Component
public class DatabaseConfigurationValidator {
public DatabaseConfigurationValidator(DatabaseProperties props) {
validateProperties(props);
}
private void validateProperties(DatabaseProperties props) {
if (props.getUrl() == null || props.getUrl().isBlank()) {
throw new IllegalStateException("app.database.url is required");
}
if (props.getLogin() == null || props.getLogin().isBlank()) {
throw new IllegalStateException("app.database.login is required");
}
if (props.getPassword() == null || props.getPassword().isBlank()) {
throw new IllegalStateException("app.database.password is required");
}
}
}
Сравнение подходов
| Подход | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| @ConfigurationProperties | Стандартно, встроено в Spring, типизировано | Требует JSR-303 зависимость | ВСЕГДА - это best practice |
| @ConditionalOnProperty | Гибко, можно применять к beans | Сложнее для отладки | Для условного создания beans |
| ApplicationListener | Полный контроль, логирование | Verbose код | Когда нужна сложная логика |
| @PostConstruct | Просто, локально для сервиса | Нет早预 проверки | Для простых случаев |
| Custom Starter | Переиспользуемо, чистое разделение | Оверхед для маленьких проектов | Для библиотек и starter'ов |
Пример полного решения (РЕКОМЕНДУЕТСЯ)
// 1. Properties класс
@Component
@ConfigurationProperties(prefix = "app.database")
@Validated
public class DatabaseProperties {
@NotBlank private String url;
@NotBlank private String login;
@NotBlank private String password;
// getters/setters
}
// 2. application.properties
app.database.url=jdbc:mysql://localhost:3306/mydb
app.database.login=root
app.database.password=secret
// 3. Конфиг для DataSource
@Configuration
public class DatabaseConfiguration {
@Bean
public DataSource dataSource(DatabaseProperties props) {
return DataSourceBuilder.create()
.url(props.getUrl())
.username(props.getLogin())
.password(props.getPassword())
.build();
}
}
При отсутствии любого из параметров приложение выдаст:
Parameter 0 of constructor in ... required a bean of type ... that could not be found
Bound validation error in ...
И приложение не запустится, что именно требуется по задаче.