当前位置: 首页 > 知识库问答 >
问题:

如何有条件地使spring启动应用程序在启动时终止

舒赞
2023-03-14

我想实现下面的用例——我的Spring Boot应用程序应该只在应用程序中有某个属性时启动。yaml设置为:

myapp
    active: true

如果未设置该属性,则上下文初始化将失败,并显示一条消息,表明该属性丢失。

我在这个主题中找到了如何实现它:Spring启动-检测和终止,如果属性没有设置?但是我不能遵循这种方法的问题是,在加载检查此属性的bean之前,上下文初始化可能会失败。

例如,如果其他bean由于缺少另一个属性而无法加载,那么上下文初始化将在该点失败,并且检查所需属性的Mybean将不会加载。这对我来说不合适,因为我想要myapp。在加载任何其他bean之前,首先检查活动属性。

我之所以想这样做,是因为在运行应用程序时应该设置特定的配置文件-应用程序-[profile]。yaml包含“myapp.active:true”和加载上下文所需的一些其他必需属性。

我希望我的应用程序总是因为myapp而失败。active not true,以便我可以输出一条有意义的消息,告知配置文件丢失,并且应用程序必须使用其中一个配置文件(来自给定的配置文件列表)运行。一些不是开发者的家伙正在运行这个应用程序,所以我想让他们知道为什么这个应用程序没有运行,否则他们会认为这个应用程序中有一些bug。

我怎样才能做到这一点?是否有可能在加载bean之前读取属性?我希望避免在所有bean上设置@DependsOn(或者通过BeanPostProcessor进行相同的设置),我正在寻找一个更优雅的解决方案。

共有1个答案

宣滨海
2023-03-14

如果使用属性条件,应用程序将无法启动。够快吗?

 @SpringBootApplication
 @ConditionalOnProperty(name = "myapp.active")
 public class FastFailWhenPropertyNotPresentApplication {

     public static void main(String[] args) {
            SpringApplication.run(FastFailWhenPropertyNotPresentApplication.class, args);
    }

}

基本上,@springbootplication只是一个@配置类。

您有一个选项matchIfMissing,可用于指定如果未设置属性,条件是否应匹配。默认为false。

编辑:

更好的解决方案是通过@ConfigurationProperties@Validated组合来配置属性,这样您就可以使用javax了。验证。约束和注释。

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;
  }

}

注意:您可以省略@条件属性(name="myapp.active")

@AssertTrue@NotNull结合使用,因为@AssertTrue认为null元素有效。

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);
  }

}
 类似资料:
  • 我有一个Spring Boot应用程序,它有一些外部依赖(例如,项目之外的文件,需要存在,以便应用程序正确启动)。 和一系列其他例外。有没有一种方法可以恰当地做到这一点?

  • 问题内容: 我尝试使用范围类型APPLICATION和带有@ Create,@ Beg的方法来注释类,但这似乎不起作用。 我想要的是在应用程序启动时立即启动无限循环。 问题答案: 如果希望在初始化后立即执行方法,则可以使用以下注释:

  • 我有一份Java申请。 应用程序有一个决定应用程序是否在启动时启动的设置。 目前,我通过在StartUp items文件夹中放置/删除快捷方式实现了这一点。 然而,我想知道是否有更好的方法来处理这种行为。 编辑 是的,是视窗。抱歉之前没有清除。 应用程序有一个UI,用户可以在其中触发操作,并且应用程序在运行时定期在后台运行一些任务。 @Peter,如何使用应用程序中的代码更改注册表?这种方法是否与

  • 我想对Spring数据使用ElasticSearch。我使用的是Spring 5、Spring Boot 2和ElasticSearch 7.4。Docker compose: 马文: 存储库: 配置: 和错误时启动应用程序: 引起:java.lang.NoSuchMEDError:org.springframework.http.HttpHeaders.(Lorg/springframe/uti

  • 问题内容: 我有一个Java应用程序。 该应用程序具有一个设置,该设置决定该应用程序是否在启动时启动。 目前,我可以通过在“启动项目”文件夹中放置/删除快捷方式来实现此目的。 但是,我想知道是否有更好的方法来处理此行为。 编辑 是的,它是Windows。抱歉,之前没有清除该内容。 该应用程序具有一个用户可以在其中触发动作的UI,并且该应用程序在运行时会定期在后台运行一些任务。 @Peter,如何在

  • 我正在尝试使用简单的spring启动应用程序。我在ApplicationContext上启动应用程序时遇到问题。 2017-04-26 11:17:31.101警告14528---[main]s.c.a.AnnotationConfigApplicationContext:上下文初始化期间遇到异常-取消刷新尝试:org。springframework。豆。工厂未满足的PendencyExcepti