Java 如何防止 Spring Boot 守护进程/服务器应用程序立即关闭/关闭?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28017784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 05:27:39  来源:igfitidea点击:

How to prevent Spring Boot daemon/server application from closing/shutting down immediately?

javaspringspring-bootdaemonserver

提问by Hendy Irawan

My Spring Boot application is not a web server, but it's a server using custom protocol (using Camel in this case).

我的 Spring Boot 应用程序不是 Web 服务器,而是使用自定义协议的服务器(在本例中使用 Camel)。

But Spring Boot immediately stops (gracefully) after started. How do I prevent this?

但是 Spring Boot 在启动后立即停止(优雅地)。我如何防止这种情况?

I'd like the app to stop if Ctrl+C or programmatically.

如果 Ctrl+C 或以编程方式,我希望应用程序停止。

@CompileStatic
@Configuration
class CamelConfig {

    @Bean
    CamelContextFactoryBean camelContext() {
        final camelContextFactory = new CamelContextFactoryBean()
        camelContextFactory.id = 'camelContext'
        camelContextFactory
    }

}

采纳答案by jmkgreen

As of Apache Camel 2.17 there is a cleaner answer. To quote http://camel.apache.org/spring-boot.html:

从 Apache Camel 2.17 开始,有一个更清晰的答案。引用http://camel.apache.org/spring-boot.html

To keep the main thread blocked so that Camel stays up, either include the spring-boot-starter-web dependency, or add camel.springboot.main-run-controller=true to your application.properties or application.yml file.

要保持主线程阻塞以便 Camel 保持运行,请包含 spring-boot-starter-web 依赖项,或将 camel.springboot.main-run-controller=true 添加到您的 application.properties 或 application.yml 文件中。

You will want the following dependency too:

您还需要以下依赖项:

<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring-boot-starter</artifactId> <version>2.17.0</version> </dependency>

<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-spring-boot-starter</artifactId> <version>2.17.0</version> </dependency>

Clearly replace <version>2.17.0</version>or use the camel BOM to import dependency-management information for consistency.

明确替换<version>2.17.0</version>或使用骆驼 BOM 导入依赖项管理信息以保持一致性。

回答by mariubog

for springboot app to run continously it has to be run in a container, otherwise it is just like any java app all threads are done it finishes, you can add

为了使 springboot 应用程序连续运行,它必须在容器中运行,否则就像任何 Java 应用程序一样,所有线程都完成了,您可以添加

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

and it will turn it into webapp, if not you are responsible keeping it alive in your implementation

它将把它变成 webapp,如果不是,你有责任在你的实现中保持它的活力

回答by Hendy Irawan

I found the solution, using org.springframework.boot.CommandLineRunner+ Thread.currentThread().join(), e.g.: (note: code below is in Groovy, not Java)

我找到了解决方案,使用org.springframework.boot.CommandLineRunner+ Thread.currentThread().join(),例如:(注意:下面的代码是在 Groovy 中,而不是在 Java 中)

package id.ac.itb.lumen.social

import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication

@SpringBootApplication
class LumenSocialApplication implements CommandLineRunner {

    private static final log = LoggerFactory.getLogger(LumenSocialApplication.class)

    static void main(String[] args) {
        SpringApplication.run LumenSocialApplication, args
    }

    @Override
    void run(String... args) throws Exception {
        log.info('Joining thread, you can press Ctrl+C to shutdown application')
        Thread.currentThread().join()
    }
}

回答by Anatoly

Spring Boot leaves the task of running the application to the protocol around which the application is implemented. See, for example, this guide:

Spring Boot 将运行应用程序的任务留给了实现应用程序的协议。例如,请参阅本指南

Also required are some housekeeping objects like a CountDownLatchto keep the main thread alive...

还需要一些内务处理对象,例如 aCountDownLatch以保持主线程处于活动状态...

So the way of running a Camel service, for example, would to be to run Camel as a standalone applicationfrom your main Spring Boot application class.

因此,例如,运行 Camel 服务的方法是将 Camel 作为独立应用程序从您的主 Spring Boot 应用程序类中运行。

回答by Willy du Preez

An example implementation using a CountDownLatch:

使用 CountDownLatch 的示例实现:

@Bean
public CountDownLatch closeLatch() {
    return new CountDownLatch(1);
}

public static void main(String... args) throws InterruptedException {
    ApplicationContext ctx = SpringApplication.run(MyApp.class, args);  

    final CountDownLatch closeLatch = ctx.getBean(CountDownLatch.class);
    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            closeLatch.countDown();
        }
    });
    closeLatch.await();
}

Now to stop your application, you can look up the process ID and issue a kill command from the console:

现在要停止您的应用程序,您可以查找进程 ID 并从控制台发出 kill 命令:

kill <PID>

回答by JARC

To keep the java process alive when not deploying a web application set the webEnvironment property to false like so:

要在不部署 Web 应用程序时保持 Java 进程处于活动状态,请将 webEnvironment 属性设置为 false,如下所示:

 SpringApplication sa = new SpringApplication();
 sa.setWebEnvironment(false); //important
 ApplicationContext ctx = sa.run(ApplicationMain.class, args);

回答by Cheng

My project is NON WEB Spirng Boot. My elegant solution is create a daemon thread by CommandLineRunner. Then, Application do not shutdown immediately.

我的项目是 NON WEB Spirng Boot。我的优雅解决方案是通过 CommandLineRunner 创建一个守护线程。然后,应用程序不会立即关闭。

 @Bean
    public CommandLineRunner deQueue() {
        return args -> {
            Thread daemonThread;
            consumer.connect(3);
            daemonThread = new Thread(() -> {
                try {
                    consumer.work();
                } catch (InterruptedException e) {
                    logger.info("daemon thread is interrupted", e);
                }
            });
            daemonThread.setDaemon(true);
            daemonThread.start();
        };
    }

回答by izee

All threads are completed, the program will close automatically. So, register an empty task with @Scheduledwill create a loop thread to prevent shutdown.

所有线程完成后,程序将自动关闭。因此,注册一个空任务@Scheduled将创建一个循环线程以防止关闭。

回答by Venkat

This is now made even simpler.

这现在变得更加简单。

Just add camel.springboot.main-run-controller=trueto your application.properties

只需添加camel.springboot.main-run-controller=true到您的 application.properties