关闭 Spring Boot 应用程序

概述

管理 Spring Boot 应用程序的生命周期对于生产就绪系统非常重要。Spring 容器在 ApplicationContext 的帮助下处理所有 Bean 的创建、初始化和销毁​​。 

本教程的重点是生命周期的销毁阶段。更具体地说,我们将研究关闭 Spring Boot 应用程序的不同方法。

要了解有关如何使用 Spring Boot 设置项目的更多信息,请查看Spring Boot 入门文章,或查看Spring Boot 配置

1.关机端点

默认情况下,除了/shutdown之外的所有端点都在 Spring Boot 应用程序中启用, 它是执行器端点的一部分。

这是设置这些的 Maven 依赖项:

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

如果我们还想设置安全支持,我们需要:

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

最后,我们将在application.properties文件中启用关闭端点:

management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
endpoints.shutdown.enabled=true

请注意,我们还必须公开我们想要使用的任何执行器端点。在上面的示例中,我们公开了所有执行器端点,其中包括/shutdown端点。

要关闭 Spring Boot 应用程序,我们只需像这样调用 POST 方法

curl -X POST localhost:port/actuator/shutdown

在此调用中,端口代表执行器端口。

2.关闭应用上下文

我们也可以直接使用应用程序上下文调用close()方法。

让我们从创建上下文并关闭它的示例开始:

ConfigurableApplicationContext ctx = new 
  SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run();
System.out.println("Spring Boot application started");
ctx.getBean(TerminateBean.class);
ctx.close();

这会销毁所有 bean,释放锁,然后关闭 bean 工厂为了验证应用程序关闭,我们将使用带有@PreDestroy注释的 Spring 标准生命周期回调:

public class TerminateBean {

    @PreDestroy
    public void onDestroy() throws Exception {
        System.out.println("Spring Container is destroyed!");
    }
}

我们还必须添加一个这种类型的 bean:

@Configuration
public class ShutdownConfig {

    @Bean
    public TerminateBean getTerminateBean() {
        return new TerminateBean();
    }
}

这是运行此示例后的输出:

Spring Boot application started
Closing AnnotationConfigApplicationContext@39b43d60
DefaultLifecycleProcessor - Stopping beans in phase 0
Unregistering JMX-exposed beans on shutdown
Spring Container is destroyed!

重要的是要记住,在关闭应用程序上下文时,父上下文不会因单独的生命周期而受到影响

2.1. 关闭当前应用上下文

在上面的示例中,我们创建了一个子应用程序上下文,然后使用close()方法将其销毁。

如果我们想关闭当前上下文,一种解决方案是简单地调用执行器/shutdown端点。

但是,我们也可以创建自己的自定义端点:

@RestController
public class ShutdownController implements ApplicationContextAware {
    
    private ApplicationContext context;
    
    @PostMapping("/shutdownContext")
    public void shutdownContext() {
        ((ConfigurableApplicationContext) context).close();
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.context = ctx;
        
    }
}

在这里,我们添加了一个控制器,它实现了ApplicationContextAware接口并重写了 setter 方法来获取当前的应用程序上下文。然后,在映射方法中,我们只需调用close()方法。

然后我们可以调用我们的新端点来关闭当前上下文:

curl -X POST localhost:port/shutdownContext

当然,如果我们在实际应用程序中添加这样的端点,我们也会希望保护它。

3.退出SpringApplication

SpringApplication向 JVM注册一个关闭挂钩以确保应用程序正确退出。

Bean 可以实现ExitCodeGenerator接口以返回特定的错误代码:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE).run();

int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
        // return the error code
        return 0;
    }
});

System.exit(exitCode);

下面是与 Java 8 lambda 应用程序相同的代码:

SpringApplication.exit(ctx, () -> 0);

调用System.exit(exitCode)后,程序以 0 返回代码终止

Process finished with exit code 0

4.杀死应用程序进程

最后,我们还可以使用 bash 脚本从应用程序外部关闭 Spring Boot 应用程序。我们对此选项的第一步是让应用程序上下文将其 PID 写入文件:

SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class)
  .web(WebApplicationType.NONE);
app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid"));
app.run();

接下来,我们将创建一个包含以下内容的shutdown.bat文件:

kill $(cat ./bin/shutdown.pid)

shutdown.bat的执行从shutdown.pid文件中提取进程 ID ,并使用kill命令终止 Boot 应用程序。

结论

在这篇简短的文章中,我们介绍了一些可用于关闭正在运行的 Spring Boot 应用程序的简单方法。

虽然选择合适的方法取决于开发人员,但所有这些方法都应该按设计和目的使用。

例如,当我们需要将错误代码传递给另一个环境(比如 JVM)以进行进一步操作时,首选.exit() 。使用应用程序PID提供了更大的灵活性,因为我们还可以使用 bash 脚本启动或重新启动应用程序。

最后,/shutdown 在这里可以通过 HTTP 从外部终止应用程序。对于所有其他情况,.close()将完美运行。

与往常一样,本文的完整代码可在GitHub 项目上获得。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值