【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的异常处理:全局异常与自定义异常

 <前文回顾>

点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12907601&sharerefer=PC&sharesource=FoyoDesigner&sharefrom=from_link

<今日更新>

一、开篇整活儿

今儿个咱唠唠 Spring Boot 里头的异常处理。这玩意儿吧,说大不大,说小不小,整好了是锦上添花,整不好就是火上浇油。你要是刚入门,那可得悠着点儿,别一上来就整得自己“翻车”了。

二、Java 中的异常是啥构型?

Java 里头的异常,说白了就是程序运行时出的岔子。Java 的异常体系是“树形结构”,最顶上是 Throwable,往下分成 Error 和 Exception。Error 是那种严重的、没法儿处理的错误,比如说内存溢出啥的。Exception 是那种可以处理的异常,比如说空指针、数组越界啥的。

1. Exception 的分类

Exception 又分成两种:受检异常非受检异常

  • 受检异常:这种异常你得在代码里头显式处理,要么 try-catch,要么 throws。比如说 IOException,你要是读写文件,那得处理这个异常。
  • 非受检异常:这种异常不用显式处理,比如说 NullPointerException、ArrayIndexOutOfBoundsException,这些异常通常是代码写得不严谨导致的。

Java Code

// 受检异常示例

try {

    FileInputStream fis = new FileInputStream("file.txt");

} catch (IOException e) {

    e.printStackTrace();

}

// 非受检异常示例

String str = null;

System.out.println(str.length()); // 这里会抛出 NullPointerException

2. 异常之间的关系

Java 里头的异常是“继承关系”,子类异常可以捕获父类异常。比如说,IOException 是 Exception 的子类,你要是 catch 了 Exception,那 IOException 也能被捕获。

Java Code

try {

    // 一些可能抛出异常的代码

} catch (IOException e) {

    // 处理 IOException

} catch (Exception e) {

    // 处理其他 Exception

}

这段代码里头,IOException 会被第一个 catch 捕获,其他的 Exception 会被第二个 catch 捕获。

三、Spring Boot 中的全局异常处理

Spring Boot 里头有个 @ControllerAdvice 注解,专门用来做全局异常处理。你可以把它想象成一个“兜底的”,Controller 里头没处理的异常,它都能接住。

1. 全局异常处理示例

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception e) {

        return new ResponseEntity<>("出错了:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);

    }

}

这段代码里头,@ControllerAdvice 是用来定义一个全局的异常处理类,@ExceptionHandler 是用来处理特定类型的异常的。ResponseEntity 是用来返回 HTTP 响应的,里头可以带上状态码和响应体。

2. 处理特定异常

你可以针对不同的异常,写不同的处理方法。比如说,处理 NullPointerException 和 IllegalArgumentException。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(NullPointerException.class)

    public ResponseEntity<String> handleNullPointerException(NullPointerException e) {

        return new ResponseEntity<>("空指针异常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

    }

    @ExceptionHandler(IllegalArgumentException.class)

    public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {

        return new ResponseEntity<>("参数不合法:" + e.getMessage(), HttpStatus.BAD_REQUEST);

    }

}

这段代码里头,NullPointerException 和 IllegalArgumentException 会被分别处理,返回不同的错误信息。

四、自定义异常

有时候,Java 自带的异常不够用,你得自己整一个。自定义异常很简单,继承 Exception 或者 RuntimeException 就行。

1. 自定义异常示例

Java Code

public class MyCustomException extends RuntimeException {

    public MyCustomException(String message) {

        super(message);

    }

}

这段代码里头,MyCustomException 是自定义异常,继承自 RuntimeException,所以它是非受检异常。

2. 使用自定义异常

你可以在代码里头抛出这个自定义异常。

Java Code

@RestController

@RequestMapping("/api")

public class MyController {

    @GetMapping("/test")

    public String test() {

        throw new MyCustomException("这是我的自定义异常");

    }

}

这段代码里头,test 方法会抛出 MyCustomException,然后被全局异常处理器捕获。

3. 处理自定义异常

你可以在全局异常处理器里头,专门处理这个自定义异常。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(MyCustomException.class)

    public ResponseEntity<String> handleMyCustomException(MyCustomException e) {

        return new ResponseEntity<>("自定义异常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

    }

}

这段代码里头,MyCustomException 会被专门处理,返回自定义的错误信息。

五、异常的 AOP 处理

AOP(面向切面编程)是 Spring 里头的一个高级特性,可以用来在方法执行前后做一些额外的事情。异常处理也可以用 AOP 来做。

1. AOP 处理异常示例

Java Code

@Aspect

@Component

public class ExceptionAspect {

    @AfterThrowing(pointcut = "execution(* com.example.demo.controller.*.*(..))", throwing = "e")

    public void handleException(Exception e) {

        System.out.println("捕获到异常:" + e.getMessage());

    }

}

