当前位置: 首页 > news >正文

SpringBoot的全局异常拦截

在 Spring Boot 中,可以通过使用 @ControllerAdvice 注解和 @ExceptionHandler 注解来实现全局异常拦截。

@RestControllerAdvice

@RestControllerAdvice 是 Spring Framework 提供的注解,用于定义全局异常处理类,并且结合 @ExceptionHandler 注解来处理异常。与 @ControllerAdvice 不同的是,@RestControllerAdvice 默认情况下会将返回值转换为 JSON 格式。

@RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法}

@ResponseStatus(...)

@ResponseStatus(HttpStatus.BAD_REQUEST) 是一个注解,用于在异常处理方法上指定特定的HTTP状态码。当该异常被抛出时,将返回指定的HTTP状态码给客户端。

@RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法/*** 缺少请求体异常处理器* @param e 缺少请求体异常 使用get方式请求 而实体使用@RequestBody修饰*/@ResponseStatus(HttpStatus.BAD_REQUEST)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',请求体缺失'{}'", requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}
}

@ExceptionHandler(...)

@ExceptionHandler(...) 是一个异常处理注解,用于捕获请求的异常。当客户端发送的请求消息无法被框架正确解析时,将抛出该异常并调用对应的异常处理方法。

@RestControllerAdvice
public class GlobalExceptionHandler {//.....拦截异常方法/*** 缺少请求体异常处理器* @param e 缺少请求体异常 使用get方式请求 而实体使用@RequestBody修饰*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(HttpMessageNotReadableException.class)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',请求体缺失'{}'", requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}
}

RuntimeException

RuntimeException 是 Java 提供的一个运行时异常类。与受检查异常不同,运行时异常不需要在方法声明中显式地声明或捕获,并且在运行时抛出时也不需要强制捕获或处理。所以我们可以在全局异常捕获中去捕获这个异常

public class BusinessException extends RuntimeException {private int code;//使用枚举构造public BusinessException(HttpCodeEnum httpCodeEnum){super(httpCodeEnum.getMsg());this.code=httpCodeEnum.getCode();}//使用自定义消息体public BusinessException(HttpCodeEnum httpCodeEnum, String msg){super(msg);this.code=httpCodeEnum.getCode();}//根据异常构造public BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg){super(msg);this.code=httpCodeEnum.getCode();}}

 上述代码定义了一个名为 BusinessException 的自定义异常类,它继承自 RuntimeException

这个自定义异常类具有以下特点:

  1. 包含了一个 code 字段,用于表示异常的错误码。
  2. 提供了不同的构造方法,以方便在抛出异常时指定错误码和错误信息。
  • BusinessException(HttpCodeEnum httpCodeEnum) 构造方法使用枚举类型 HttpCodeEnum 来设置异常的错误码和错误信息。
  • BusinessException(HttpCodeEnum httpCodeEnum, String msg) 构造方法使用自定义的错误信息来设置异常的错误码和错误信息。
  • BusinessException(HttpCodeEnum httpCodeEnum, Throwable msg) 构造方法使用其他异常的实例来设置异常的错误码,并可选地提供通过 Throwable 获取的错误信息。

HttpCodeEnum 枚举类

我们还需要一个类表示 HTTP 响应的状态码和对应的消息 ,以下为基本的举例查考。

public enum HttpCodeEnum {// 成功SUCCESS(200, "操作成功"),// 登录NEED_LOGIN(401, "需要登录后操作"),NO_OPERATOR_AUTH(403, "无权限操作"),SYSTEM_ERROR(500, "出现错误"),USERNAME_EXIST(501, "用户名已存在"),PHONENUMBER_EXIST(502, "手机号已存在"), EMAIL_EXIST(503, "邮箱已存在"),REQUIRE_USERNAME(504, "必需填写用户名"),CONTENT_NOT_NULL(506, "评论内容不能为空"),FILE_TYPE_ERROR(507, "文件类型错误"),USERNAME_NOT_NULL(508, "用户名不能为空"),NICKNAME_NOT_NULL(509, "昵称不能为空"),PASSWORD_NOT_NULL(510, "密码不能为空"),EMAIL_NOT_NULL(511, "邮箱不能为空"),NICKNAME_EXIST(512, "昵称已存在"),LOGIN_ERROR(505, "用户名或密码错误");int code;String msg;HttpCodeEnum(int code, String errorMessage) {this.code = code;this.msg = errorMessage;}public int getCode() {return code;}public String getMsg() {return msg;}
}

上述代码定义了一个 HttpCodeEnum 枚举类,用于表示 HTTP 响应的状态码和对应的消息。

这个枚举类具有以下特点:

