SpringMVC:统一异常处理(11)
统一异常处理
- 1. 说明
- 2. 问题描述
- 3. 异常处理器使用
- 3.1 创建异常处理器类
- 3.2 让程序抛出异常
- 3.3 测试
- 4. 项目异常处理方案
- 4.1 异常分类
- 4.2 异常解决方案
- 4.3 异常解决方案的具体实现
- 4.4 测试
- 5. 总结
1. 说明
\quad本篇文章是在文章SpringMVC:SSM整合(SpringMVC+Spring+Mybatis)案例(9)和SpringMVC:统一封装结果(10)的基础上进行讲解的,建议在读本篇文章之前建议预先了解这两篇文章。
2. 问题描述
前端接收到这个信息后和之前我们约定的格式(统一返回Result类)不一致,这个问题该如何解决?
在解决问题之前,我们先来看下异常的种类及出现异常的原因:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
- 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
在开发的任何一个位置都有可能出现异常,而且这些异常是不能避免的。所以我们就得将异常进行处理。
-
各个层级均出现异常,异常处理代码书写在哪一层?
所有的异常均抛出到表现层进行处理
-
异常的种类很多,表现层如何将所有的异常都处理到呢?
异常分类
-
表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决?
AOP
3. 异常处理器使用
3.1 创建异常处理器类
在controller层下创建异常处理器类:
// @RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
// @ControllerAdvice用于标识当前类为普通风格对应的异常处理器
@RestControllerAdvice
public class ProjectExceptionAdvice {// 除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常@ExceptionHandler(Exception.class)public void doException(Exception ex){System.out.println("出现异常。")}
}
3.2 让程序抛出异常
修改BookController
的getById方法,添加int i = 1/0
.
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {int i = 1/0;Book book = bookService.getById(id);Integer code = book != null ? Code.GET_OK : Code.GET_ERR;String msg = book != null ? "" : "数据查询失败,请重试!";return new Result(code,book,msg);
}
3.3 测试
说明异常已经被拦截并执行了doException
方法。
4. 项目异常处理方案
4.1 异常分类
因为异常的种类有很多,如果每一个异常都对应一个@ExceptionHandler,那得写多少个方法来处理各自的异常,所以我们在处理异常之前,需要对异常进行一个分类:
-
业务异常(BusinessException)
-
规范的用户行为产生的异常
- 用户在页面输入内容的时候未按照指定格式进行数据填写,如在年龄框输入的是字符串
-
不规范的用户行为操作产生的异常
- 如用户故意传递错误数据
-
-
系统异常(SystemException)
- 项目运行过程中可预计但无法避免的异常
- 比如数据库或服务器宕机
- 项目运行过程中可预计但无法避免的异常
-
其他异常(Exception)
- 编程人员未预期到的异常,如:用到的文件不存在
将异常分类以后,针对不同类型的异常,要提供具体的解决方案:
4.2 异常解决方案
- 业务异常(BusinessException)
- 发送对应消息传递给用户,提醒规范操作
- 大家常见的就是提示用户名已存在或密码格式不正确等
- 发送对应消息传递给用户,提醒规范操作
- 系统异常(SystemException)
- 发送固定消息传递给用户,安抚用户
- 系统繁忙,请稍后再试
- 系统正在维护升级,请稍后再试
- 系统出问题,请联系系统管理员等
- 发送特定消息给运维人员,提醒维护
- 可以发送短信、邮箱或者是公司内部通信软件
- 记录日志
- 发消息和记录日志对用户来说是不可见的,属于后台程序
- 发送固定消息传递给用户,安抚用户
- 其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护(纳入预期范围内)
- 一般是程序没有考虑全,比如未做非空校验等
- 记录日志
4.3 异常解决方案的具体实现
思路:
-
先通过自定义异常,完成BusinessException和SystemException的定义
-
将其他异常包装成自定义异常类型
-
在异常处理器类中对不同的异常进行处理
步骤一:定义两个异常处理器
自定义系统异常处理器,用于封装异常信息,对异常进行分类:
public class SystemException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public SystemException(Integer code, String message) {super(message);this.code = code;}public SystemException(Integer code, String message, Throwable cause) {super(message, cause);this.code = code;}}
自定义业务异常处理器,用于封装异常信息,对异常进行分类:
public class BusinessException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public BusinessException(Integer code, String message) {super(message);this.code = code;}public BusinessException(Integer code, String message, Throwable cause) {super(message, cause);this.code = code;}
}
说明:
- 让自定义异常类继承
RuntimeException
的好处是,后期在抛出这两个异常的时候,就不用在try…catch…或throws了 - 自定义异常类中添加
code
属性的原因是为了更好的区分异常是来自哪个业务的
步骤2:将其他异常包成自定义异常
public Book getById(Integer id) {//模拟业务异常,包装成自定义异常if(id == 15){throw new BusinessException(Code.BUSINESS_ERR,"业务层出现异常");}//模拟系统异常,将可能出现的异常进行包装,转换成自定义异常try{int i = 1/0;}catch (Exception e){throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请重试!",e);}return bookDao.getById(id);
}
状态码Code类:
// 状态码
public class Code {public static final Integer SAVE_OK = 20011;public static final Integer SAVE_ERR = 20010;public static final Integer DELETE_OK = 20021;public static final Integer DELETE_ERR = 20020;public static final Integer UPDATE_OK = 20031;public static final Integer UPDATE_ERR = 20030;public static final Integer GET_OK = 20041;public static final Integer GET_ERR = 20040;public static final Integer SYSTEM_ERR = 50001;public static final Integer SYSTEM_TIMEOUT_ERR = 60001;public static final Integer SYSTEM_UNKNOW_ERR = 70001;public static final Integer BUSINESS_ERR = 80001;}
步骤3:处理器类中处理自定义异常
package com.itheima.controller;import com.itheima.exception.BusinessException;
import com.itheima.exception.SystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** @Author Mr.Lu* @Date 2023/2/11 9:36* @ClassName ProjectExceptionAdvice* @Version 1.0*/
// @RestControllerAdvice用于标识当前类为REST风格对应的异常处理器
@RestControllerAdvice
public class ProjectExceptionAdvice {@ExceptionHandler(BusinessException.class)public Result doBusinessException(BusinessException ex){return new Result(ex.getCode(), null, ex.getMessage());}@ExceptionHandler(SystemException.class)public Result doSystemException(SystemException ex){// 记录日志// 发送消息给运维// 发送邮件给开发人员,ex对象发送给开发人员return new Result(ex.getCode(), null, ex.getMessage());}// 除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常@ExceptionHandler(Exception.class)public Result doOtherException(Exception ex){//记录日志//发送消息给运维//发送邮件给开发人员,ex对象发送给开发人员return new Result(8888,null, "系统繁忙,请稍后再试!");}
}
4.4 测试
根据ID查询,如果传入的参数为15,会报BusinessException
如果传入的是其他参数,会报SystemException
5. 总结
项目中的异常处理方式:
相关文章:

SpringMVC:统一异常处理(11)
统一异常处理1. 说明2. 问题描述3. 异常处理器使用3.1 创建异常处理器类3.2 让程序抛出异常3.3 测试4. 项目异常处理方案4.1 异常分类4.2 异常解决方案4.3 异常解决方案的具体实现4.4 测试5. 总结1. 说明 \quad本篇文章是在文章SpringMVC:SSM整合(Spring…...

SpringBoot的配置与使用
SpringBoot简介 我们的Spring是包含了众多工具的IoC容器,而SpringBoot则是Spring的加强版,可以更加方便快捷的使用 如果Spring是手动挡的车,那么SpringBoot就是自动挡的车,让我们的驾驶体验变得更好 SpringBoot具有一下几种特征…...

【Python】tkinter messagebox练习笔记
我一好友在朋友圈看到人家用代码花式秀恩爱,让我也做一个,我就用我学习半年python的功力,做了这一个东西。🙏窗口主页面(图一)为了让我这个盆友有颜面,特意做了一个问答问他帅不帅,以…...
2022年12月电子学会Python等级考试试卷(五级)答案解析
青少年软件编程(Python)等级考试试卷(五级) 分数:100 题数:38 一、单选题(共25题,共50分) 1. 下面哪个语句正确定义了元组类型数据tuple1?( ) A. t…...

计算机网络自定向下 -- 浅谈可靠性之rdt协议
可靠性数据传输原理 可靠指数据在传输过程中不错,不丢,不乱 运输层要为应用层提供一种服务:数据可以通过一条可靠的信道进行传输,在该信道中传输的数据不会受到损坏或者丢失, 实现这种服务的是可靠数据传输协议。 要实现这种服…...

制造业升级转型:制造业上市公司-智能制造词频统计数据集
发展智能制造,关乎中国制造业转型升级的成效。基于中国制造业上市公司年报,通过文本数据挖掘,提取关键词反映企业对智能制造的关切焦点,进而运用词频及共词网络分析,洞察中国智能制造的发展态势。 研究发现࿰…...
HTML 开发工具整理
一、千乐微云团队推荐的HTML开发工具Visual Studio Code 简称VS Code (第一推荐)Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持几乎所有主流的开发语言的语法高亮、智能代码补全、自定义快捷键、括号…...
介绍ACE C++网络通信框架
很久以前笔者也不太熟悉ACE C网络通信框架,偶然的机会逐渐接触后,发现它的优良! 总结来看它的有点如下 非常适合后台无界面网络通信的系统编程 适合小型化核心网使用;但值得注意,如果您需要的是web领域技术栈&…...

【Mac OS】JDK 多版本切换配置
前言 由于不同的项目可能需要使用的 JDK 版本不一样,所以在系统中配置多个 JDK 版本,并且能随时切换,是一个必要的配置。 查看已安装的 JDK 版本 /usr/libexec/java_home -V框框1是执行的命令 框框2是当前系统下所有的 JDK 版本 框框3是当…...

RabbitMQ-Exchanges交换机
一、介绍 RabbitMQ消息传递模型的核心思想是:生产者生产的消息从不会直接发送到队列。实际上,通常生产者甚至不知道这些消息传递到了哪些队列中。相反,生产者只能将消息发送到交换机,交换机工作的内容非常简单,一方…...

离散数学 课时二 命题逻辑等值演算
等值式(等值联结词) 1、设A、B是两个命题公式,若A、B构成的等价式 A等价于B 为重言式,那么称A与B是等值的 2、常用等值式: 注意: 1 双否定律 2 幂等律 3 交换律 4 结合律 5 吸收律 6 德摩根律 7 同一律 8 零律 9 矛盾律 10 排中律 11 蕴含表达式 12 …...
Debezium系列之:事件扁平化转换SMT,简化debezium数据格式,为数据添加head,为值添加键值对
Debezium系列之:事件扁平化转换SMT,简化debezium数据格式,为数据添加head,为值添加键值对 一、需求背景二、Debezium数据格式和扁平化数据格式对比三、事件扁平化SMT作用四、事件扁平化转换SMT设置五、事件扁平化参数详解六、完整SMT参数配置一、需求背景 Debezium 数据更改…...

内网渗透(十八)之Windows协议认证和密码抓取-本地认证(NTML哈希和LM哈希)
系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…...

Portraiture全新4.0最新版人像磨皮插件更新内容
Portraiture是一款智能磨皮插件,为Photoshop和Lightroom添加一键磨皮美化功能,快速对照片中皮肤、头发、眉毛等部位进行美化,无需手动调整,大大提高P图效率。全新4版本,升级AI算法,并独家支持多人及全身模式…...

前端也能悄悄对视频截图?js实现对视频按帧缓存
前言 虽然最后没有采用这种方案来实现滚动控制视频进度,但是仍然想自己试试这种方案的实现,毕竟应用范围也挺广的。 核心代码并不多,算是一篇小短文~。 掘金好像不允许放站外演示链接,所以这里就用动图大概展示下最终…...

TCP、UDP网络编程面试题
TCP、UDP、Socket、HTTP网络编程面试题 什么是网络编程 网络编程的本质是多台计算机之间的数据交换。数据传递本身没有多大的难度,不就是把一个设备中的数据发送给其他设备,然后接受另外一个设备反馈的数据。现在的网络编程基本上都是基于请求/响应方式…...

用网络调试助手测试PLC-Reocrder收听模式的过程
目录 一、测试环境 二、步骤及要点说明 1、PLC-Recorder的通道配置 2、PLC-Recorder启动采集 3、配置网络调试助手 4、启动调试助手的连接,并点击“启动批量发送” 5、停止发送,查看发送和接收的情况 三、小结 一、测试环境 Windows10操作系统&a…...

牛客小白月赛66
牛客小白月赛66_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)冒着期末挂科的风险打了打,缓解了一下网瘾,感觉还行最近为了期末鸽了很多期的div3,一学期末就手痒想训,感觉再不打人要没了,结果…...

加载sklearn新闻数据集出错 fetch_20newsgroups() HTTPError: HTTP Error 403: Forbidden解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

图解LeetCode——剑指 Offer 53 - I. 在排序数组中查找数字 I
一、题目 统计一个数字在排序数组中出现的次数。 二、示例 示例 1 【输入】nums [5,7,7,8,8,10], target 8 【输出】2 示例 2: 【输入】nums [5,7,7,8,8,10], target 6 【输出】0 提示: 0 < nums.length < 10^5-10^9 < nums[i] < 10^9nums 是一…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
SQL进阶之旅 Day 22:批处理与游标优化
【SQL进阶之旅 Day 22】批处理与游标优化 文章简述(300字左右) 在数据库开发中,面对大量数据的处理任务时,单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”,深入探讨如何通过批量操作和游标技术提…...