[英]How to conditionally make a Spring Boot application terminate at startup based on a property
我想實現以下用例 - 只有在application.yaml
中設置了某個屬性時,我的 Spring Boot 應用程序才應該啟動:
myapp:
active: true
如果未設置該屬性,則上下文初始化應失敗並顯示缺少該屬性的消息。
我在這個主題中找到了如何實現它: Spring Boot - 如果未設置屬性,則檢測並終止? 但我不能遵循這種方法的問題是,在加載檢查此屬性的 bean 之前,上下文初始化可能會失敗。
例如,如果某個其他 bean 由於缺少另一個屬性而無法加載,則上下文初始化將在此時失敗,並且我的用於檢查所需屬性的 bean 將不會被加載。 這對我來說myapp.active
因為我希望在加載任何其他 bean 之前首先檢查myapp.active
屬性。
我想要這樣的原因是在運行應用程序時應該設置某個配置文件 - application-[profile].yaml
包含myapp.active: true
和加載上下文所需的其他一些強制性屬性.
我希望我的應用程序總是失敗,因為 myapp.active 不是真的,這樣我就可以輸出一條有意義的消息,告訴配置文件丟失,並且應用程序必須使用其中一個配置文件(來自給定的配置文件列表)運行。 一些不是開發人員的人正在運行該應用程序,所以我希望他們知道該應用程序沒有運行的原因,否則他們會認為該應用程序中存在一些錯誤。
我怎樣才能做到這一點? 是否有可能在加載 bean 之前以某種方式讀取屬性? 我想避免在所有 bean 上設置@DependsOn
(或通過BeanPostProcesser
做同樣的事情)並且正在尋找更優雅的解決方案。
如果您使用財產條件,則該應用程序將無法啟動。 夠快嗎?
@SpringBootApplication
@ConditionalOnProperty(name = "myapp.active")
public class FastFailWhenPropertyNotPresentApplication {
public static void main(String[] args) {
SpringApplication.run(FastFailWhenPropertyNotPresentApplication.class, args);
}
}
基本上@SpringBootApplication
只是一個@Configuration
類。
您有一個matchIfMissing
選項,可用於指定如果未設置屬性則條件是否匹配。 默認為false。
編輯:
更好的解決方案是通過將@ConfigurationProperties
與@Validated
結合使用來配置屬性,因此可以使用javax.validation.constraints批注。
package stackoverflow.demo;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
@Component
@ConfigurationProperties(prefix = "myapp")
@Validated
public class MyAppProperties {
@AssertTrue
@NotNull
private Boolean active;
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
}
注意:您可以省略@ConditionalOnProperty(name = "myapp.active")
將@AssertTrue
與@NotNull
結合使用,因為@AssertTrue
認為空元素有效。
並且spring-boot會免費生成一個不錯的錯誤消息:
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'myapp' to stackoverflow.demo.MyAppProperties failed:
Property: myapp.active
Value: false
Origin: class path resource [application.properties]:1:16
Reason: must be true
Action:
Update your application's configuration
編輯 (更新問題后)
更快的方法: 您的應用程序將無法啟動,也不會加載應用程序上下文
package stackoverflow.demo;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.ClassPathResource;
@SpringBootApplication
public class FastFailWhenPropertyNotPresentApplication {
static Boolean active;
static {
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yaml"));
active = (Boolean) yaml.getObject().getOrDefault("myapp.active", false);
}
public static void main(String[] args) {
if (!active) {
System.err.println("your fail message");
} else {
SpringApplication.run(FastFailWhenPropertyNotPresentApplication.class, args);
}
}
}
另一個最適合您需求的解決方案...
通過監聽ApplicationEnvironmentPreparedEvent
在{@link SpringApplication}啟動時發布的事件,並且* {@link Environment}首先可用於檢查和修改。 *
注意:您不能使用@EventListener
,但是已經將偵聽器添加到SpringApplication
package stackoverflow.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
@SpringBootApplication
public class FastFailWhenPropertyNotPresentApplication {
static class EnvironmentPrepared implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
Boolean active = event.getEnvironment().getProperty("myapp.active",Boolean.class,Boolean.FALSE);
if(!active) {
throw new RuntimeException("APPLICATION FAILED TO START: ACTIVE SHOULD BE TRUE ");
}
}
};
public static void main(String[] args) throws Exception {
SpringApplication springApplication = new SpringApplication(FastFailWhenPropertyNotPresentApplication.class);
springApplication.addListeners(new FastFailWhenPropertyNotPresentApplication.EnvironmentPrepared());
springApplication.run(args);
}
}
一種選擇是創建一個 bean 來檢查屬性是否存在,如果未設置屬性,則在 bean 創建期間拋出異常。
@Component
public static EnsureApplicationActive {
@Value("${myapp.active}")
private Boolean active;
@PostConstruct
public void ensureApplicationActive() {
if (!Boolean.TRUE.equals(active)) {
throw new IllegalStateException("TODO: Meaningful message goes here");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.