  1. 包含一组枚举常量,每个常量代表一个 HTTP 响应状态。
  2. 每个常量都有一个整型的 code 和一个字符串类型的 msg,分别表示状态码和对应的消息。
  3. 提供了相应的构造方法、获取 code 和 msg 的方法。

ResponseResult类

该类的主要作用是封装接口返回的数据,统一格式化输出,方便前端调用和展示。

import lombok.Data;import java.io.Serializable;
@Data
public class ResponseResult<T> implements Serializable {private Boolean success;private Integer code;private String msg;private T data;public ResponseResult() {this.success=true;this.code = HttpCodeEnum.SUCCESS.getCode();this.msg = HttpCodeEnum.SUCCESS.getMsg();}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}public ResponseResult(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public ResponseResult(Integer code, String msg) {this.code = code;this.msg = msg;}public static ResponseResult errorResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.error(code, msg);}public static ResponseResult okResult() {ResponseResult result = new ResponseResult();return result;}public static ResponseResult okResult(int code, String msg) {ResponseResult result = new ResponseResult();return result.ok(code, null, msg);}public static ResponseResult setHttpCodeEnum(HttpCodeEnum enums) {return okResult(enums.getCode(), enums.getMsg());}public ResponseResult<?> error(Integer code, String msg) {this.success=false;this.code = code;this.msg = msg;return this;}public ResponseResult<?> ok(Integer code, T data) {this.success=true;this.code = code;this.data = data;return this;}public ResponseResult<?> ok(Integer code, T data, String msg) {this.success=true;this.code = code;this.data = data;this.msg = msg;return this;}public ResponseResult<?> ok(T data) {this.success=true;this.data = data;return this;}}

全局异常捕获

全局异常捕获是一种处理应用程序中未处理的异常的机制,它可以统一处理应用程序中的异常,避免异常导致程序崩溃或向用户显示不友好的错误信息。我们可以通过上述的解释去捕获异常,定义code类型枚举返回ResponseResult给前端

import com.example.demo.util.HttpCodeEnum;
import com.example.demo.util.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.servlet.http.HttpServletRequest;
import java.util.List;@RestControllerAdvice
public class GlobalExceptionHandler {private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);@Autowiredprivate HttpServletRequest httpServletRequest;private final String sysError="系统出错";/*** 缺少请求体异常处理器* @param e 缺少请求体异常 使用get方式请求 而实体使用@RequestBody修饰*/@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler(HttpMessageNotReadableException.class)public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',请求体缺失'{}'", requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}/** @Description:  捕获请求方法异常,比如post接口使用了get*/@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public ResponseResult methodNotAllowedHandler(HttpRequestMethodNotSupportedException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',请求方法不被允许'{}'", requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}// get请求的对象参数校验异常@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler({MissingServletRequestParameterException.class})public ResponseResult bindExceptionHandler(MissingServletRequestParameterException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',get方式请求参数'{}'必传", requestURI, e.getParameterName());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), sysError);}// post请求的对象参数校验异常@ResponseStatus(HttpStatus.BAD_REQUEST)@ExceptionHandler({MethodArgumentNotValidException.class})public ResponseResult methodArgumentNotValidHandler(MethodArgumentNotValidException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',post方式请求参数异常'{}'", requestURI, e.getMessage());List<ObjectError> allErrors = e.getBindingResult().getAllErrors();return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), getValidExceptionMsg(allErrors));}// 业务类异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(BusinessException.class)public ResponseResult businessExceptionHandler(BusinessException e) {String requestURI = httpServletRequest.getRequestURI();System.out.println(e);log.error("请求地址'{}',捕获业务类异常'{}'", requestURI,e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}// 运行时异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(RuntimeException.class)public ResponseResult runtimeExceptionHandler(RuntimeException e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',捕获运行时异常'{}'", requestURI, e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}// 系统级别异常@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)@ExceptionHandler(Throwable.class)public ResponseResult throwableExceptionHandler(Throwable e) {String requestURI = httpServletRequest.getRequestURI();log.error("请求地址'{}',捕获系统级别异常'{}'", requestURI,e.getMessage());return ResponseResult.errorResult(HttpCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());}private String getValidExceptionMsg(List<ObjectError> errors) {if(!CollectionUtils.isEmpty(errors)){StringBuilder sb = new StringBuilder();errors.forEach(error -> {if (error instanceof FieldError) {sb.append(((FieldError)error).getField()).append(":");}sb.append(error.getDefaultMessage()).append(";");});String msg = sb.toString();msg = msg.substring(0, msg.length() -1);return msg;}return null;}}

