【问题标题】:How to shut down a Spring Boot command-line application如何关闭 Spring Boot 命令行应用程序
【发布时间】:2014-12-07 09:17:18
【问题描述】:

我正在使用 Spring Boot 构建一个命令行 java 应用程序以使其快速运行。

应用程序加载不同类型的文件(例如 CSV)并将它们加载到 Cassandra 数据库中。它不使用任何 Web 组件,它不是 Web 应用程序。

我遇到的问题是在工作完成后停止应用程序。我正在使用带有@Component 的 Spring CommandLineRunner 接口来运行任务,如下所示,但是当工作完成时,应用程序并没有停止,由于某种原因它一直在运行,我找不到停止它的方法.

@Component
public class OneTimeRunner implements CommandLineRunner {

    @Autowired
    private CassandraOperations cassandra;

    @Autowired
    private ConfigurableApplicationContext context;

    @Override
    public void run(String... args) throws Exception {
        // do some work here and then quit
        context.close();
    }
}

更新:问题似乎是spring-cassandra,因为项目中没有其他内容。有谁知道为什么它让线程在后台运行以防止应用程序停止?

更新:更新到最新的 Spring Boot 版本后问题消失了。

【问题讨论】:

  • 有什么解决办法吗?它发生在普通的弹簧靴上(没有 cassandra)
  • @ACV 不,我只是忍受它。我了解到一些弹簧模块会产生自己的线程,例如Cassandra 有一个用于连接的线程池,或者当您使用侦听器容器时使用 RabbitMQ。在您调用 context.close() 停止应用程序后,这些需要一些时间才能关闭。

标签: java spring spring-boot spring-data-cassandra


【解决方案1】:

答案取决于仍在工作的是什么。您可能可以通过线程转储找到答案(例如使用 jstack)。但如果它是由 Spring 启动的任何东西,您应该能够在您的 main() 方法(或 CommandLineRunner)中使用 ConfigurableApplicationContext.close() 来停止应用程序。

【讨论】:

  • 好的,我用断点调试了应用程序,有 17 个:Thread[New I/O worker#(1-17)]。我将不得不对此进行调查。关于ConfigurableApplicationContext.close(),停止应用大约需要30秒,正常吗??
  • 它必须等待任何工作来释放线程。对我来说听起来像是超时。
  • 没错,我怀疑 Spring Cassandra 出于某种原因保持这些线程运行。
  • 是根据当前标准使用 ConfigurableApplicationContext.close() 关闭应用程序的好方法吗?
  • 不确定你的意思。这是以编程方式关闭应用程序上下文的唯一方法。
【解决方案2】:

我找到了解决方案。你可以使用这个:

public static void main(String[] args) {
    SpringApplication.run(RsscollectorApplication.class, args).close();
    System.out.println("done");
}

只需在运行时使用.close()

【讨论】:

  • 好吧....如果您查看问题上的代码,我就是这样做的。 SpringApplication.run(Main.class, args) 返回一个 ConfigurableApplicationContext 您可以存储或稍后像我一样存储 @Autowire。我在这个问题上遇到的问题是,在上下文中调用close() 后,应用程序会停止一段时间。
  • 好的,清楚。可能是文件需要时间刷新到数据库中
【解决方案3】:

我在当前项目(spring boot 应用程序)中也遇到了这个问题。 我的解决方案是:

// releasing all resources
((ConfigurableApplicationContext) ctx).close();
// Close application
System.exit(0);

context.close() 不要停止我们的控制台应用程序,它只是在释放资源。

【讨论】:

    【解决方案4】:

    使用org.springframework.boot.SpringApplication#exit。例如

    @Component
    public class OneTimeRunner implements CommandLineRunner {
    
        @Autowired
        private ConfigurableApplicationContext context;
    
        @Override
        public void run(String... args) throws Exception { 
            SpringApplication.exit(context);
        }
    }
    

    【讨论】:

      【解决方案5】:

      这是@EliuX 答案与@Quan Vo 的组合。谢谢两位!

      主要的不同是我将 SpringApplication.exit(context) 响应代码作为参数传递给 System.exit(),因此如果关闭 Spring 上下文时出现错误,您会注意到。

      SpringApplication.exit() 将关闭 Spring 上下文。

      System.exit() 将关闭应用程序。

      @Component
      public class OneTimeRunner implements CommandLineRunner {
      
          @Autowired
          private ConfigurableApplicationContext context;
      
          @Override
          public void run(String... args) throws Exception { 
             System.exit(SpringApplication.exit(context));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-05-29
        • 2017-01-16
        • 2019-08-27
        • 2017-03-06
        • 2018-01-18
        • 2020-12-13
        • 2015-10-27
        • 2016-06-09
        相关资源
        最近更新 更多