这段代码里头,@Aspect 是用来定义一个切面,@AfterThrowing 是用来在方法抛出异常后执行的。pointcut 是指定哪些方法需要被切面处理,throwing 是指定异常对象的变量名。

2. AOP 和全局异常处理的区别

AOP 和全局异常处理都可以用来处理异常,但它们的应用场景不一样。全局异常处理是用来处理 Controller 里头的异常,而 AOP 可以用来处理任何地方的异常,比如说 Service 层、DAO 层啥的。

六、Spring Boot 里头的异常处理坑点

1. 异常处理的顺序

Spring Boot 里头,异常处理的顺序很重要。你要是先 catch 了 Exception,那后面的 catch 就不起作用了。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception e) {

        return new ResponseEntity<>("出错了:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);

    }

    @ExceptionHandler(NullPointerException.class)

    public ResponseEntity<String> handleNullPointerException(NullPointerException e) {

        return new ResponseEntity<>("空指针异常:" + e.getMessage(), HttpStatus.BAD_REQUEST);

    }

}

这段代码里头,NullPointerException 会被 handleException 捕获,handleNullPointerException 就不起作用了。

2. 异常信息的暴露

Spring Boot 里头,默认会把异常信息返回给客户端。你要是觉得这样不安全,可以把异常信息隐藏掉。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception e) {

        return new ResponseEntity<>("出错了", HttpStatus.INTERNAL_SERVER_ERROR);

    }

}

这段代码里头,异常信息被隐藏了,客户端只能看到“出错了”。

3. 日志记录

异常处理里头,日志记录是个大事儿。你要是没记日志,那出了问题就抓瞎了。

Java Code

@ControllerAdvice

public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)

    public ResponseEntity<String> handleException(Exception e) {

        logger.error("捕获到异常:", e);

        return new ResponseEntity<>("出错了", HttpStatus.INTERNAL_SERVER_ERROR);

    }

}

这段代码里头,异常信息被记录到日志里头了,方便以后排查问题。

专有名词解释

  1. Throwable:Java 中所有错误和异常的基类。
  2. Error:Java 中表示严重错误的类,通常无法恢复。
  3. Exception:Java 中表示可恢复异常的类。
  4. 受检异常:必须在代码中显式处理的异常。
  5. 非受检异常:不需要显式处理的异常。
  6. ControllerAdvice:Spring 中用于定义全局异常处理类的注解。
  7. ExceptionHandler:Spring 中用于处理特定类型异常的注解。
  8. ResponseEntity:Spring 中用于封装 HTTP 响应的类。
  9. AOP:面向切面编程,一种编程范式,用于在方法执行前后做一些额外的事情。
  10. Aspect:Spring 中用于定义切面的注解。
  11. AfterThrowing:Spring 中用于在方法抛出异常后执行的注解。
  12. Logger:用于记录日志的工具类。

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

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

相关文章

【Mybatis-plus】在mybatis-plus中 if test标签如何判断 list不为空

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

Lineageos 22.1(Android 15)制定应用强制横屏

一、前言 有时候需要系统的某个应用强制衡平显示&#xff0c;不管他是如何配置的。我们只需要简单的拿到top的Task下面的ActivityRecord&#xff0c;并判断包名来强制实现。 二、调整wms com.android.server.wm.DisplayRotation /*** Given an orientation constant, return…

HTML网页代码预览器

HTML网页代码预览器 可以用于学习和实验HTML和CSS&#xff0c;比较方便。源码参考自网络。 功能 实时预览&#xff1a;当你在左侧的“代码编辑器”中输入代码时&#xff0c;右侧的“预览窗口”会实时显示你的网页效果&#xff08;注意&#xff0c;不能体现嵌入的JavaScript运…

Arm Linux ceres库编译

由于工作需要&#xff0c;需在国产化系统上编译ceres库&#xff0c;手上有一块树莓派&#xff0c;就在树莓派上面进行测试编译ceres库&#xff0c;总体来说比较顺利。只出现了一点小问题 参考链接&#xff1a; Ceres中文教程-安装 按照上面Linux编译过程 目录 1、在线安装依赖…

【算法学习计划】动态规划 -- 背包问题(01背包和完全背包)

目录 DP41 【模板】01背包 leetcode 416.分割等和子集 leetcode 494.目标和 leetcode 1049.最后一块石头的重量Ⅱ DP42 【模板】完全背包 leetcode 322.零钱兑换 leetcode 518.零钱兑换Ⅱ leetcode 279.完全平方数 今天&#xff0c;我们将通过 8 道题目&#xff0c;来带…

138. 随机链表的复制

题目&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节…

网络HTTPS协议

Https HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是 HTTP 协议的加密版本&#xff0c;它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说&#xff1a; • 加密通信&#xff1a;在用户请求访问一个 HTTPS 网站时&#xff0c;客户端&#x…

19921 多重背包

19921 多重背包 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;动态规划、背包问题 &#x1f4d6; &#x1f4da; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.Scanner;public class Main {static int N …

