【Spring Boot】异常处理
异常处理
- 1.认识异常处理
- 1.1 异常处理的必要性
- 1.2 异常的分类
- 1.3 如何处理异常
- 1.3.1 捕获异常
- 1.3.2 抛出异常
- 1.3.4 自定义异常
- 1.4 Spring Boot 默认的异常处理
- 2.使用控制器通知
- 3.自定义错误处理控制器
- 3.1 自定义一个错误的处理控制器
- 3.2 自定义业务异常类
- 3.2.1 自定义异常类
- 3.2.2 自定义全局捕获异常
- 3.2.3 测试自定义异常类
1.认识异常处理
异常处理 是编程语言的机制,用来处理软件系统中出现的异常情况,增强代码的可读性。
1.1 异常处理的必要性
异常处理用于解决一些程序无法掌控,但又必须面对的情况。例如,程序需要读取文件、连接网络、使用数据库等,但可能文件不存在、网络不畅通、数据库无效等情况。为了程序能继续运行此时就需要把这些情况进行异常处理。异常处理的方法通常有以下几种:
- 将异常通知给开发人员、运维人员或用户。
- 使因为异常中断的程序以适当的方式继续运行,或者退出。
- 保存用户的当前操作,或者进行数据回滚。
- 释放资源。
1.2 异常的分类
- Error:代表编译和系统的错误,不允许捕获。
- Exception:标准 Java 库的方法所激发的异常,包含运行异常 Runtime_Exception 和非运行异常 Non_RuntimeException 的子类。
- Runtime Exception:运行时异常。
- Non RuntimeException:非运行时可检测的异常,Java 编译器利用分析方法或构造方法中可能产生的结果来检测程序中是否含有检测异常的处理程序,每个可能的可检测异常、方法或构造方法的
throws
子句必须列出该异常对应的类。 - Throw:用户自定义异常。
1.3 如何处理异常
1.3.1 捕获异常
捕获异常的格式,见以下代码:
try{//......
}
catch(//......
)
finally{//......
}
try
:在try
语句中编写可能发生异常的代码,即正常的业务功能代码。如果执行完try
语句不发生异常,则执行finally
语句(如果有的话)和finally
后面的代码;如果发生异常,则尝试去匹配catch
语句。catch
:捕捉错误并处理。finally
:finally
语句是可选的,无论异常是否发生、是否匹配、是否被处理,finally
都会执行。
一个 try
至少要有一个 catch
语句,或至少要有 1 1 1 个 finally
语句。finally
不是用来处理异常的,也不会捕获异常,是为了做一些清理工作,如流的关闭、数据库连接的关闭等。
1.3.2 抛出异常
除用 try
语句处理异常外,还可以用 throw
、throws
抛出异常。
执行 throw
语句的地方是一个异常抛出点,后面必须是一个异常对象,且必须写在函数中。
throw
、throws
的用法见以下代码。
throw
语法:
throw(异常对象);
throws
语法:
[(修饰符)](返回值类型)(方法名)([参数列表])[throws(异常类)]{...}
1.3.4 自定义异常
在应用程序的开发过程中,经常会自定义异常类,以避免使用 try
产生重复代码。自定义异常类一般是通过扩展 Exception 类来实现的。这样的自定义异常属于 检查异常(checked exception
)。如果要自定义非检查异常,则需要继承 RuntimeException。
1.4 Spring Boot 默认的异常处理
Spring Boot 提供了一个默认处理异常的映射。在 Spring Boot 的 Web 项目中,尝试访问一个不存在的 URL(http://localhost:8080/pipi
),会得到 Spring Boot 中内置的异常处理如下提示:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat May 18 22:49:20 CST 2019
There was an unexpected error (type=Not Found, status=404).
No message available.
同样的地址,如果发送的请求带有 Content-Type→application/json;charset=UTF-8
则返回的是 JSON 格式的错误结果,见以下输出结果:
{"timestamp":"2019-05-18T14:47:46.722+0000","status": 404,"error": "Not Found","message": "No message available","path": "/pipi"
}
从上面结果可以看出,Spring Boot 会根据消费者发送的 Content-Type
来返回相应的异常内容,如果 Content-Type
是 applicaton/json
,则返回 JSON 文件;如果 Content-Type
,是 text/html
,则返回 HTML 文件。
2.使用控制器通知
在编写代码时,需要对异常进行处理。进行异常处理的普通的代码是 try...catch
结构。但在开发业务时,只想关注业务正常的代码,对于 catch
语句中的捕获异常,希望交给异常捕获来处理,不单独在每个方法中编写。这样不仅可以减少冗余代码,还可以减少因忘记写 catch
而出现错误的概率。
Spring 正好提供了一个非常方便的异常处理方案:控制器通知(@ControllerAdvice 或 @RestcontrollerAdvice),它将所有控制器作为一个切面,利用切面技术来实现。
通过基于 @ControllerAdvice 或 @RestControllerAdvice 的注解可以对异常进行全局统一处理,默认对所有的 Controller 有效。如果要限定生效范围,则可以使用 ControllerAdvice 支持的限定范围方式。
- 按注解:
@ControllerAdvice(annotations=RestController.class)
。 - 按包名:
@ControllerAdvice("org.example.controller")
。 - 按类型:
@ControllerAdvice(assignableTypes={Controllerlnterface.class, AbstractController.class})
。
这是 ControllerAdvice 进行统一异常处理的优点,它能够细粒度地控制该异常处理器针对哪些 Controller、包或类型有效。
可以利用这一特性在一个系统实现多个异常处理器,然后 Controller 可以有选择地决定使用哪个,使得异常处理更加灵活、降低侵入性。
异常处理类会包含以下一个或多个方法:
- @InitBinder:对表单数据进行绑定,用于定义控制器参数绑定规则。如转换规则、格式化等。可以通过这个注解的方法得到 WebDataBinder 对象,它在参数转换之前被执行。
- @ModelAttribute:在控制器方法被执行前,对所有 Controller 的 Model 添加属性进行操作。
- @ExceptionHandler:定义控制器发生异常后的操作,可以拦载所有控制器发生的异常。
- @ControllerAdvice:统一异常处理,通过
@ExceptionHandler(value=Exception.class)
来指定捕获的异常。@ControllerAdvice + @ExceptionHandle
可以处理除 404 以外的运行异常。
3.自定义错误处理控制器
3.1 自定义一个错误的处理控制器
以下代码演示如何自定义一个错误的处理控制器。
package com.example.demo.Controller;import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
/*springboot提供了默认的错误映射地址error
@RequestMapping("${server.error.path:${error.path:/error}}")
@RequestMapping("/error")
上面2种写法都可以
*/
@RequestMapping("/error")
//继承springboot提供的ErrorController
public class TestErrorController implements ErrorController {//一定要重写方法,默认返回null就可以,不然报错,因为getErrorPath为空@Overridepublic String getErrorPath() {return null;}//一定要添加url映射,指向error@RequestMappingpublic Map<String, Object> handleError() {//用Map容器返回信息Map<String, Object> map = new HashMap<String, Object>();map.put("code", 404);map.put("msg", "不存在");return map;}/*这里加一个能正常访问的页面,作为比较因为写在一个控制器所以它的访问路径是http://localhost:8080/error/ok*/@RequestMapping("/ok")@ResponseBodypublic Map<String, Object> noError() {//用Map容器返回信息Map<String, Object> map = new HashMap<String, Object>();map.put("code ", 200);map.put("msg", "正常,这是测试页面");return map;}
}
启动项目,访问一个不存在的网址,则返回下方信息:
访问正确定义的映射,则返回下方正确信息:
3.2 自定义业务异常类
3.2.1 自定义异常类
自定义异常类需要继承 Exception(异常)类。这里继承 RuntimeException,代码如下:
package com.example.demo.exception;public class BusinessException extends RuntimeException{//自定义错误码private Integer code;//自定义构造器,必须输入错误码及内容public BusinessException(int code, String msg) {super(msg);this.code = code;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}
}
RuntimeException 和 Error 是非检查异常,其他的都是检查异常。所有方法都可以在不声明 throws
方法的情况下抛出 RuntimeException 及其子类,不可以在不声明的情况下抛出非 RuntimeException,即:非 RuntimeException 要自己写 catch
语句处理,如果 RuntimeException 不使用 try...catch
进行捕捉,则会导致程序运行中断。
3.2.2 自定义全局捕获异常
package com.example.demo.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;@ControllerAdvice
public class CustomerBusinessExceptionHandler {@ResponseBody@ExceptionHandler(BusinessException.class)public Map<String, Object> businessExceptionHandler(BusinessException e) {Map<String, Object> map = new HashMap<String, Object>();map.put("code", e.getCode());map.put("message", e.getMessage());//发生异常进行日志记录,此处省略return map;}
}
3.2.3 测试自定义异常类
创建控制器。以抛出 BusinessException 的自定义异常。
package com.example.demo.controller;import com.example.demo.exception.BusinessException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TestController {@RequestMapping("/BusinessException")public String testResponseStatusExceptionResolver(@RequestParam("i") int i) {if (i == 0) {throw new BusinessException(600, "自定义业务错误");}return "success";}}
启动项目,访问 http://localhost:8080/BusinessException?i=0
测试异常处理情况,则抛出下方错误信息:
相关文章:
【Spring Boot】异常处理
异常处理 1.认识异常处理1.1 异常处理的必要性1.2 异常的分类1.3 如何处理异常1.3.1 捕获异常1.3.2 抛出异常1.3.4 自定义异常 1.4 Spring Boot 默认的异常处理 2.使用控制器通知3.自定义错误处理控制器3.1 自定义一个错误的处理控制器3.2 自定义业务异常类3.2.1 自定义异常类3…...
Laravel学习-自定义辅助函数
因为laravel框架的辅助函数helpers不会进入版本库,被版本库忽略的,只有自己创建一个helpers辅助函数。 可以在任意文件下创建helpers.php文件,建议在app目录下, 然后在composer.json文件中,autoload 中间,…...
LLVM Cpu0 新后端6
想好好熟悉一下llvm开发一个新后端都要干什么,于是参考了老师的系列文章: LLVM 后端实践笔记 代码在这里(还没来得及准备,先用网盘暂存一下): 链接: https://pan.baidu.com/s/1yLAtXs9XwtyEzYSlDCSlqw?…...
GAT1399协议分析(9)--图像上传
一、官方定义 二、wirechark实例 有前面查询的基础,这个接口相对简单很多。 请求: 文本化: POST /VIID/Images HTTP/1.1 Host: 10.0.201.56:31400 User-Agent: python-requests/2.32.3 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive content-type:…...
Spring ApplicationContext的getBean方法
Spring ApplicationContext的getBean方法 在Spring框架的ApplicationContext中,getBean(Class<T> requiredType)方法可以接受一个类类型参数,这个参数可以是接口类也可以是实现类。 使用接口类: 如果requiredType是一个接口,…...
自然语言处理(NLP)—— 自动摘要
自动摘要是一种将长文本信息浓缩为短文本的技术,旨在保留原文的主要信息和意义。 1 自动摘要的第一种方法 它的第一种方法是基于理解的,受认知科学和人工智能的启发。 在这个方法中,我们首先建立文本的语义表示,这可以理解为文本…...
Spring RestClient报错:400 Bad Request : [no body]
我项目采用微服务架构,所以各服务之间通过Spring RestClient远程调用,本来一直工作得好好的,昨天突然发现远程调用一直报错,错误详情如下: org.springframework.web.client.HttpClientErrorException$BadRequest: 400…...
【数据结构】 -- 堆 (堆排序)(TOP-K问题)
引入 要学习堆,首先要先简单的了解一下二叉树,二叉树是一种常见的树形数据结构,每个节点最多有两个子节点,通常称为左子节点和右子节点。它具有以下特点: 根节点(Root):树的顶部节…...
C#面:XML与 HTML 的主要区别是什么
C# XML与HTML有以下几个主要区别: 用途不同:XML(eXtensible Markup Language)是一种用于存储和传输数据的标记语言,它的主要目的是描述数据的结构和内容。HTML(HyperText Markup Language)是一…...
java并发-如何保证线程按照顺序执行?
【readme】 使用只有单个线程的线程池(最简单)Thread.join() 可重入锁 ReentrantLock Condition 条件变量(多个) ; 原理如下: 任务1执行前在锁1上阻塞;执行完成后在锁2上唤醒;任务…...
PyCharm中 Fitten Code插件的使用说明一
一. 简介 Fitten Code插件是是一款由非十大模型驱动的 AI 编程助手,它可以自动生成代码,提升开发效率,帮您调试 Bug,节省您的时间,另外还可以对话聊天,解决您编程碰到的问题。 前一篇文章学习了 PyCharm…...
Polar Web【简单】PHP反序列化初试
Polar Web【简单】PHP反序列化初试 Contents Polar Web【简单】PHP反序列化初试思路EXP手动脚本PythonGo 运行&总结 思路 启动环境,显示下图中的PHP代码,于是展开分析: 首先发现Easy类中有魔术函数 __wakeup() ,实现的是对成员…...
树莓派4B 零起点(二) 树莓派 更换软件源和软件仓库
目录 一、准备工作,查看自己的树莓派版本 二、安装HTTPS支持 三、更换为清华源 1、更换Debian软件源 2,更换Raspberrypi软件仓库 四、进行软件更新 接前章,我们的树莓派已经启动起来了,接下来要干的事那就是更换软件源和软件…...
Pytorch 实现目标检测二(Pytorch 24)
一 实例操作目标检测 下面通过一个具体的例子来说明锚框标签。我们已经为加载图像中的狗和猫定义了真实边界框,其中第一个 元素是类别(0代表狗,1代表猫),其余四个元素是左上角和右下角的(x, y)轴坐标(范围…...
如何使用Python中的列表解析(list comprehension)进行高效列表操作
Python中的列表解析(list comprehension)是一种创建列表的简洁方法,它可以在单行代码中执行复杂的循环和条件逻辑。列表解析提供了一种快速且易于阅读的方式来生成新的列表。 以下是一些使用列表解析进行高效列表操作的示例: 1.…...
java使用websocket遇到的问题
java使用websocket的bug 1 websocket连接正常但是收不到服务端发出的消息java的websocket并发的时候导致连接断开(看着连接是正常的,但是实际上已经断开) 1 websocket连接正常但是收不到服务端发出的消息 java的websocket并发的时候导致连接断…...
[Cloud Networking] Layer 2
文章目录 1. 什么是Mac Address?2. 如何查找MAC地址?3. 二层数据交换4. [Layer 2 Protocol](https://blog.csdn.net/settingsun1225/article/details/139552315) 1. 什么是Mac Address? MAC 地址是计算机的唯一48位硬件编码,嵌入到网卡中。 MAC地址也…...
[240609] qwen2 发布,在 Ollama 已可用 | 采用语言模型构建通用 AGI(2020年8月)
目录 qwen2 发布,在 Ollama 已可用Qwen2 模型概览 (基于 Ollama 网站信息)一、模型介绍二、模型参数三、支持语言 (除英语和中文外)四、模型性能五、许可证六、数据支撑: 采用语言模型构建通用 AGI qwen2 发布,在 Ollama 已可用 Qwen2 模型概览 (基于 O…...
赶紧收藏!2024 年最常见 20道分布式、微服务面试题(五)
上一篇地址:赶紧收藏!2024 年最常见 20道分布式、微服务面试题(四)-CSDN博客 九、在分布式系统中,如何保证数据一致性? 在分布式系统中保证数据一致性是一个复杂的问题,因为分布式系统由多个独…...
为什么Kubernetes(K8S)弃用Docker:深度解析与未来展望
为什么Kubernetes弃用Docker:深度解析与未来展望 🚀 为什么Kubernetes弃用Docker:深度解析与未来展望摘要引言正文内容(详细介绍)什么是 Kubernetes?什么是 Docker?Kubernetes 和 Docker 的关系…...
软件游戏提示msvcp120.dll丢失的解决方法,总结多种靠谱的解决方法
在电脑使用过程中,我们可能会遇到一些错误提示,其中之一就是“找不到msvcp120.dll”。那么,msvcp120.dll是什么?它对电脑有什么影响?有哪些解决方法?本文将从以下几个方面进行探讨。 一,了解msv…...
使用kafka tools工具连接带有用户名密码的kafka
使用kafka tools工具连接带有用户名密码的kafka 创建kafka连接,配置zookeeper 在Security选择Type类型为SASL Plaintext 在Advanced页面添加如下图红框框住的内容 在JAAS_Config加上如下配置 需要加的配置: org.apache.kafka.common.security.plain.Pla…...
[个人感悟] Java基础问题应该考察哪些问题?
前言 “一切代码无非是数据结构和算法流程的结合体.” 忘了最初是在何处看见这句话了, 这句话, 对于Java基础的考察也是一样. 正如这句话所说, 我们对于基础的考察主要考察, 数据结构, 集合类型结构, 异常类型, 已经代码的调用和语法关键字. 其中数据结构和集合类型结构是重点…...
MySQL-主从复制
1、主从复制的理解 在工作用常见Redis作为缓存与MySQL一起使用。当有请求时,首先会从缓存中进行查找,如果存在就直接取出,否则访问数据库,这样 提升了读取的效率,也减少了对后台数据库的访问压力。Redis的缓存架构时高…...
开发没有尽头,尽力既是完美
最近遇到了一些难题,开发系统总有一些地方没有考虑周全,偏偏用户使用的时候“完美复现”了这个隐藏的Bug...... 讲道理创业一年之久为了生存,我一直都有在做复盘,复盘的核心就是:如何提升营收、把控开发质量࿰…...
【手推公式】如何求SDE的解(附录B)
【手推公式】如何求SDE的解(附录B) 核心思路:不直接求VE和VP的SDE的解xt,而是求xt的期望和方差,从而写出x0到xt的条件分布形式(附录B) 论文:Score-Based Generative Modeling throug…...
STM32F103单片机工程移植到航顺单片机HK32F103注意事项
一、简介 作为国内MCU厂商中前三阵营之一的航顺芯片,建立了世界首创超低功耗7nA物联网、万物互联核心处理器浩瀚天际10X系列平台,接受代理商/设计企业/方案商定制低于自主研发十倍以上成本,接近零风险自主品牌产品,芯片设计完成只…...
Llama模型家族之Stanford NLP ReFT源代码探索 (四)Pyvene论文学习
LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 基于 LlaMA…...
rapidjson 打包过程插入对象
开发过程中遇到一种情况,在打包过程中插入一个字符串(里面是json对象), 官方文档 没看到相关例子,不知道是不是自己粗心没找到。方法RawValue其实是一个通用打包方法,一般情况我们都调用的是String()、Int(…...
NVeloDocx一个基于NVelocity的word模版引擎
NVeloDocx是一个基于NVelocity的Word模版引擎,目前主要是用于E6低代码开发平台供用户轻松制作各种Word报告模版。 有以下优点: 1、完全的NVelocity语法; 2、直接在Word中写NVelocity脚本,使用非常非常方便; 3、完全兼…...
网站开发三大元素/大型营销型网站制作
Servlet处理请求的流程: 1) 客户端在浏览器的地址栏中输入一个请求的URL,按回车后就向服务器端发起一个http request(由浏览器生成)。 2) 服务器端的Web Server首先接受到请求,并将请求转交给容器,容器会根据请求的URL去调用客户端要访问的Servlet。 3) …...
建筑工程网签合同周末可以签吗/seo是什么
本文已迁移至:https://blog.csdn.net/COCO56/article/details/89382093 原标题:VS各版本下载与密钥(从2008到2017),VS老版本在官网如何下载(解决下载老版本时提示抱歉,我们找不到适合您的下载内容的问题&a…...
上海松江做网站/设计网站模板
服务器文件删除日志 内容精选换一换主机和云服务的日志数据上报至云日志服务后,默认存储时间为7天,您也在创建日志组时,可以对日志存储进行设置(1-30天)。超出存储时间的日志数据将会被自动删除,对于需要长期存储的日志数据(日志持…...
目前做美术的网站以及app/网络营销这个专业怎么样
(下面内容均是来源于网友经验,我只是大自然的搬运工,多谢广大网友) 原因应该是 :上次关机时未正常关机; 表现症状:QQ初始化失败,很多网页打不开,一些应用打不开ÿ…...
做网站贵/东莞网站到首页排名
免费帮大家发布招聘需求,如有需要可在微信上与我联系~地点:南京岗位:数据分析 & 数据开发经验要求:本科3年左右,研究生1年左右薪资:13-18K技能要求:数据开发【熟悉Java,了解大数…...
数据库跟网站内容/网站模版
1. UISearchDisplayController.searchResultsTableView 的frame指定只有在 didShowSearchResultsTableView委托调用之后,反正我觉得系统会改动它的大小位置,所以我不得不写了一个重新定位它的frame,来覆盖系统的默认设置。 2. UISearchDis…...