实战:SpringBoot扩展功能ExitCodeGenerator生成的退出代码

1. 简介

ExitCodeGenerator是 Spring Boot 框架中的一个接口,它允许应用程序退出时生成自定义的退出代码。你可以根据不同的退出码,执行相应的动作,如:资源清理,日志记录等。

我们可以通过实现ExitCodeGenerator接口并注册为 Bean。然后,在需要的时候,可以调用SpringApplication#exit方法并传递相应的 ApplicationContext ExitCodeGenerator实例来触发应用程序的退出,并返回由 ExitCodeGenerator生成的退出代码。

ExitCodeGenerator的应用场景包括但不限于自定义错误处理、应用程序状态报告、系统监控与告警以及优雅地关闭应用程序。通过实现和使用 ExitCodeGenerator,开发者可以更加灵活地控制和管理 Spring Boot 应用程序的退出行为,从而提高系统的可靠性和可维护性。

保留异常退出和正常退出的现场。

2. 实战案例

关于退出码exitCode说明:一般0表示成功,其它数字表示因异常而退出。

2.1 根据不同的异常退出程序

定义异常代码

public interface ExitCode {/**初始化错误*/int INIT_ERROR = 1 ;/**类没有发现错误*/int NOT_FOUND_CLASS_ERROR = 2 ;/**内存溢出错误*/int OOM_ERROR = 3 ;
}
上面定义了3中错误类型

定义异常退出

@Component
public class AppExit {private final ApplicationContext context ;public AppExit(ApplicationContext context) {this.context = context ;}public void exit(Throwable e) {// 初始化错误if (e instanceof ExceptionInInitializerError err) {// TODOSpringApplication.exit(this.context, () -> ExitCode.INIT_ERROR) ;}// 类没有发现错误if (e instanceof NoClassDefFoundError err) {// TODOSpringApplication.exit(this.context, () -> ExitCode.NOT_FOUND_CLASS_ERROR) ;}// OOM错误if (e instanceof OutOfMemoryError err) {System.err.println("发生OOM,内存溢出了,程序准备退出") ;SpringApplication.exit(this.context, () -> ExitCode.OOM_ERROR) ;}}
}
该类定义了不同错误时执行不同的退出逻辑。

定义全局错误拦截

@RestControllerAdvice
public static class ErrorControllerAdvice {private final AppExit appExit ;public ErrorControllerAdvice(AppExit appExit) {this.appExit = appExit ;}// 退出程序,所以无需返回值@ExceptionHandler({ExceptionInInitializerError.class, NoClassDefFoundError.class, OutOfMemoryError.class})public void error(Throwable e) {this.appExit.exit(e.getCause()) ;}
}
该错误拦截器会对上面3个Error进行处理。

测试代码

这里模拟OOM错误

List<byte[]> list = new ArrayList<>() ;
@GetMapping("")
public Object exit() {while(true) {try {TimeUnit.MILLISECONDS.sleep(100) ;}list.add(new byte[200 * 1024 * 1024]) ;}
}
启动SpringBoot程序时设置堆内存
-Xmx100m -Xmx100m

测试结果

图片

我们的程序也退出了。

2.2 ExitCodeGenerator定义为Bean

我们可以将多个ExitCodeGenerator定义为bean。当执行退出时,会遍历所有的对象,直到exitCode不为0时退出。如下示例:

@Component
public class ErrorInitializerExitCode implements ExitCodeGenerator {public int getExitCode() {System.err.printf("初始化错误退出...") ;return ExitCode.INIT_ERROR ;}
}
@Component
public class ErrorClassNotFoundExitCode implements ExitCodeGenerator {public int getExitCode() {System.err.printf("类没有发现错误退出...") ;return ExitCode.NOT_FOUND_CLASS_ERROR ;}
}
@Component
public class ErrorOOMExitCode implements ExitCodeGenerator {public int getExitCode() {System.err.printf("OOM错误退出...") ;return ExitCode.OOM_ERROR ;}
}
上面示例定义了3个ExitCodeGenerator Bean实例,当调用退出方法时,会遍历这3个Bean对象,通过正常的代码调用退出方法
@GetMapping("/e")
public Object quit() {try {// 调用接口后,能返回正常的值return "success quit" ;} finally {new Thread(() -> {try {TimeUnit.MILLISECONDS.sleep(500) ;} catch (InterruptedException e) {}SpringApplication.exit(this.context) ;}).start() ;}
}

输出结果

图片

这里的输出就与具体什么异常没有关系了,只要遇到第一个返回不为0的数字,则直接退出了。

如果你希望控制这些ExitCode的顺序,那么你可以实现Ordered接口或者使用@Order注解。如下示例:

@Component
public static class ErrorInitializerExitCode implements ExitCodeGenerator, Ordered {public int getExitCode() {System.err.printf("初始化错误退出...%n") ;return ExitCode.INIT_ERROR ;}@Overridepublic int getOrder() {return 1 ;}
}
注:order值越小优先级越高。

2.3 退出事件监听

当exitCode返回值不为0时,Spring Boot会发布ExitCodeEvent事件,我们可以监听该事件进行相应的处理。

@Component
public class ExitCodeEventListener implements ApplicationListener<ExitCodeEvent> {@Overridepublic void onApplicationEvent(ExitCodeEvent event) {System.out.printf("程序准备退出, 退出码: %d%n", event.getExitCode()) ;}
}
输出结果

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/46701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最适合入门的面向对象编程教程:17 类和对象的Python实现-鸭子类型与“file-like object“

全网最适合入门的面向对象编程教程&#xff1a;17 类和对象的 Python 实现-鸭子类型与“file-like object“ 摘要&#xff1a; 本文主要介绍了 Python 中创建自定义类时鸭子类型的基本定义、特点和应用场景&#xff0c;同时列举了**“file-like object“** 的例子对鸭子类型进…

axios以post方式提交表单形式数据

某些后端框架请求接口必须走form表单提交的那种形式&#xff0c;但前端很少有<form action"接口地址" method"post"></form>这种写法去提交表单数据&#xff0c;所以前端需要用axios模拟一个表单提交接口。 Content-Type 代表发送端&#xff0…

单链表的介绍和实现

前言 Hello,小伙伴们&#xff0c;你们的作者君又回来了&#xff0c;今天我将带领大家继续学习另一种线性表&#xff1a;单链表&#xff0c; 准备好的小伙伴三连打卡上车&#xff0c;你们的支持就是我更新的动力&#xff0c;一定不要吝啬手中的三连哟&#xff0c;万分感谢&…

ElementUI el-select 组件动态设置disabled后,高度变更的问题解决办法

问题描述 Vue2 项目在使用 el-select 组件时&#xff0c;动态将disabled变更为了 true&#xff0c;元素的高度发生了变化。 问题原因 通过浏览器开发人员工具面板&#xff0c;发现&#xff0c;组件内的 input 元素被动态设置了height的样式&#xff1a; 在项目中检查后并…

深度解析:如何优雅地删除GitHub仓库中的特定commit历史

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

three.js创建基础模型

场景是一个三维空间&#xff0c;是所有物品的容器。可以将其想象成一个空房间&#xff0c;里面可以放置要呈现的物体、相机、光源等。 通过new THREE.Scene()来创建一个新的场景。 /**1. 创建场景 -- 放置物体对象的环境*/ const scene new THREE.Scene();场景只是一个三维的…

django学习入门系列之第四点《案例 后台管理样例》

文章目录 往期回顾 前期准备&#xff1a; 导航新建&#xff0c;按钮表格 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!-- 开发版本 --><link rel"stylesheet…

2024-07-16 Unity插件 Odin Inspector6 —— Group Attributes

文章目录 1 说明2 Group 特性2.1 BoxGroup2.2 ButtonGroup2.3 FoldoutGroup2.4 ShowIfGroup / HideIfGroup2.5 HorizontalGroup2.6 ResponsiveButtonGroup2.7 TabGroup2.8 ToggleGroup2.9 VerticalGroup 1 说明 ​ 本文介绍 Odin Inspector 插件中有关 Group 特性的使用方法。…

【解决问题】permission denied while trying to connect to the Docker daemon socket

解决方法 sudo usermod -aG docker $USER 运行上面命令&#xff0c;将当前用户添加到 docker 组&#xff0c;重启电脑。 GPT-4o (OpenAI) 看起来你在尝试通过 make build 构建项目时遇到了权限问题&#xff0c;尤其是在拉取 Docker 镜像时没有权限访问 Docker 的 Unix 套接…

如何使用 GPT?

​通过实例&#xff0c;来展示如何最好地使用 GPT。 生成文字 假设你在写一篇文章&#xff0c;需要在结尾加上这样一句&#xff1a;「California’s population is 53 times that of Alaska.」&#xff08;加州的人口是阿拉斯加州的 53 倍&#xff09;。 但现在你不知道这两个…

谷歌准备斥资 230 亿收购网络安全初创公司 Wiz

Alphabet 正在就收购 Wiz 进行深入谈判&#xff0c;这将显著增强其安全能力。这将是谷歌母公司有史以来最大规模的收购。 这是路透社根据匿名消息来源撰写的内容。目标收购金额为230亿美元&#xff0c;即211亿欧元。 Wiz 拥有实时检测和响应网络威胁的技术。通过实施人工智能…

有关电力电子技术的一些相关仿真和分析:⑥单相相控调压电路与单相斩控调压电路(MATLAB/Siumlink仿真)

针对单相相控调压电路&#xff0c;仿真研究对于给定负载&#xff0c;不同触发角作用下&#xff0c;输出电压波形和输入电流波形&#xff08;对照电网电压&#xff09;&#xff0c;研究输出电压有效值随触发角变化的规律&#xff0c;讨论并验证输入电流连续的条件。采用相同的电…

WPF实现一个带旋转动画的菜单栏

WPF实现一个带旋转动画的菜单栏 一、创建WPF项目及文件1、创建项目2、创建文件夹及文件3、添加引用 二、代码实现2.ControlAttachProperty类 一、创建WPF项目及文件 1、创建项目 打开VS2022,创建一个WPF项目&#xff0c;如下所示 2、创建文件夹及文件 创建资源文件夹&…

<Qt> 初识Qt

目录 一、项目文件解析 widget.h main.cpp widget.cpp widget.ui .pro文件 二、QT 实现Hello World程序 &#xff08;一&#xff09;按钮控件 1. 纯代码 2. 图形化 &#xff08;二&#xff09;标签控件 1. 纯代码 2. 图形化 三、内存泄漏问题 四、qdebug()的使用…

php基础: 三角形

包含&#xff1a;左三角、左上三角、右三角、右上三角、等腰三角、倒等腰三角。注意空格的数量&#xff0c;因为*号后面加了空格 /*** * 左三角形* param $n* return void*/ function triangleLeft($n){echo <pre>;for ($i 1; $i < $n; $i) {for ($j 1; $j < $i…

el-table的selection多选表格改为单选

需求场景: 选择表格数据时&#xff0c;需要控制单条数据的操作按钮是否禁用。 效果图: html代码: <div><el-tableref"multipleTable":data"tableData"tooltip-effect"dark"style"width: 100%"selection-change"handl…

Android:创建自定义View

点击查看创建自定义view官网文档 一、简介 设计良好的自定义视图与任何其他精心设计的类一样。它通过一个简单的接口封装一组特定的功能&#xff0c;高效使用 CPU 和内存&#xff0c;诸如此类。除了是一个精心设计的类之外&#xff0c;自定义视图还必须执行以下操作&#xff1…

LinuxShell编程2——shell搭建Discuzz论坛网站

目录 一、环境准备 ①准备一台虚拟机 ②初始化虚拟机 1、关闭防火墙 2、关闭selinux 3、配置yum源 4、修改主机名 二、搭建LAMP环境 ①安装httpd(阿帕奇apache&#xff09;服务器 查看是否安装过httpd 启动httpd 设置开机启动 查看状态 安装网络工具 测试 ②安装…

STM32 - FLASH 笔记

STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&#xff0c;通过闪存存储器接口&#xff08;外设&#xff09;可以对程序存储器和选项字节进行擦除和编程 读写FLASH的用途&#xff1a; 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 通过在程序…

java设计模式(十五)命令模式(Command Pattern)

1、模式介绍&#xff1a; 命令模式&#xff08;Command Pattern&#xff09;是一种行为设计模式&#xff0c;其主要目的是将请求封装成一个对象&#xff0c;从而允许使用不同的请求、队列或者日志来参数化其他对象。这种模式使得命令的请求者和实现者解耦。 2、应用场景&…