C/C++蓝桥杯算法真题打卡(Day5)

一、P8772 [蓝桥杯 2022 省 A] 求和 - 洛谷 算法代码&#xff1a; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便编程 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用标准库函数时都要加 std::int main() {int n; …

【大模型基础_毛玉仁】3.5 Prompt相关应用

目录 3.5 相关应用3.5.1 基于大语言模型的Agent3.5.2 数据合成3.5.3 Text-to-SQL3.5.4 GPTs 3.5 相关应用 Prompt工程应用广泛&#xff0c;能提升大语言模型处理基础及复杂任务的能力&#xff0c;在构建Agent、数据合成、Text-to-SQL转换和设计个性化GPTs等方面不可或缺。 . …

主成分分析PCA与奇异值分解SVD

线性代数 SVD 奇异值分解&#xff08;Singular Value Decomposition&#xff0c;简称 SVD&#xff09;是线性代数中的一种基本工具&#xff0c;它将任意一个 (m * n) 矩阵 (A) 分解成三个简单矩阵的乘积&#xff0c;即 其中&#xff1a; (U) 是一个 (m*m) 的正交&#xff08…

自主代理的摩尔定律:AI 的指数级革命

图像由 Gemini 生成 前言&#xff1a;AI 正在以超过摩尔定律的速度迅速提升其自主工作能力&#xff0c;研究显示&#xff0c;AI 能够可靠完成的任务时长正以每 7 个月翻一倍的速度增长。这种指数级的发展趋势意味着&#xff0c;AI 不再只是应对简单问答或短任务的工具&#xff…

气膜文化馆:打造沉浸式文娱新空间—轻空间

演唱会、展览、音乐剧……都能办&#xff1f; 当然&#xff01;气膜文化馆不仅适用于体育赛事&#xff0c;在文化娱乐方面同样大放异彩&#xff01; 声学优化&#xff0c;打造极致听觉体验 气膜文化馆采用专业声学设计&#xff0c;避免传统场馆的回声干扰&#xff0c;提供更清…

【数据标准】数据标准化框架体系-对象类数据标准

导读&#xff1a;对象类数据标准化框架通过统一数据定义、分类和标记&#xff0c;解决数据孤岛与不一致问题&#xff0c;支撑数据分析、AI应用与合规需求。企业需结合自身业务特性&#xff0c;灵活选择国际标准&#xff08;如ISO&#xff09;、行业规范或自建体系&#xff0c;并…

【江协科技STM32】软件SPI读写W25Q64芯片(学习笔记)

SPI通信协议及S为5Q64简介&#xff1a;【STM32】SPI通信协议&W25Q64Flash存储器芯片&#xff08;学习笔记&#xff09;-CSDN博客 STM32与W25Q64模块接线&#xff1a; SPI初始化&#xff1a; 片选SS、始终SCK、MOSI都是主机输出引脚&#xff0c;输出引脚配置为推挽输出&…

C 语 言 --- 扫 雷 游 戏(初 阶 版)

C 语 言 --- 扫 雷 游 戏 初 阶 版 代 码 全 貌 与 功 能 介 绍扫雷游戏的功能说明游 戏 效 果 展 示游 戏 代 码 详 解game.htest.cgame.c 总结 &#x1f4bb;作 者 简 介&#xff1a;曾 与 你 一 样 迷 茫&#xff0c;现 以 经 验 助 你 入 门 C 语 言 &#x1f4a1;个 人 主…

数据库基础知识

目录 一、什么是数据库&#xff1f; 二、基本使用方法 &#xff08;1&#xff09;启动服务器进程 &#xff08;2&#xff09;连接服务器 &#xff08;3&#xff09;基本sql语句 三、MySQL架构 四、SQL语句分类 五、存储引擎是什么 一、什么是数据库&#xff1f; 数据库…

在线生成自定义二维码

在线生成自定义二维码 1. 引言 二维码已成为现代互联网的重要工具&#xff0c;广泛应用于链接分享、支付、身份认证等场景。然而&#xff0c;很多在线二维码生成工具功能有限&#xff0c;难以满足个性化需求。如果你需要 自定义颜色、Logo、不同形状的二维码&#xff0c;那么…

DeepSeek处理多模态数据的技术要点和实现方式

DeepSeek具备处理多模态数据的能力&#xff0c;以下是相关技术要点和实现方式。 1. ‌多模态模型架构‌ ‌单流/双流网络‌&#xff1a;通过将文本和图像输入统一编码器&#xff08;单流&#xff09;或分别编码后交互&#xff08;双流&#xff09;实现模态融合‌。‌预训练模…

系统架构设计知识体系总结

1.技术选型 1.什么是技术选型&#xff1f; 技术选型是指评估和选择在项目或系统开发中使用的最合适的技术和工具的过程。这涉及考虑基于其能力、特性、与项目需求的兼容性、可扩展性、性能、维护和其他因素的各种可用选项。技术选型的目标是确定与项目目标相符合、能够有效解…