测试

入参不正确时

发出请求

返回结果

 捕获异常

运行时错误

 发起请求

返回结果

 捕获异常

业务异常

 发送请求

返回结果

捕获异常

相关文章:

SpringBoot的全局异常拦截

在 Spring Boot 中&#xff0c;可以通过使用 ControllerAdvice 注解和 ExceptionHandler 注解来实现全局异常拦截。 RestControllerAdvice RestControllerAdvice 是 Spring Framework 提供的注解&#xff0c;用于定义全局异常处理类&#xff0c;并且结合 ExceptionHandler 注…...

『力扣每日一题11』:转换成小写字母

一、题目 给你一个字符串 s &#xff0c;将该字符串中的大写字母转换成相同的小写字母&#xff0c;返回新的字符串。 示例 1&#xff1a; 输入&#xff1a;s "Hello" 输出&#xff1a;"hello"示例 2&#xff1a; 输入&#xff1a;s "here" 输…...

复习Day07:链表part03:21. 合并两个有序链表、2. 两数相加

之前的blog链接&#xff1a;https://blog.csdn.net/weixin_43303286/article/details/131700482?spm1001.2014.3001.5501 我用的方法是在leetcode再过一遍例题&#xff0c;明显会的就复制粘贴&#xff0c;之前没写出来就重写&#xff0c;然后从拓展题目中找题目来写。辅以Lab…...

Ubuntu中启动HDFS后没有NameNode解决办法

关闭进程&#xff1a; stop-dfs.sh 格式化&#xff1a; hadoop namenode -format 出现报错信息&#xff1a; 23/10/03 22:27:04 WARN fs.FileUtil: Failed to delete file or dir [/usr/data/hadoop/tmp/dfs/name/current/fsimage_0000000000000000000.md5]: it still exi…...

AWS-Lambda之导入自定义包-pip包

参考文档&#xff1a; https://repost.aws/zh-Hans/knowledge-center/lambda-import-module-error-python https://blog.csdn.net/fxtxz2/article/details/112035627 简单来说,以 " alibabacloud_dyvmsapi20170525 " 包为例 ## 创建临时目录 mkdir /tmp cd ./tmp …...

MAC 如何解决GitHub下载速度慢的问题

说在前面 解决github下载速度慢的方法很多&#xff0c;本文主要介绍通过Git镜像的方式解决下载慢的问题。 主要步骤有&#xff1a;1、找到gitconfig文件&#xff0c; 2、通过git命令查看当前生效的config 配置 3、使用git config命令编辑并添加国内镜像源 1、gitconfig 文件在…...

Redis与分布式-哨兵模式

接上文 Redis与分布式-主从复制 1.哨兵模式 启动一个哨兵&#xff0c;只需要修改配置文件即可&#xff0c; sentinel monitor lbwnb 1247.0.0.1 6001 1先将所有服务关闭&#xff0c;然后修改配置文件&#xff0c;redis Master&#xff0c;redis Slave&#xff0c;redis Slave…...

创建型设计模式 原型模式 建造者模式 创建者模式对比

创建型设计模式 单例 工厂模式 看这一篇就够了_软工菜鸡的博客-CSDN博客 4.3 原型模式 4.3.1 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 4.3.2 结构 原型模式包含如下角色&#xff1a; 抽象原型类&#xff1a;规定了…...

HTML详细基础(二)文件路径

