TODO 逻辑有问题,待修复
原因:
在项目实际生产环境中,有时需要 重启 springboot 接口,此时 如果可以一键重启,那岂不是很方便。
描述:
重启Spring Boot应用程序的关键步骤是对主类中SpringApplication.run(Application.class,args);方法返回值的处理。通过查看官方文档可以看到,ConfigurableApplicationContext接口类中定义了一个close()方法,可以用来关闭当前应用的上下文。在应用程序的main()方法中,我们可以使用一个临时变量来存放SpringApplication.run()返回的ConfigurableApplicationContext对象,当我们完成对Spring Boot应用程序中属性的设置后,调用ConfigurableApplicationContext的#close()方法,最后再调用SpringApplication.run()方法重新给ConfigurableApplicationContext对象进行赋值已达到重启的效果。
简而言之,先关闭 application 程序,在启动 application。
主要代码:
重启方法
ExecutorService threadPool = new ThreadPoolExecutor(1, 1, 0,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardOldestPolicy());
threadPool.execute(() -> {
ExampleRestartApplication.context.close();
ExampleRestartApplication.context = SpringApplication.run(ExampleRestartApplication.class,
ExampleRestartApplication.args);
});
threadPool.shutdown();
main 方法
@SpringBootApplication
public class ExampleRestartApplication {
public static String[] args;
public static ConfigurableApplicationContext context;
public static void main(String[] args) {
ExampleRestartApplication.args = args;
ExampleRestartApplication.context = SpringApplication.run(ExampleRestartApplication.class, args);
}
}
ok,没问题,此时,我们可以加入一个 spring.application.name 进行测试,再重启过程中 去修改 spring.application.name 对应值,在进行测试,以证明重启ok。
重启api接口
package cn.wbw.httpbootrest.restart;
import cn.wbw.httpbootrest.ExampleRestartApplication;
import cn.wbw.httpbootrest.util.PropUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.YamlMapFactoryBean;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 重新启动项目
*
* @author wbw
* @date 2019/7/6 10:57
*/
@RestController
public class RestartController {
@Value("${spring.application.name}")
String name;
private static Logger logger = LoggerFactory.getLogger(RestartController.class);
@RequestMapping("/refresh")
public String restart() {
logger.info("spring.application.name:\t{}", name);
try {
PropUtil instance = PropUtil.getProp("application.properties");
instance.setProperty("spring.application.name", "SPRING-DYNAMIC-SERVER");
logger.info("props:\t{}", instance.getValue("spring.application.name"));
} catch (Exception e) {
logger.error("error", e);
}
ExecutorService threadPool = new ThreadPoolExecutor(1, 1, 0,
TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), new ThreadPoolExecutor.DiscardOldestPolicy());
threadPool.execute(() -> {
ExampleRestartApplication.context.close();
ExampleRestartApplication.context = SpringApplication.run(ExampleRestartApplication.class,
ExampleRestartApplication.args);
});
threadPool.shutdown();
return "spring.application.name:" + name;
}
@RequestMapping("/info")
public String info() {
logger.info("spring.application.name:" + name);
return name;
}
}
application.properties
spring.application.name=appBoot
server.port=9080
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.wbw</groupId>
<artifactId>http-boot-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>http-boot-rest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
启动测试:
- 第一次访问 /info 返回 appBoot 。
- 第二次访问 /refresh。
- 第三次访问 /info 返回 SPRING-DYNAMIC-SERVER 。
ok,完美,不过,具体应用到生产环境还是有待考验的。