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

springboot全局异常捕获处理

一、需求

实际项目中,经常抛出各种异常,不能直接抛出异常给前端,这样用户体验相当不好,用户看不懂你的Exception,对于一些sql异常,直接抛到页面上也不安全。所以有没有好的办法解决这些问题呢,当然有了,进行全局异常处理,当正常返回给前端就行了。
例如:
在这里插入图片描述

二、引入依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>

三、创建统一返回结果封装类

import lombok.Data;@Data
public class Response<T> {private int code;private String msg;private T data;public Response() {}public Response(int code) {this.code = code;}public Response(int code, String msg) {this.code = code;this.msg = msg;}public Response(T data) {this.data = data;}public Response(int code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public static Response ok() {Response response = new Response();response.setCode(200);response.setMsg("成功");return response;}public static <T> Response<T> ok(T data) {Response response = new Response();response.setCode(200);response.setMsg("成功");response.setData(data);return response;}public static Response fail(String msg) {Response response = new Response();response.setCode(201);response.setMsg(msg);return response;}public static Response fail(int code, String msg) {Response response = new Response();response.setCode(code);response.setMsg(msg);return response;}}

四、创建状态码常量类

我这里直接用了基本数据类型做状态码,没有写描述,也可以用map的形式创建对象,既有状态码,又有描述。

public class HttpStatusData {/*** 操作成功*/public static final int SUCCESS = 200;/*** 对象创建成功*/public static final int CREATED = 201;/*** 请求已经被接受*/public static final int ACCEPTED = 202;/*** 操作已经执行成功,但是没有返回数据*/public static final int NO_CONTENT = 204;/*** 资源已被移除*/public static final int MOVED_PERM = 301;/*** 重定向*/public static final int SEE_OTHER = 303;/*** 资源没有被修改*/public static final int NOT_MODIFIED = 304;/*** 参数列表错误(缺少,格式不匹配)*/public static final int BAD_REQUEST = 400;/*** 未授权*/public static final int UNAUTHORIZED = 401;/*** 访问受限,授权过期*/public static final int FORBIDDEN = 403;/*** 资源,服务未找到*/public static final int NOT_FOUND = 404;/*** 不允许的http方法*/public static final int BAD_METHOD = 405;/*** 资源冲突,或者资源被锁*/public static final int CONFLICT = 409;/*** 不支持的数据,媒体类型*/public static final int UNSUPPORTED_TYPE = 415;/*** 系统内部错误*/public static final int ERROR = 500;/*** 接口未实现*/public static final int NOT_IMPLEMENTED = 501;
}

五、编写全局异常类

import com.alibaba.fastjson.JSONException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;import java.nio.file.AccessDeniedException;
import java.sql.SQLIntegrityConstraintViolationException;/*** @author HTT*/
@RestControllerAdvice
@Slf4j
public class ExceptionAdviceHandler {/*** 权限校验异常** @param e* @param request* @return*/@ExceptionHandler(AccessDeniedException.class)public Response handleAccessDeniedException(AccessDeniedException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},权限校验失败{}", requestURI, e.getMessage());return Response.fail(HttpStatusData.FORBIDDEN, "没有权限,请联系管理员授权");}/*** 请求方式不支持** @param e* @param request* @return*/@ExceptionHandler(HttpRequestMethodNotSupportedException.class)public Response handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},不支持{}请求", requestURI, e.getMethod());return Response.fail(e.getMessage());}/*** 参数验证失败异常** @param e* @param request* @return*/@ExceptionHandler(MethodArgumentNotValidException.class)public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e,HttpServletRequest request) {String requestURI = request.getRequestURI();String message = e.getBindingResult().getFieldError().getDefaultMessage();log.error("请求地址{},参数验证失败{}", requestURI, e.getObjectName(), e);return Response.fail(message);}/*** 拦截错误SQL异常** @param e* @param request* @return*/@ExceptionHandler(BadSqlGrammarException.class)public Response handleBadSqlGrammarException(BadSqlGrammarException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址'{}',发生数据库异常.", requestURI, e);return Response.fail(HttpStatusData.ERROR, "数据库异常!");}/*** 可以拦截表示违反数据库的完整性约束导致的异常。** @param e* @param request* @return*/@ExceptionHandler(DataIntegrityViolationException.class)public Response handleDataIntegrityViolationException(DataIntegrityViolationException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址'{}',发生数据库异常.", requestURI, e);return Response.fail(HttpStatusData.ERROR, "数据库异常!");}/*** 可以拦截违反数据库的非完整性约束导致的异常,可能也会拦截一些也包括 SQL 语句错误、连接问题、权限问题等各种数据库异常。** @param e* @param request* @return*/@ExceptionHandler(UncategorizedSQLException.class)public Response handleUncategorizedSqlException(UncategorizedSQLException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址'{}',发生数据库异常.", requestURI, e);return Response.fail(HttpStatusData.ERROR, "数据库异常!");}/*** 拦截未知的运行时异常** @param e* @param request* @return*/@ExceptionHandler(RuntimeException.class)public Response handleRuntimeException(RuntimeException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},发生未知运行异常", requestURI, e);return Response.fail(e.getMessage());}/*** 业务自定义异常** @param e* @param request* @return*/@ExceptionHandler(BusinessException.class)public Response handleServiceException(BusinessException e,HttpServletRequest request) {String requestURI = request.getRequestURI();Integer code = 201;log.error("请求地址{},发生业务自定义异常{}", requestURI, e.getMessage(), e);
//        return code != null ? Response.fail(code, e.getMessage()) : Response.fail(e.getMessage());return Response.fail(e.getMessage());}/*** 全局异常** @param e* @param request* @return*/@ExceptionHandler(Exception.class)public Response handleException(Exception e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},发生系统异常", requestURI, e);return Response.fail(e.getMessage());}/*** 发生数据唯一性约束异常** @param e* @param request* @return*/@ExceptionHandler(SQLIntegrityConstraintViolationException.class)public Response sQLIntegrityConstraintViolationException(RuntimeException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},发生数据唯一性约束异常", requestURI, e);return Response.fail(HttpStatusData.ERROR, "数据库异常!,发生数据唯一性约束异常");}/*** 网络请求超时异常** @param e* @param request* @return*/@ExceptionHandler(ResourceAccessException.class)public Response resourceAccessException(RuntimeException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},网络请求超时异常", requestURI, e);return Response.fail(HttpStatusData.ERROR, "网络请求超时异常,调用三方接口异常");}/*** 网络请求超时异常** @param e* @param request* @return*/@ExceptionHandler(JSONException.class)public Response jSONException(RuntimeException e,HttpServletRequest request) {String requestURI = request.getRequestURI();log.error("请求地址{},JSON格式转换异常", requestURI, e);return Response.fail(HttpStatusData.ERROR, "JSON格式转换异常");}}

六、创建自定义异常类

/*** @author: wr* @date: 2020/2/17 18:03*/
public class BusinessException extends RuntimeException {/*** 无参构造函数*/public BusinessException(){super();}/*** 指定异常信息构造函数* @param message*/public BusinessException(String message){super(message);}
}

七、 编写测试类


@RestController
@RequestMapping
public interface EntrepreneurPortraitApi {@PostMapping("/test")public void test(){throw new BusinessException("测试全局异常是否生效");}}   

八、测试结果

启动项目,浏览器访问 http://localhost:8888/test

{"code": 201,"msg": "失败","data": "测试全局异常是否生效"
}

相关文章:

springboot全局异常捕获处理

一、需求 实际项目中&#xff0c;经常抛出各种异常&#xff0c;不能直接抛出异常给前端&#xff0c;这样用户体验相当不好&#xff0c;用户看不懂你的Exception,对于一些sql异常&#xff0c;直接抛到页面上也不安全。所以有没有好的办法解决这些问题呢&#xff0c;当然有了&am…...

Flask(1): 在windows系统上部署项目1

1 前言 学习python也有段时间了&#xff0c;最近一个小项目要部署&#xff0c;正好把过程写下来。 在程序的结构上我选择了w/s模式&#xff0c;相比于c/s模式&#xff0c;无需考虑客户端的升级&#xff1b;框架我选择了flask&#xff0c;就是冲着轻量级去的&#xff0c;就是插件…...

【文献阅读】EndoNet A Deep Architecture for Recognition Tasks on Laparoscopic Videos

关于数据集的整理 Cholec80 胆囊切除手术视频数据集介绍 https://zhuanlan.zhihu.com/p/700024359 数据集信息 Cholec80 数据集 是一个针对内窥镜引导 下的胆囊切除手术视频流程识别数据集。数据集提供了每段视频中总共7种手术动作及总共7种手术工具的标注&#xff0c;标…...

基于springboot的个人财务管理系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…...

Linux系统编程---孤儿进程与僵尸进程

1、前言 在上一篇博客文章已经对Linux系统编程内容进行了较为详细的梳理&#xff0c;本文将在上一篇的基础上&#xff0c;继续梳理Linux系统编程中关于孤儿进程和僵尸进程的知识脉络。如有疑问的博客朋友可以通过下面的博文链接进行参考学习。 Linux系统编程---多进程-CSDN博客…...

简单使用MCP

简单使用MCP 1 简介 模型上下文协议&#xff08;Model Context Protocol&#xff0c;MCP&#xff09;是由Anthropic&#xff08;产品是Claude&#xff09;推出的开放协议&#xff0c;它规范了应用程序如何向LLM提供上下文。MCP可帮助你在LLM之上构建代理和复杂的工作流。 从…...

Semaphore的核心机制

在 Java 中&#xff0c;Semaphore 通过 许可计数器 和 同步队列 的机制实现并发线程数的限制。以下是其核心实现原理和步骤的详细分析&#xff1a; 一、核心机制 许可计数器&#xff08;Permits&#xff09; • 初始化时指定的许可数&#xff08;如 new Semaphore(3)&#xff0…...

计算机视觉与深度学习 | RNN原理,公式,代码,应用

RNN(循环神经网络)详解 一、原理 RNN(Recurrent Neural Network)是一种处理序列数据的神经网络,其核心思想是通过循环连接(隐藏状态)捕捉序列中的时序信息。每个时间步的隐藏状态 ( h_t ) 不仅依赖当前输入 ( x_t ),还依赖前一时间步的隐藏状态 ( h_{t-1} ),从而实现…...

Keil MDK 编译问题:last line of file ends without a newline

问题与处理策略 问题描述 ..\..\User\main.c(38): warning: #1-D: last line of file ends without a newline} ..\..\User\main.c: 1 warning, 0 errors问题原因 这是文件末尾缺少换行符警告 处理策略 在文件&#xff08;main.c&#xff09;的最后一行按回车键添加一个空…...

MySQL:9.表的内连和外连

9.表的内连和外连 表的连接分为内连和外连 9.1 内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;之前查询都是内连 接&#xff0c;也是在开发过程中使用的最多的连接查询。 语法&#xff1a; select 字段 from 表1 inner join 表2 on 连接…...

C++栈操作集合

数组 #include <bits/stdc.h> using namespace std;class sss{ private:int a[1000];int curr -1; public:void push(int);void pop();int top();bool empyt();int size(); };int main() {sss n;while(true){int a;cout<<"1.添加\n2.删除-\n3.显示栈顶\n4.储…...

在阿里云和树莓派上编写一个守护进程程序

目录 一、阿里云邮件守护进程 1. 安装必要库 2. 创建邮件发送脚本 mail_daemon.py 3. 设置后台运行 二、树莓派串口守护进程 1. 启用树莓派串口 2. 安装依赖库 3. 创建串口输出脚本 serial_daemon.py 4. 设置开机自启 5. 使用串口助手接收 一、阿里云邮件守护进程 1.…...

每日一题——最小测试用例集覆盖问题

最小测试用例集覆盖问题&#xff08;C语言实现&#xff09; 问题描述 假设我们有一系列测试用例&#xff0c;每个测试用例会覆盖若干个代码模块。 我们使用一个二维数组来表示这些测试用例的覆盖情况&#xff1a; 如果某个测试用例 i 能覆盖代码模块 j&#xff0c;则数组中…...

LangChain 单智能体模式示例【纯代码】

# LangChain 单智能体模式示例import os from typing import Anyfrom langchain.agents import AgentType, initialize_agent, Tool from langchain_openai import ChatOpenAI from langchain.tools import BaseTool from langchain_experimental.tools.python.tool import Pyt…...

基于前端技术的QR码API开发实战:从原理到部署

前言 QR码&#xff08;Quick Response Code&#xff09;是一种二维码&#xff0c;于1994年开发。它能快速存储和识别数据&#xff0c;包含黑白方块图案&#xff0c;常用于扫描获取信息。QR码具有高容错性和快速读取的优点&#xff0c;广泛应用于广告、支付、物流等领域。通过扫…...

RenderStage::drawInner

文章目录 RenderStage::drawInnerOSG渲染后台关系图OSG的渲染流程RenderBin::draw(renderInfo,previous)RenderBin::drawImplementationRenderLeaf::renderosg::State::apply(const StateSet*)Drawable::draw(RenderInfo& renderInfo)Drawable::drawInner(RenderInfo& …...

C++初阶-类和对象(中)

目录 1.类的默认成员函数 2.构造函数&#xff08;难度较高&#xff09; ​编辑 ​编辑 ​编辑 3.析构函数 4.拷贝构造函数 5.赋值运算符重载 5.1运算符重载 5.2赋值运算符重载 6.取地址运算符重载 6.1const成员函数 6.2取地址运算符重载 7.总结 1.类的默认成员函数…...

智谱开源新一代GLM模型,全面布局AI智能体生态

2024年4月15日&#xff0c;智谱在中关村论坛上正式发布了全球首个集深度研究与实际操作能力于一体的AI智能体——AutoGLM沉思。这一革命性技术的发布标志着智谱在AGI&#xff08;通用人工智能&#xff09;领域的又一次重要突破。智谱的最新模型不仅推动了AI智能体技术的升级&am…...

Vue3中provide和inject的用法示例

在 Vue3 中&#xff0c;provide 和 inject 用于实现跨层级组件通信。以下是一个简单的示例&#xff1a; 1. 父组件 (祖先组件) - 提供数据 javascript 复制 // ParentComponent.vue import { provide, ref, reactive } from vue;export default {setup() {// 提供静态数据p…...

分治-快排-75.颜色分类-力扣(LeetCode)

一、题目解析 给定一个数组将其元素按照0&#xff0c;1,&#xff0c;2三段式排序&#xff0c;并且在原地进行排序。 二、算法原理 解法&#xff1a;三指针 用cur遍历数组&#xff0c;left记录0的最左侧&#xff0c;right记录2的最右侧。 left初始值为-1&#xff0c;right的初…...

铅酸电池充电器方案EG1253+EG4321

参考&#xff1a; 基于EG1253EG4321铅酸电池(48V20AH)三段式充电器 屹晶微高性价比的电瓶车充电器方案——EG1253 电瓶电压 48V电瓶锂电池&#xff0c;其充满约为55V~56V&#xff0c;因此充电器输出电压为55V~56V&#xff1b; 若是48V铅酸电池&#xff0c;标称电压为48V&…...

Spring Boot 实现 Excel 导出功能(支持前端下载 + 文件流)

&#x1f9e0; 一、为什么用 EasyExcel&#xff1f; 在 Java 开发中&#xff0c;操作 Excel 的框架主要有&#xff1a; Apache POI&#xff08;经典但慢、内存占用大&#xff09; JXL&#xff08;老旧不维护&#xff09; Alibaba EasyExcel&#xff08;阿里出品&#xff0c;…...

vue 中formatter

:formatter 是前端表格组件&#xff08;如 Element UI、Vxe-Table 等&#xff09;中用于 ​​自定义单元格内容显示格式​​ 的属性。它的核心作用是&#xff1a;将后端返回的原始数据&#xff08;如编码、状态值等&#xff09;转换为更友好、更易读的文本。 这段代码 :forma…...

协程?协程与线程的区别?Java是否支持协程?

一、前言 协程&#xff08;Coroutine&#xff09; 是一种轻量级的并发编程模型&#xff0c;允许在单线程内通过协作式多任务调度实现并发。由用户代码显式控制&#xff08;用户态调度而非操作系统内核调度&#xff09;&#xff0c;避免了线程上下文切换的开销&#xff0c;适合…...

jsch(shell终端Java版)

学习笔记 Java SSH库使用简介&#xff1a;Apache sshd和JSch&#xff08;Java Secure Channel&#xff09; github - fork of the popular jsch library JSch学习笔记 web-shell - gitee代码 - 纯Java实现一个web shell登录Linux远程主机&#xff0c;技术选型 SpringBoot …...

Muduo网络库实现 [十六] - HttpServer模块

目录 设计思路 类的设计 模块的实现 公有接口 私有接口 疑问点 设计思路 本模块就是设计一个HttpServer模块&#xff0c;提供便携的搭建http协议的服务器的方法。那么这个模块需要如何设计呢&#xff1f; 这还需要从Http请求说起。 首先从http请求的请求行开始分析&…...

关于进程状态

目录 进程的各种状态 运行状态 阻塞状态 挂起状态 linux中的进程状态、 进程状态查看 S状态&#xff08;浅睡眠&#xff09; t 状态&#xff08;追踪状态&#xff09; T状态&#xff08;暂停状态&#xff09; ​编辑 kill命令手册 D状态&#xff08;深度睡眠&#…...

【MySQL】Read view存储的机制,记录可见分析

read view核心组成 1.1 事务id相关 creator_trx_id: 创建该read view的事务id 每开启一个事务都会生成一个 ReadView&#xff0c;而 creator_trx_id 就是这个开启的事务的 id。 m_ids: 创建read view时系统的活跃事务&#xff08;未提交的事务&#xff09;id集合 当前有哪些事…...

SQL注入 01

0x01 用户、脚本、数据库之间的关系 首先客户端发出了ID36的请求&#xff0c;脚本引擎收到后将ID36的请求先代入脚本的sql查询语句Select * from A where id 36 &#xff0c; 然后将此代入到数据库中进行查询&#xff0c;查到后将返回查询到的所有记录给脚本引擎&#xff0c;接…...

学习笔记:黑马程序员JavaWeb开发教程(2025.3.24)

11.2 案例-文件上传-简介 火狐浏览器可以看到文件上传传递的底层数据&#xff0c;而chrome对这一块数据进行了包装 在输出日志代码处打了一个断点&#xff0c;看服务端接收到的数据&#xff0c;在上传文件的保存地址中&#xff0c;可以看到&#xff0c;有三个临时文件&…...