【实用知识】Spring Boot 优雅捕捉异常的几种姿势

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主

⛪️ 个人社区:个人社区
💞 个人主页:个人主页
🙉 专栏地址: ✅ Java 中级
🙉八股文专题:剑指大厂,手撕 Java 八股文

在这里插入图片描述

文章目录

    • Spring Boot 如何优雅捕捉异常?
      • 1. 全局异常处理器
      • 2. 控制器特定的异常处理器
      • 3. 使用 `@ControllerAdvice` 进行集中式异常处理
      • 4. 自定义异常
      • 5. 统一错误响应格式
      • 6. 日志记录
      • 写在最后

Spring Boot 如何优雅捕捉异常?

在Spring Boot中,优雅地捕捉和处理异常可以提高应用程序的健壮性和用户体验。Spring Boot提供了多种方式来处理异常,包括全局异常处理器、控制器特定的异常处理器以及使用@ControllerAdvice注解的集中式异常处理。

1. 全局异常处理器

你可以创建一个全局异常处理器来捕获整个应用中的异常。这通常通过实现HandlerExceptionResolver接口或继承ResponseEntityExceptionHandler类来完成。

使用 ResponseEntityExceptionHandler

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = { IllegalArgumentException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
        ErrorResponse error = new ErrorResponse("Invalid input", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = { RuntimeException.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<ErrorResponse> handleRuntimeException(RuntimeException ex) {
        ErrorResponse error = new ErrorResponse("Internal server error", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 自定义错误响应类
class ErrorResponse {
    private String message;
    private String details;

    public ErrorResponse(String message, String details) {
        this.message = message;
        this.details = details;
    }

    // Getters and setters
}

2. 控制器特定的异常处理器

你也可以在单个控制器内定义异常处理器方法,只处理该控制器内的异常。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @RequestMapping("/get")
    public User getUser() {
        // 业务逻辑
        if (someCondition) {
            throw new IllegalArgumentException("Invalid user ID");
        }
        return new User();
    }

    @ExceptionHandler(value = { IllegalArgumentException.class })
    public ResponseEntity<ErrorResponse> handleIllegalArgumentException(IllegalArgumentException ex) {
        ErrorResponse error = new ErrorResponse("Invalid input", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

3. 使用 @ControllerAdvice 进行集中式异常处理

@ControllerAdvice 是 Spring 提供的一个注解,用于定义全局异常处理类。这个类可以包含多个 @ExceptionHandler 方法,每个方法处理不同类型的异常。

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = { IllegalArgumentException.class })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleIllegalArgumentException(IllegalArgumentException ex) {
        return new ErrorResponse("Invalid input", ex.getMessage());
    }

    @ExceptionHandler(value = { RuntimeException.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleRuntimeException(RuntimeException ex) {
        return new ErrorResponse("Internal server error", ex.getMessage());
    }
}

// 自定义错误响应类
class ErrorResponse {
    private String message;
    private String details;

    public ErrorResponse(String message, String details) {
        this.message = message;
        this.details = details;
    }

    // Getters and setters
}

4. 自定义异常

为了更好地控制异常处理,你可以创建自定义异常类,并在需要的地方抛出这些异常。

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

然后在全局异常处理器中处理这些自定义异常:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = { ResourceNotFoundException.class })
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleResourceNotFoundException(ResourceNotFoundException ex) {
        return new ErrorResponse("Resource not found", ex.getMessage());
    }

    // 其他异常处理器
}

5. 统一错误响应格式

为了保持一致性,建议定义一个统一的错误响应格式。这样客户端可以更容易地解析和处理错误信息。

public class ErrorResponse {
    private int status;
    private String message;
    private String details;

    public ErrorResponse(int status, String message, String details) {
        this.status = status;
        this.message = message;
        this.details = details;
    }

    // Getters and setters
}

6. 日志记录

在异常处理器中添加日志记录,以便于调试和监控。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ControllerAdvice
public class GlobalExceptionHandler {

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

    @ExceptionHandler(value = { RuntimeException.class })
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse handleRuntimeException(RuntimeException ex) {
        logger.error("Unexpected error occurred: ", ex);
        return new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Internal server error", ex.getMessage());
    }

    // 其他异常处理器
}

写在最后

通过上述方法,你可以在Spring Boot应用中优雅地捕捉和处理异常。使用@ControllerAdvice可以集中管理异常处理逻辑,而自定义异常和统一的错误响应格式则有助于提高代码的可维护性和一致性。同时,日志记录对于调试和监控也非常重要。

精彩专栏推荐订阅:在下方专栏👇🏻
✅ 2023年华为OD机试真题(A卷&B卷)+ 面试指导
✅ 精选100套 Java 项目案例
✅ 面试需要避开的坑(活动)
✅ 你找不到的核心代码
✅ 带你手撕 Spring
✅ Java 初阶

在这里插入图片描述

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

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

相关文章

计算机网络:数据链路层 —— 虚拟局域网 VLAN

文章目录 局域网虚拟局域网 VLAN虚拟局域网 VLAN 概述实现机制IEEE 802.1Q帧以太网交换机的接口类型Access 接口Trunk 接口Hybrid 接口不进行人为的VLAN划分划分两个不同VLANTrunk接口去标签后进行转发Trunk接口直接转发 局域网 局域网&#xff08;Local Area Network&#xf…

ICP之点云特征计算

这次我们来聊一下点云的特征计算方法&#xff0c; 主流的有两类 1&#xff1a;基于直方图的特征计算 2&#xff1a;基于签名的特征计算 这次我将介绍基于直方图的方式。 基于直方图的特征方法中&#xff0c;PFH&#xff08;Point Feature Histograms&#xff09;和FPFH&#x…

vue3项目中引入阿里图标库

开篇 本篇的主题是在vue3项目中引入阿里图标库 步骤 注册阿里图标库账号(阿里图标)&#xff0c;并创建项目 将图标加入项目中 将需要的图标先加入购物车&#xff0c;随后加入到项目中 生成项目代码 在项目中生成项目代码&#xff0c;便于后续复制到vue项目中 ## 在vue3项目…

基于Ubuntu24.04,下载并编译Android12系统源码 (一)

1. 前言 1.1 编译源码可以干什么 定制Android系统将最新版本的Android系统刷入到自己的Android设备中将整个系统源码导入到Android Studio中&#xff08;可以不用编译源码来实现&#xff09;。 只要有对应的Android源码版本的android.iml和android.ipr文件&#xff0c;就可以…

使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效

背景 在项目开发中&#xff0c;实现用户友好的输入交互是提升用户体验的关键之一。例如&#xff0c;在客服对话框中&#xff0c;其中有包含多个快捷选项用于快速问答&#xff0c;每个快捷选项都是一个可点击的按钮&#xff0c;并需要绑定点击事件来执行相应操作。然而&#xf…

JavaSE笔记2】面向对象

目录 一、深刻认识面向对象 二、对象在计算机中的执行原理 三、this 四、构造器 五、封装 六、实体Javabean(实体类) 1. 是什么&#xff1f; 2. 实体类用来干什么&#xff1f; 七、成员变量和局部变量的区别 一、深刻认识面向对象 二、对象在计算机中的执行原理 三、this Java中…

LINUX1.3

cp&#xff08;复制&#xff09;: 将需要复制的文件或目录&#xff08;源&#xff09;重建一份&#xff0c;并保存为新的文件或目录 cp 源文件 -------目标地址 在当前文件夹时&#xff1a; cp 源文件 &#xff08;要改名&#xff09;------目的地址&#xff08;可以改名或…

Redis高频面试题

一、Redis有什么好处? 高性能:Redis是一个基于内存的数据存储系统,相比于传统的基于磁盘的数据库系统,它能够提供更高的读写性能。支持丰富的数据类型:Redis支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等,这使得它可以用于多种不同的应用场景。持久化:Re…

4.2-7 运行MR应用:词频统计

文章目录 1. 准备数据文件2. 文件上传到HDFS指定目录2.1 创建HDFS目录2.2 上传文件到HDFS2.3 查看上传的文件 3. 运行词频统计程序的jar包3.1 查看Hadoop自带示例jar包3.2 运行示例jar包里的词频统计 4. 查看词频统计结果5. 在HDFS集群UI界面查看结果文件6. 在YARN集群UI界面查…

基于Python和OpenCV的疲劳检测系统设计与实现

项目运行 需要先安装Python的相关依赖&#xff1a;pymysql&#xff0c;Django3.2.8&#xff0c;pillow 使用pip install 安装 第一步&#xff1a;创建数据库 第二步&#xff1a;执行SQL语句&#xff0c;.sql文件&#xff0c;运行该文件中的SQL语句 第三步&#xff1a;修改源…

【Web开发】什么是Nuxt? 利用Nuxt快速搭建前端项目

Nuxt官网&#xff1a;https://nuxt.com/ 启动一个Nuxt项目 在vscode的项目文件终端运行以下命令&#xff1a; npx nuxilatest init <my-app>npm installnpm run dev然后就启动了一个Nuxt项目 安装Nuxt UI Nuxt UI官网&#xff1a;https://ui.nuxt.com/ npx nuxilates…

【acwing】算法基础课-搜索与图论

目录 1、dfs(深度优先搜索) 1.1 排列数字 1.2 n皇后问题 搜索顺序1 搜索顺序2 2、bfs(广度优先搜索) 2.1 走迷宫 2.2 八数码 3、树与图的存储 4、树与图的遍历 4.1 树的重心 4.2 图中点的层次 5、拓扑排序 6、最短路问题 6.1 朴素Dijkstra算法 6.2 堆优化Dijks…

JAVA基础:集合 (学习笔记)

集合 什么是集合&#xff1f; 一种引用数据类型&#xff0c;可以存储多个数据 为什么要学习集合&#xff1f; 数组的缺点&#xff1a; &#xff08;1&#xff09;空间长度不可以改变。 &#xff08;2&#xff09;没办法获得数组中真实的元素个数。 &#xff08;3&#xff…

江协科技STM32学习- P22 实验-ADC单通道/ADC多通道

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

『 Linux 』网络传输层 - TCP (一)

文章目录 TCP协议TCP数据段格式TCP确认应答机制TCP流量控制 TCP协议 TCP协议(Transmission Control Protocol , 传输控制协议) 是互联网协议套件中的核心协议之一; 主要用于确保数据在网络上的可靠传输,其具有以下特点: 面向连接 在数据传输前,TCP需要在通信双方之间建立一个连…

MySQL的group_concat函数:将分组中的多个值连接成一个字符串的聚合函数

MySQL的group_concat函数&#xff1a;将分组中的多个值连接成一个字符串的聚合函数 主要作用说人话解释举个&#x1f330; 主要作用 可以将同一组内的多个值合并为一个由指定分隔符分隔的字符串&#xff0c;简化数据展示和分析。 说人话解释 group_concat()会计算哪些行属于…

怎么找歌曲的伴奏?找伴奏不再难

在音乐创作、演唱练习或是娱乐活动中&#xff0c;找到一首歌曲的伴奏版本是一个常见的需求。伴奏不仅能够帮助我们更好地理解歌曲的结构和旋律&#xff0c;还能为演唱者提供一个专业的音乐背景。那么&#xff0c;我们该如何有效地找到歌曲的伴奏呢?本文将为你提供几种实用的方…

ubuntu18.04安装xenomai3.1(百分百成功版)

准备工作 1、下载ubuntu18.04.06。 https://releases.ubuntu.com/18.04/ubuntu-18.04.6-desktop-amd64.iso 2、安装虚拟机vmware或virtual machine。 开始安装xenomai 1、在桌面安装一个文件夹,文件夹名字叫xenomai。 2、 在终端输入uname-a 查看自己的内核版本。 3、下…

Linux学习笔记 | sudo命令的基本使用

sudo命令 sudo 命令是 Unix 和 Linux 系统中用于执行需要超级用户权限&#xff08;即 root 权限&#xff09;操作的工具。它允许系统管理员授予某些用户&#xff08;或用户组&#xff09;以 root 或其他指定用户的权限来运行特定命令&#xff0c;而无需知道 root 用户的密码。…

电脑怎么进行全盘加密?

1.使用Windows自带的BitLocker&#xff1a; 打开“控制面板”&#xff0c;选择“系统和安全”&#xff0c;然后点击“BitLocker驱动器加密”。 选择要加密的驱动器&#xff0c;点击“启用BitLocker”。 选择解锁驱动器的方式&#xff0c;通常选择“使用密码解锁驱动器”&…