spring:
pid:
file: F:/cloud-nacos/cloud_gateway/application.pid
原始启动类
SpringApplication.run(MainApplication.class, args);
@SpringBootApplication
@EnableDiscoveryClient
public class GateWayApp {
/**
* @author: GuoTong
* @date: 2022-10-05 10:42:59
*/
public static void main(String[] args) {
try {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication springApplication = new SpringApplication(MainApplication.class);
springApplication.addListeners(new ApplicationPidFileWriter());
springApplication.run(args);
} catch (Exception e) {
e.printStackTrace();
}
}
package com.gton.shutdown;
import com.alibaba.cloud.commons.io.FileUtils;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.gton.config.Resp;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.IOException;
/**
* @description: 优雅停机?
* 简单的说,就是向应用进程发出停止指令之后,能保证正在执行的业务操作不受影响,
* 直到操作运行完毕之后再停止服务。
* @author: GuoTong
* @createTime: 2023-07-14 22:32
* @since JDK 1.8 OR 11
**/
@RestController
@Slf4j
public class ApplicationContextShutDown implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
/**
* Description: 优雅停机
*
* @author: GuoTong
* @date: 2023-07-14 22:46:01
* @return:void
*/
@GetMapping(value = {"/ShutDown", "/shutdown"})
public void shutdownFunction() {
log.info("Application Context Doing ShutDown .......");
((ConfigurableApplicationContext) context).close();
}
/**
* Description: 获取进程号
*
* @author: GuoTong
* @date: 2023-07-14 22:46:01
* @return:void
*/
@GetMapping(value = {"/queryPid", "/getPid"})
public Resp queryApplicationPid() {
String fileInputStreamPid = getPidFunction();
return Resp.Ok(fileInputStreamPid);
}
/**
* Description: 强行终止进程
*
* @author: GuoTong
* @date: 2023-07-14 22:46:01
* @return:void
*/
@GetMapping(value = {"/kill", "/stop", "/termination"})
public void termination() {
// 获取上下文环境信息{application.yml}
String pid = getPidFunction();
String endingApplicationShell = "kill -9 " + pid;
// java主要通过Runtime和Process执行Linux命令, Process是Runtime.exec返回值,可以用来对执行过程进行后续操作(获取结果,发送命令,等待结果)。
try {
log.info("强行终止进程 ,{}", endingApplicationShell);
Runtime.getRuntime().exec(endingApplicationShell);
} catch (IOException e) {
log.error("强行终止进程失败", e);
}
}
/**
* Description: 容器销毁前调用
*
* @author: GuoTong
* @date: 2023-07-14 22:42:19
* @return:
*/
@PreDestroy
public void PreDestroy() {
log.info("springBoot项目已经优雅关闭 .......");
}
/**
* Description:Springboot自身提供的优雅停机
*
* @param applicationContext
* @author: GuoTong
* @date: 2023-07-14 22:42:08
* @return:
*/
public void exitApplication(ApplicationContext applicationContext) {
// SpringApplication.exit()方法也可以安全的退出程序
int exit = SpringApplication.exit(applicationContext, (ExitCodeGenerator) () -> 0);
//同时会返回一个退出码,这个退出码可以传递给所有的context最后通过调用System.exit()可以将这个错误码也传给JVM。
System.exit(exit);
}
/**
* Description: 获取上下文环境信息{application.yml}PID
*
* @author: GuoTong
* @date: 2023-07-15 00:15:14
* @return:java.lang.String
*/
private String getPidFunction() {
Environment environment = context.getEnvironment();
String pidFileName = environment.getProperty("spring.pid.file");
if (StringUtils.isEmpty(pidFileName)) {
pidFileName = "application.pid";
}
String fileInputStreamPid = null;
try {
fileInputStreamPid = FileUtils.readFileToString(new File(pidFileName), CharsetUtil.UTF_8);
} catch (IOException e) {
log.info("获取Pid失败", e);
}
return fileInputStreamPid;
}
}
Maven实例:pom.xml文件中添加更换依赖 org.springframework.boot spring-boot-starter