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

nsc4cvqm  于 2022-10-30  发布在  Spring
关注(0)|答案(9)|浏览(233)

我的Sping Boot 应用程序不是Web服务器,但它是使用自定义协议的服务器(在本例中使用Camel)。
但是Sping Boot 在启动后会立即停止(正常)。如何防止这种情况?
我希望应用程序停止,如果Ctrl+C或编程。

@CompileStatic
@Configuration
class CamelConfig {

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

}
zxlwwiss

zxlwwiss1#

我找到了解决方案,使用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()
    }
}
zdwk9cvp

zdwk9cvp2#

从Apache Camel 2.17开始,有一个更清晰的答案。引用http://camel.apache.org/spring-boot.html
要保持主线程阻塞以便Camel保持运行,可以包含spring-boot-starter-web依赖项,或者将camel.springboot.main-run-controller=true添加到application.properties或application.yml文件中。
您还需要以下依赖项:
<version>2.17.0</version>
明确替换<version>2.17.0</version>或使用camel BOM导入相关性管理信息以实现一致性。

vdzxcuhz

vdzxcuhz3#

一个使用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();
}

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

kill <PID>
fnx2tebb

fnx2tebb4#

Sping Boot 将运行应用程序的任务留给了实现应用程序所依据的协议。
还需要一些内务处理对象,如CountDownLatch,以保持主线程处于活动状态...
例如,运行Camel服务的方法是从您的主Sping Boot 应用程序类中将Camel作为standalone application运行。

v6ylcynt

v6ylcynt5#

现在这变得更简单了。
只需将camel.springboot.main-run-controller=true添加到您的application.properties

70gysomp

70gysomp6#

所有的线程都完成了,程序会自动关闭。所以,用@Scheduled注册一个空任务会创建一个循环线程来防止关闭。
文件应用程序.yml

spring:
  main:
    web-application-type: none

文件DemoApplication.java

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

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

}

文件KeepAlive.java

@Component
public class KeepAlive {

   private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
   private static final SimpleDateFormat dateFormat =  new SimpleDateFormat("HH:mm:ss");

   @Scheduled(fixedRate = 1 * 1000 * 60) // 1 minute
   public void reportCurrentTime() {
       log.info("Keepalive at time {}", dateFormat.format(new Date()));
   }
}
rjee0c15

rjee0c157#

我的项目是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();
        };
    }
ruarlubt

ruarlubt8#

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

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

x0fgdtte9#

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

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

它会将其转换为webapp,否则您有责任使其在实现中保持活动状态

相关问题