1、添加actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、自定义actuator关停代码
@Endpoint(
id = "myShutdown",
enableByDefault = false
)
@Component
@Slf4j
public class MyShutdownEndpoint implements ApplicationContextAware{
private static final Map<String, String> NO_CONTEXT_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap("message", "No context to shutdown."));
private static final Map<String, String> SHUTDOWN_MESSAGE = Collections.unmodifiableMap(Collections.singletonMap("message", "Shutting down, bye..."));
private ConfigurableApplicationContext context;
public MyShutdownEndpoint() {
}
@WriteOperation
public Map<String, String> shutdown() {
if (this.context == null) {
return NO_CONTEXT_MESSAGE;
} else {
boolean var6 = false;
Map var1;
try {
//在停止程序前,先停止自定义的模块代码。
String modules = ConfigurationHolder.getSystemParamFromFile(GlobalConstant.MODULE_CODE, "");
if (Tools.isNotEmptyStr(modules)) {
String[] moduleArr = modules.split(",");
SignalModule module;
for (String moduleName : moduleArr) {
module = (SignalModule) context.getBean(moduleName);
module.stopModule();
log.info("模块{}已停止",moduleName);
}
}
var6 = true;
var1 = SHUTDOWN_MESSAGE;
var6 = false;
} finally {
if (var6) {
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(this.getClass().getClassLoader());
thread.start();
}
}
Thread thread = new Thread(this::performShutdown);
thread.setContextClassLoader(this.getClass().getClassLoader());
thread.start();
return var1;
}
}
private void performShutdown() {
try {
Thread.sleep(500L);
} catch (InterruptedException var2) {
Thread.currentThread().interrupt();
}
this.context.close();
}
public void setApplicationContext(ApplicationContext context) throws BeansException {
if (context instanceof ConfigurableApplicationContext) {
this.context = (ConfigurableApplicationContext)context;
}
}
}
3、配置properties文件
# 利用actuator优雅停止程序
management.endpoint.health.show-details=always
# 原启用shutdown配置
# management.endpoint.shutdown.enabled=true
#自定义启用myShutdown配置
management.endpoint.myShutdown.enabled=true
management.health.redis.enabled=false
management.health.db.enabled=false
management.endpoints.web.exposure.include=*
# 自定义管理断点的前缀,安全性考虑
management.endpoints.web.base-path=/actuator
# 自定义端口
management.server.port=18081
# 不允许远程管理连接,安全性考虑
management.server.address=127.0.0.1
4、本地测试
成功后会输出:{"message":"Shutting down, bye..."}
5、附shell脚本启动与停止
#!/bin/bash
#这里可替换为你自己的执行程序,其他代码无需更改
APP_NAME=demoApp
APP_JAR=demoApp-1.0-RELEASE.jar
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is already running. pid=${pid} ."
else
nohup /home/jdk1.8.0_161/bin/java -D$APP_NAME -jar $APP_JAR > logs/demoApp.log 2>&1 &
status
tail -f logs/demoApp.log
fi
}
#停止方法
stop(){
is_exist
if [ $? -eq "0" ]; then
curl -X POST http://127.0.0.1:18081/actuator/myShutdown
httpode="$(curl -sL -w '%{http_code}' http://127.0.0.1:18081/actuator/myShutdown -o /dev/null)";
while [ "${httpCode}" != "000" ]
do
httpCode="$(curl -sL -w '%{http_code}' http://127.0.0.1:18081/actuator/myShutdown -o /dev/null)"
done
sleep 5
kill -9 $pid
echo "${APP_NAME} is stop success"
else
echo "${APP_NAME} is not running"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo "${APP_NAME} is running. Pid is ${pid}"
else
echo "${APP_NAME} is NOT running."
fi
}
#重启
restart(){
stop
start
}
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac