异常统一处理:Exception(兜底异常)

一、引言

本篇内容是“异常统一处理”系列文章的重要组成部分,主要聚焦于对 Exception(兜底异常) 的原理解析与异常处理机制,并给出测试案例。

  • 关于 全局异常统一处理 的原理和完整实现逻辑,请参考文章:
    《SpringBoot 全局异常统一处理(AOP):@RestControllerAdvice + @ExceptionHandler + @ResponseStatus》
  • 本文仅详细解析 Throwable(兜底异常) 的异常处理;其他类型异常的原理和处理方法,请参阅本文所在专栏内的其他文章。

二、异常原理

SpringBoot项目,异常统一处理,是否应该有兜底异常?

在Spring Boot项目中,异常统一处理是非常重要的一部分,确保系统能够以一致且用户友好的方式响应各种运行时错误。确实应该设计一个兜底异常处理器,它通常用来捕获那些没有被具体异常处理器所处理的任何未预期或未知的异常。

兜底异常处理器(Fallback Exception Handler) 的作用在于:

  1. 全面覆盖:当出现没有明确指定的异常类型时,兜底异常处理器可以捕获所有未被捕获的异常。

  2. 友好提示:对于这类无法预知的具体问题,兜底异常处理器通常会返回一个通用的错误信息给客户端,避免暴露过多服务器内部细节。

  3. 日志记录:在处理这些异常时,通常还会进行详细的日志记录,这对于后续排查问题至关重要。

  4. 业务连续性:在某些场景下,兜底异常处理器还可能包含重试机制、熔断策略或者降级服务,以保证系统的健壮性和可用性。

在Spring Boot中实现兜底异常处理的方式是在带有@ControllerAdvice注解的全局异常处理类中定义一个处理Exception的方法,并使用@ExceptionHandler(Exception.class)注解该方法。通过这种方式,无论哪种未处理的异常发生,都会触发这个兜底异常处理器来进行集中处理。

三、异常处理代码

3.1 异常处理示意图

在这里插入图片描述

3.2 异常处理核心代码

package com.example.core.advice;

import com.example.core.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.HandlerMethod;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final String USER_TIP = "服务器异常!请稍后重试,或联系业务人员处理。";

    /**
     * 兜底异常处理。
     * <p>
     * 作为最后兜底的异常处理,不应该将异常信息的细节返回给前端;
     * 因为异常信息中可能会包含一些敏感信息,比如SQL报错可能会包含数据库的表名、字段名和SQL语句,将这些暴露给用户存在安全性风险。
     */
    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<String> handle(Exception e, HandlerMethod handlerMethod) {
        // 记录错误日志
        log.error("发生了一个未预期的异常", e);

        // 返回统一的错误响应给前端。
        return Result.fail(USER_TIP, String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), null);
    }

}    

四、测试案例

4.1 测试代码

package com.example.web.exception.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("exception")
@Tag(name = "异常统一处理")
public class ExceptionController {

    @GetMapping("fallback_exception")
    @Parameter(name = "input", description = "输入参数", example = "张三", in = ParameterIn.QUERY)
    @Operation(summary = "兜底异常", description = "当 input 为空时,抛出异常。")
    public String testFallbackException(@Nullable String input) {
        // IDE在此处给出警告;这是为了测试,特意留下来的。
        String lowerCaseInput = input.toLowerCase();
        log.info("lowerCaseInput = {}", lowerCaseInput);
        return "成功";
    }

}

4.2 正确请求示例

在这里插入图片描述

4.3 未处理异常时的报错

请求响应

在这里插入图片描述

控制台的错误日志

在这里插入图片描述

4.4 已处理异常时的响应

在这里插入图片描述

五、相关问题

(1)异常统一处理,是否应该有兜底异常?

我认为应该有兜底异常。详细解释请参考如下文章。

参考文章:《异常处理:全面覆盖与精细化管理的平衡》

(2)Exception和Throwable,哪个更合适?

在Java中,所有异常都是Throwable类的子类。Throwable是Java中所有错误或异常的超类,它有两个直接子类:ErrorException

  • Error是程序无法处理的错误,通常表示运行时环境的错误,如系统崩溃、虚拟机错误(如OutOfMemoryError)等,应用程序一般不应捕获这类错误进行处理。

  • Exception则是程序可以捕获并进行处理的异常,包括了检查型异常(如IOException)和运行时异常(如NullPointerException)等。

在设计Spring Boot项目全局兜底异常处理器时,通常选择捕获Exception更为合适,而非Throwable。原因如下:

  1. 业务相关性Exception涵盖了所有可能在业务逻辑中抛出并需要处理的异常情况,而Error通常是不应该被捕获并在应用层处理的。

  2. 避免处理不合适的错误:捕获Throwable可能会误处理JVM级别的错误,这些错误往往意味着更严重的系统问题,不适合在应用层面进行简单的错误处理和响应,而是应该尽快通知运维人员进行排查。

因此,推荐的做法是在全局异常处理器中使用@ExceptionHandler(Exception.class)来作为兜底异常处理,例如:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<?> handleAllExceptions(Exception ex) {
        // ...
    }
}

这样能确保我们只处理与业务相关的可预期异常,而不涉及JVM级别的内部错误。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker搭建zookeeper集群

文章目录 1. 集群搭建2. Leader选举3. Zookeeper集群角色 1. 集群搭建 这里我们使用docker-compose 搭建伪集群 version: 3.1 services:zoo1:image: zookeeperrestart: alwayscontainer_name: zoo1ports:- 2181:2181volumes:- /home/zk/zoo1/data:/data- /home/zk/zoo1/datal…

【数据结构初阶 7】二叉树:链式二叉树的基本操作实现

文章目录 &#x1f308; Ⅰ 定义二叉树结点&#x1f308; Ⅱ 创建二叉树结点&#x1f308; Ⅲ 遍历二叉树1. 先序遍历2. 中序遍历3. 后序遍历4. 层序遍历 &#x1f308; Ⅳ 销毁二叉树 &#x1f308; Ⅰ 定义二叉树结点 1. 每个结点都由三部分组成 数据域&#xff1a;存储本结…

【JVM】线上一次fullGC排查思路

fullGC问题背景 监控告警发现&#xff0c;今天开始我们线上应用频繁出现fullGC&#xff0c;并且每次出现后磁盘都会被占满 查看监控 查看监控发现FULLGC的机器均为同一个机房的集器&#xff0c;并且该机房有线上error报错&#xff0c;数据库监控对应的时间点也有异常&#x…

Vue3 路由配置 + 路由跳转 + 路由传参(动态路由传参 + 普通路由传参)

Vue Router&#xff1a; Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;让用 Vue.js 构建单页应用变得轻而易举。 效果 一、介绍 1、官方文档&#xff1a;https://router.vuejs.org/zh/introduction.html 介绍 | Vue RouterVue.js 的官方路由https://router.vuejs.…

Java/Python/Go不同开发语言基础数据结构和相关操作总结-GC篇

Java/Python/Go不同开发语言基础数据结构和相关操作总结 1. 常见gc方式1.1 gc判断对象是否存活1.2 引用计数法1.2 标记-清除算法1.3 复制算法1.4 标记-压缩算法1.5 分代收集算法 2. java的gc方式以及垃圾回收器2.1 gc方式2.1 gc回收器2.1.1 Serial收集器2.1.2 ParNew收集器2.1.…

SSM---Mybatis查询数据库的功能

Mybatis查询数据库的功能流程&#xff1a; 在maven中加入mybatis依赖&#xff0c;mysql驱动依赖创建一张student表创建表对应的实体类&#xff1a;student类&#xff0c;用来保存表中的每行数据创建持久层的DAO接口&#xff0c;用来定义操作数据库的方法创建这个表对应的sql映…

计算机设计大赛 深度学习图像风格迁移 - opencv python

文章目录 0 前言1 VGG网络2 风格迁移3 内容损失4 风格损失5 主代码实现6 迁移模型实现7 效果展示8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习图像风格迁移 - opencv python 该项目较为新颖&#xff0c;适合作为竞赛课题…

IDEA下新建SpringBoot项目详细步骤

在IDEA下使用Spring Initializer&#xff1a; 一、新建项目&#xff0c;利用阿里云网址https://start.aliyun.com/下载项目&#xff0c;来到Spring Initializer模块&#xff1a; 我的jdk是8&#xff0c;构建Maven类型的项目&#xff0c;Java版本选8&#xff0c;Group为公司名。…

二阶低通滤波器(博途PLC SCL源代码)

在学习滤波器之前我们先了解下截止频率的准确定义,周期正弦信号经过传递函数后的输出信号,其幅值衰减-3dB时对应的频率。-3dB的含义是幅值衰减为原来的约0.707。更多滤波器信号处理相关内容请参看下面文章链接: 1、PLC一阶低通滤波器 https://rxxw-control.blog.csdn.net/…

前端路由与后端路由的区别

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

JSONVUE

1.JSON学习 1.概念: JSON是把JS对象变成字符串. 2.作用: 多用于网络中数据传输. JavaScript对象 let person{name:"张三",age:18}//将JS对象转换为 JSON数据let person2JSON{"name":"张三","age":18}; 3.JS对象与JSON字符串转换…

读人工不智能:计算机如何误解世界笔记03_AlphaGo

1. 人工智能 1.1. “人工智能”这个词听起来就是电影里的意象 1.1.1. 电影《星际迷航&#xff1a;下一代》中栩栩如生的机器人“数据少校” 1.1.2. 电影《2001太空漫游》中的哈尔9000 1.1.3. 电影《她》中的人工智能系统萨曼莎 1.1.4. 漫威系列漫画和电影中钢铁侠的管家贾…

前端常用6种数据加密方式的使用(最详解)

目录 前言 一、6种常用加密方案 1.Base64加密 2.MD5加密&#xff08;不可逆&#xff09; 3.sha256加密 4.sha1加密&#xff08;相比于MD5 安全性高&#xff0c;但是 速度慢&#xff09; 5.AES加密 6.字符串的编码和解码 二、结语 往期回顾 前言 相信大家在工作或面试…

冯诺依曼体系结构 与 操作系统

一、冯诺依曼体系结构 深入理解冯诺依曼体系结构 计算机的出现就是为了解决实际问题, 所以把问题交给计算机&#xff0c;计算机经过处理&#xff0c;得到一个结果反馈给我们&#xff0c;所以这中间就必然涉及到了输入设备&#xff0c;中央处理器(包括运算器和控制器)和输出设备…

SQL数据操作

目标:掌握mysql中数据的增删改查的基本操作 新增数据 查看数据 更新数据 删除数据 1、新增数据 目标:了解数据的新增指令和逻辑&#xff0c;实现数据的入库操作 概念 新增数据:将数据插入到数据表永久存储 新增数据是根据表的字段顺序和数据类型要求将数据存放到数据表中 …

Low Poly Trees Pack - Flowers

包含59种程式化的低聚植物&#xff0c;作为.fbx网格文件和即用型预制件。 包装内含物 59 个独特的低多边形植物预制件 - 50种开花的草本植物 - 6 棵葡萄树 - 3 灌木 产品特点 -所有植物和石头预制件使用单一反照率256x256纹理图集和1种材质。 -三体计数&#xff1a;50-1000 -支…

2.21日学习打卡----初学Nginx(一)

2.21日学习打卡 目录: 2.21日学习打卡一. Nginx是什么&#xff1f;概述Nginx 五大应用场景HTTP服务器正向代理反向代理正向代理与反向代理的区别&#xff1a;负载均衡动静分离 为啥使用Nginx? 二.下载Nginx&#xff08;linux&#xff09;环境准备下载Nginx和安装NginxNginx源码…

进阶数据结构 BTree 的插入与删除操作实现

在数据库系统和文件系统中&#xff0c;高效的数据组织与管理是关键之一。B-Tree&#xff08;Balanced Tree&#xff09;作为一种平衡搜索树结构&#xff0c;在这一领域发挥着重要作用。本文详细探讨了 B-Tree 的基本概念以及对其进行插入与删除操作的实现&#xff0c;旨在帮助读…

kubectl使用及源码阅读

目录 概述实践样例yaml 中的必须字段 kubectl 代码原理kubectl 命令行设置pprof 抓取火焰图kubectl 中的 cobra 七大分组命令kubectl createcreateCmd中的builder模式createCmd中的visitor访问者模式外层VisitorFunc分析 结束 概述 k8s 版本 v1.24.16 kubectl的职责 1.主要的…

供应链大数据:穿越经济迷雾的指南针

随着经济形势的变幻莫测&#xff0c;企业运营面临着前所未有的挑战。在这个充满不确定性的时代&#xff0c;供应链大数据如同一盏明亮的指南针&#xff0c;为企业提供精准的方向指引。下面&#xff0c;我们将深入探讨供应链大数据如何帮助企业洞察市场趋势、优化库存管理、降低…