目录 一.相对路径 二.绝对路径 三.超链接标签 四.锚点链接 首先&#xff0c;扩展一些HTML执行的原理&#xff1a; htmL(hypertext markup Language) 是一种规范&#xff08;或者说是一种标准&#xff09;&#xff0c;它通过标记符&#xff08;tag&#xff09;来标记要显示…...

大数据-玩转数据-Flink 海量数据实时去重

一、海量数据实时去重说明 借助redis的Set&#xff0c;需要频繁连接Redis&#xff0c;如果数据量过大, 对redis的内存也是一种压力&#xff1b;使用Flink的MapState&#xff0c;如果数据量过大, 状态后端最好选择 RocksDBStateBackend&#xff1b; 使用布隆过滤器&#xff0c;…...

1.在vsCode上创建Hello,World

(1).编译器的安装配置 使用vsCode进行编写c语言,首先需要安装gcc编译器,可以自己去寻找资料或者gcc官网进行下载. 下载好后,将文件夹放入到自己指定的目录后,配置系统环境变量,将path指向编译器的bin目录 进入bin目录打开cmd,输入gcc -v,然后就会成功输出信息. (2).vsCode配…...

XrayGLM - 医学大模型

文章目录 关于 XrayGLM研究背景VisualGLM-6B 关于 XrayGLM XrayGLM: 首个会看胸部X光片的中文多模态医学大模型 | The first Chinese Medical Multimodal Model that Chest Radiographs Summarization. 基于VisualGLM-6B 微调 github : https://github.com/WangRongsheng/Xra…...

Hive 常见数据倾斜场景及解决方案(Map\Join\Reduce端)

目录 MapReduce流程简述a) Map倾斜b) Join倾斜c) Reduce倾斜 首先回顾一下MapReduce的流程 MapReduce流程简述 输入分片&#xff1a; MapReduce 作业开始时&#xff0c;输入数据被分割成多个分片&#xff0c;每个分片大小一般在 16MB 到 128MB 之间。这些分片会被分配给不同的…...

C++中的四种强制类型转换符详解

前 言 C 既支持 C 风格的类型转换&#xff0c;又有自己风格的类型转换。C 风格的转换格式很简单&#xff0c;但是有不少缺点&#xff1a; 转换太过随意&#xff0c;可以在任意类型之间转换。你可以把一个指向 const 对象的指针转换成指向非 const 对象的指针&#xff0c;把一…...

Windows电脑多开器的优缺点对比

Windows电脑多开器是一种能够让用户同时运行多个应用程序、游戏或者网页的软件工具。它的作用在于让用户能够更加高效地工作、学习或者娱乐。但是&#xff0c;这种软件也存在一些优劣势的对比。 优点&#xff1a; 提升工作效率。多开器可以让用户同时打开多个应用程序或者网页…...

Java笔记六(面向对象:类与对象)

面向对象编程的本质&#xff1a;以类的方式组织代码&#xff0c;以对象的组织&#xff08;封装&#xff09;数据 抽象 三大特征&#xff1a;封装 继承 多态 从认识角度考虑是先有对象后有类。对象&#xff0c;是具体的事物。类&#xff0c;是抽象的&#xff0c;是对对象的抽…...

Git使用【中】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析3 目录 &#x1f449;&#x1f3fb;分支管理分支概念git branch&#xff08;查看/删除分…...

Greenplum7一键安装

2023年9月底&#xff0c;Greenplum 发布了7.0.0版本&#xff0c;并于2023年10月03日开放了安装部署说明文档&#xff0c;现在快速尝鲜版的docker一键部署方式如下&#xff1a; mkdir /data/gpdb docker run -d --name greenplum -p 15432:5432 -v /data/gpdb:/data inrgihc/g…...

Springboo整合Sentinel

Springboo整合Sentinel 1.启动Sentinel java -jar sentinel-dashboard-1.8.6.jar2.访问localhost:8080到Sentinel管理界面(默认账号和密码都是sentinel) 3.引入依赖(注意版本对应) <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spr…...

python爬取csdn个人首页中的所有封面

#爬取csdn个人首页中的所有封面 import requests import json import reurlhttps://blog.csdn.net/community/home-api/v1/get-business-list? headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safar…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...