【问题标题】:Spring Boot programmatically restart appSpring Boot 以编程方式重新启动应用程序
【发布时间】:2017-07-13 07:45:06
【问题描述】:

我正在开发一个 Spring Boot 应用程序,我需要在其中编写 Java 代码来关闭应用程序本身(包括其线程),然后重新启动它。我尝试了以下两种方法,第一种是用 Java 发出 Linux 命令,如下所示:

Process p = Runtime.getRuntime().exec("kill -SIGINT " + pid);

其中 pid 是应用程序本身的 pid。这与按"ctrl + c" 的效果相同。但是以这种方式成功关闭了应用程序,我不知道如何重新启动它。我尝试使用相同的方法发出另一个命令(如“mvn spring-boot:run”,这是我启动应用程序的方式),但由于应用程序已经关闭,这不起作用。

其次,我也试过调用AbstractApplicationContext的refresh()方法如下:

AbstractApplicationContext appContext = new AnnotationConfigApplicationContext();
appContext.registerShutdownHook();
appContext.refresh();

但我觉得这种上下文刷新和重启不一样?

那么用 Java 代码重新启动 Spring Boot 应用程序的正确方法是什么?任何帮助表示赞赏,谢谢!

【问题讨论】:

  • 我认为没有正确的方法可以使用 Java 代码重新启动 Spring Boot 应用程序。为什么不使用 shell 脚本。此外,服务器端应用程序的设计方式应允许它们长时间运行。

标签: java spring spring-boot


【解决方案1】:

gstackoverflow 的答案对我不起作用,我的解决方案:

将依赖项添加到 build.gradle

compile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '2.0.0.RELEASE'
compile("org.springframework.boot:spring-boot-starter-actuator")

自动连接的重启端点

@Autowired
private RestartEndpoint restartEndpoint;

将此添加到 application.properties

management.endpoint.restart.enabled = true

然后调用

    Thread restartThread = new Thread(() -> restartEndpoint.restart());
    restartThread.setDaemon(false);
    restartThread.start();

【讨论】:

  • 不需要通过新线程调用方法,因为函数 restart() 已经像你一样为它创建了一个新线程。
【解决方案2】:

您需要将spring-boot-starter-actuatorSpring cloud 依赖添加到您的应用程序,并使用/restart 端点重新启动应用程序。 Here 是文档:

对于 Spring Boot Actuator 应用程序,有一些 其他管理端点:

  • POST 到 /env 以更新环境并重新绑定 @ConfigurationProperties 和日志级别

  • /refresh 用于重新加载引导上下文并刷新 @RefreshScope 豆

  • /restart 用于关闭 ApplicationContext 并重新启动它 (默认禁用)

  • /pause 和 /resume 用于调用生命周期方法(stop() 和 ApplicationContext 上的 start())

完成后,您可以使用REST API 调用重新启动应用程序(通过RestTemplatecurl)。与杀死它并重新运行它相比,这将是重新启动应用程序更清洁的方法。

【讨论】:

  • 谢谢。您能否详细说明如何使用 RestTemplate 向 /restart 发送有效的 POST 请求?我尝试将 postForObject("/restart", null, String.class) 方法与 RestTemplate 一起使用,但得到了“java.lang.IllegalArgumentException: URI is not absolute”异常。我是 Spring Boot 的新手。谢谢。
  • curl -X POST http://localhost:8080/project-code/restartrestTemplate.postForObject("http://localhost:8080/project-code/restart", null, String.class) project-code 依赖于您的配置 server.servlet.context-path=project-code
【解决方案3】:

不要只执行 kill 命令,而是执行一个已经准备好的脚本/程序来杀死调用进程并启动应用程序的新实例。

【讨论】:

    【解决方案4】:

    DevTools 依赖应用程序上下文的关闭挂钩在重新启动期间将其关闭。如果您通过SpringApplication.setRegisterShutdownHook(false) 禁用了关闭挂钩,它将无法正常工作。

    另见:Using Spring Boot

    【讨论】:

      【解决方案5】:

      补充Darshan Mehta答案:

      就我而言,我是这样做的:

      1.添加依赖:

      compile("org.springframework.boot:spring-boot-starter-actuator")
      compile("org.springframework.cloud:spring-cloud-starter:1.2.4.RELEASE")
      

      2.autowired restartEndpoint:

      import org.springframework.cloud.context.restart.RestartEndpoint;
      ....
      @Autowired
      private RestartEndpoint restartEndpoint;
      

      3.并调用:

      Thread thread = new Thread(new Runnable() {
          @Override
          public void run() {
              restartEndpoint.invoke();
          }
      });
      thread.setDaemon(false);
      thread.start();
      

      我需要新线程,因为 spring mvc 为每个请求创建守护线程

      【讨论】:

        【解决方案6】:

        我们可以像这样使用 Spring Devtools 的 Restarter:

        org.springframework.boot.devtools.restart.Restarter.getInstance().restart()
        

        【讨论】:

          猜你喜欢
          • 2020-12-06
          • 2017-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-26
          • 2016-09-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多