SpringBoot异常处理?用这两个就够啦!
在日常项目中,我们难免会遇到系统错误的情况。如果对系统异常的情况不做处理,Springboot本身会默认将错误异常作为接口的请求返回。
@GetMapping("/testNorError")
public void testNorError() {try {throw new MyException(6000, "我的错误");}catch (Exception e){throw new MyException(5000, "我的包装异常", e);}
}
从上图可以看到,Springboot没有对异常进行处理的情况下,将错误的堆栈直接当做响应数据返回了。这样对用户既不友好,又可能因为泄漏系统堆栈信息引发潜在的安全风险。因此,搭建一个完善的异常处理机制,对于维护系统健壮性是十分必要的。
通用异常处理
要快速的搭建异常处理机制,那么需要考虑如何对异常进行捕获并加以处理?最便捷的方法便是用**@ExceptionHandler**注解实现。
@ExceptionHandler(MyException.class)protected ResponseEntity<Object> handleException(Exception ex) {LOGGER.error("Failed to execute,handleException:{}", ex.getMessage(), ex);return new ResponseEntity<>(new ResultDTO().fail(ResultCodeEnum.ERROR_SERVER), HttpStatus.OK);}
通过在Controller内添加上述的异常处理代码,Springboot就可以将相关的错误信息转义成系统的统一错误处理,进而避免堆栈外露。(这里的ResultDTO是系统内自定义的JSON结构,可以根据自己的业务自行修改。)
然而,@ExceptionHandler本身存在一个弊端,就是他作用的范围必须是Controller,也就意味着有多少个Controller,你的异常处理代码便要重复写多遍,这无疑是低效率的。为了减少重复的代码冗余,@ControllerAdvance就进入了我们的视野。
@ControllerAdvice
@Slf4j
public class ExtGlobalExceptionHandler {@ExceptionHandler(Exception.class)protected ResponseEntity<Object> handleException(Exception ex) {LOGGER.error("Failed to execute,handleException:{}", ex.getMessage(), ex);return new ResponseEntity<>(new ResultDTO().fail(ResultCodeEnum.ERROR_SERVER), HttpStatus.OK);}
}
简单来说,@ControllerAdvance是一个全局处理的注解,其中的代码会对所有的Controller生效,通常会搭配@ExceptionHandler处理异常,由此以来就可以实现只编写一次异常处理方法就可以处理全局异常的情况。
至于@ControllerAdvance和@ExceptionHandler是如何实现这个神奇的功能的,限于篇幅原因,后续会考虑单独出一篇文章详细介绍。(其实根据名字,不难推断ControllerAdvance就是一种针对于Controller对象的动态代理罢了。)
个性化异常处理
用了@ControllerAdvance和ExceptionHandler,几乎可以解决80%的项目面临的报错处理问题。然而,思考一下。如果一个项目中出现了多组人同时维护、迭代一个系统的时候(降本增效嘛,懂的都懂),每组人要关注的报错自然会不一样。如A组人只关注报错A,B组人员只关注报错B,那么这种通用的异常解决方案是无法区分开的。
针对于这种情况,就不得不请出另外一位大佬了,他就是:AOP,针对于动态代理有很多的实现方式和框架,这里我们直接默认采用SpringBoot的自带AOP框架:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.1.11.RELEASE</version>
</dependency>
不管选择的AOP实现框架是什么,要采用AOP编码都少不了以下两个步骤:
1、定义切点和执行时机(哪些地方要做增强)
2、定义通知(要怎么增强)
定义切点和执行时机
对于Springboot自带的AOP框架,其执行时机共有以下五个:
增强时机 | 增强类型 | 异同点 |
---|---|---|
@After | 后置增强 | 目标方法执行之后调用增强方法 |
@Before | 前置增强 | 目标方法执行之前先调用增强方法 |
@AfterReturning | 返回增强 | 目标方法执行return之后返回结果之前调用增强方法,如果出异常则不执行 |
@AfterThrowing | 异常增强 | 目标方法执行产生异常调用增强方法,需注意的是,处理后异常依旧会往上抛出,不会被catch。 |
@Around | 环绕增强 | 环绕增强包含前面四种增强,通过一定的try-catch处理,环绕类型可以替代上述的任意一种增强。 |
了解了SpringBoot的动态代理的执行时机之后,我们还需要知道其定义切点的方式。框架定义切点的方式主要有两个:
-
切点表达式
-
注解
注释
我们首先介绍注释的正确打开方式。要通过注解来实现自己的AOP,那么首先需要定义一个新的注解。这里我简单定义了一个注解:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {String SERVER_NAME() default "";String action() default "";
}
在定义了注解以后,将注解定义为方法的入参,并通过@annotation()标注出注解的变量名称,由此就可以实现注解AOP的功能。
//处理注解的地方
@Around(value = "@annotation(name)")
public <T> T test(ProceedingJoinPoint point, MyAnnotation name) throws Throwable {String serverName = name.SERVER_NAME();//处理异常return handlerRpcException(point, serverName);
}//具体代码执行处
@MyAnnotation(SERVER_NAME = "下游系统", action = "操作处理")
public <T> T testFunction() {return (T) new ResultDTO<>().success(Boolean.TRUE);
}
切点表达式
Springboot的AOP中,还提供了一种十分强大的实现动态代理切点标注的方式,即切点表达式,其基本模式如下所示:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
注意到modifiers-pattern?、declaring-type-pattern?、throws-pattern?等携带问号的参数都是非必填的。紧接着我们来逐一介绍上述参数的含义:
- modifiers-pattern?:修饰符匹配,主要表示的是切点是public/private/protected/default的哪一种。
- ret-type-pattern:顾名思义,指的是返回值的类型,常见如:void/Boolean/String等
- declaring-type-pattern?:这个指的是被增强的方法、属性的类路径,如com.example.demo.service.aop.MyAspect等
- name-pattern(param-pattern):这个是相对关键的参数,指的是被增强的方法名称以及其对应的参数类型。
- throws-pattern:throw-pattern见词知意,可以知道它是指的方法所抛出的异常类型。
除了了解了上述的表达式的基本匹配含义以外,还有几个特殊的符号通配指的提一下:
*****:匹配任何数量字符
…:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数(0个或者多个参数)
+:匹配指定类型及其子类型;仅能作为后缀放在类型模式后边
也许上面的代码和介绍让你一脸懵逼,没关系,可以简单看下下面两个表达式的含义,你就大致明白他们的含义了:
// 1、代表【返回值任意】且前缀为【com.example.demo.rpc】的【任意类下】【任意名称】的【所有参数】方法
execution(* com.example.demo.rpc.*.*(..))// 2、代表【返回值为Boolean】且位于【com.example.demo.rpc及其子包下】的【任意名称】的【以String为最后一个入参数】的方法
execution(Boolean com.example.demo.rpc..*(.., String))
借助于切面表达式,我们可以很自由灵活地定义出我们的切点,从而通过AOP实现我们对于异常的处理
@Pointcut("execution(Boolean com.example.demo.rpc..*(.., String)) || execution(另外一个表达式)")private void PointCutOfAnno() {
}@Around(value = "PointCutOfAnno()")
public <T> T testForAOP(ProceedingJoinPoint point) throws Throwable {//处理对应的异常return handlerRpcException(point, serverName);
}
总结
本文介绍了两种Springboot下针对于异常处理的编写方法:
一、借助于@ControllerAdvance和@ExceptionHandler实现的通用异常处理方法
二、借助于AOP实现的个性化异常处理机制。
两者其实本质上的实现思路都是一样的,通过对执行代码做动态代理,从而将错误包装起来,达到异常不外漏的效果。在实际业务场景中,方法一几乎可以涵盖80%的异常处理场景。方案二则主要针对一个系统中需要做个性化处理的情况,可以根据具体的业务需要进行选择。
参考文献
@Pointcut 的 12 种用法,你知道几种?
相关文章:
SpringBoot异常处理?用这两个就够啦!
在日常项目中,我们难免会遇到系统错误的情况。如果对系统异常的情况不做处理,Springboot本身会默认将错误异常作为接口的请求返回。 GetMapping("/testNorError") public void testNorError() {try {throw new MyException(6000, "我…...
mysql-查询重复数据的条数-count
查询重复数据的条数 select name , count(*) from table group by name; 查询结果:查询表table中name相同重复的个数 补充:count的用法 查询一个表中总共多少行(多少条数据) select count (*) from table 小结 …...
【Java枚举类】使用enum关键词定义枚举类
使用说明 1.使用 enum 定义的枚举类默认继承了 java.lang.Enum类,因此不能再继承其他类 2.枚举类的构造器只能使用 private 权限修饰符 3.枚举类的所有实例必须在枚举类中显式列出(, 分隔 ; 结尾)。列出的 实例系统会自动添加 public static final 修饰 4.必须在…...
第十四届蓝桥杯三月真题刷题训练——第 8 天
目录 第 1 题:分数 题目描述 运行限制 代码: 第 2 题:回文日期 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码: 第 3 题:迷宫 代码: 第 1 题:分数 题目描述 本题为填空题…...
鼎阳SDS2074X Plus免费“升级”(破解)备忘录
鼎阳SDS2074X Plus从基础参数来看,在一众国产示波器里并不出彩。但作为一款可以免费“升级”到【1】4通道2GSa/s的采样率,500MHz分析带宽,200Mpts存储深度的数字示波器(可惜原配的是200MHz的探头,500MHz的探头还是贵&a…...
【C++】C++标准模板库STL (一) string类的使用详解
前言 在前一章种我们介绍了C中的模板的使用,这是一种泛型编程,模板的使用能让我们减少大量的相似代码,减少我们的代码量与工作量,写出更加高效简洁的代码,模板如此好用,但还是要我们先出写一个泛型类或函数…...
如何用SpringBoot+Thymeleaf+Echart生成好看的柱状图,折线图,饼状图
一、前言 上篇文章我们用POI技术读取Excel并生成了相应的图表。但是实际的效果比较一般,因为本身WPS生成图表就比较简单,如果用程序操作远比人工耗时费力,效果远不如一些付费模板。如下图所示: 然后我就想到前端不是有一个简单易…...
LeetCode819. 最常见的单词(python)
题目 给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。 题目保证至少有一个词不在禁用列表中,而且答案唯一。 禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。…...
【深入理解C指针】经典笔试题——指针和数组
🔹内容专栏:【C语言】进阶部分 🔹本文概括:一些指针和数组笔试题的解析 。 🔹本文作者:花香碟自来_ 🔹发布时间:2023.3.12 目录 一、指针和数组练习题 1. 一维数组 2. 字符数组 …...
雷达散射截面
雷达散射截面(Radar Cross Section, RCS)是表征目标散射强弱的物理量。 σ = 4 π R 2 ∣ E s ∣ 2 ∣ E i ∣ 2 \sigma = 4\pi R^2 \frac{|E_s |^2}{|E_i|^2}...
希腊棺材之谜——复盘
文章目录梗概推导伪解答虽然花费6-8小时来看小说,是一件很奢侈的事情。但是再荒诞的事情终归有它背后的逻辑链条。这正如Ellery所坚持的那样,逻辑为王。希腊棺材之谜是Ellery Queen首次展露头角, 因此作者特地给他安排了3次伪解答和1次真解答…...
CentOS的下载和安装
文章目录前言一、CentOS的下载二、如何下载1.选择下载版本2.选择isos3.点击isos后,进入如下页面,接着点击X86_644.一般选择下面框住的进行下载三、安装软件选择设置接着进行分区设置设置网络和主机名前言 在学习Linux时,记录下CentOS的安装 …...
new bing的chatGPT如何解析英文论文pdf
昨天我的new bing申请下来了,有了聊天的界面: 但是解析pdf的英文文献,还是不行,没有对话窗口。就问了一下chatGPT,方案如下: 要使用New Bing解析PDF文献,你需要以下几个步骤: 1&a…...
学会这12个Python装饰器,让你的代码更上一层楼
学会这12个Python装饰器,让你的代码更上一层楼 Python 装饰器是个强大的工具,可帮你生成整洁、可重用和可维护的代码。某种意义上说,会不会用装饰器是区分新手和老鸟的重要标志。如果你不熟悉装饰器,你可以将它们视为将函数作为输…...
企业使用ERP的好处
ERP系统是企业管理信息系统的简称,它是以信息技术为手段,以物流、资金流、信息流为主线,以企业的核心业务流程为对象,建立的一套适用于企业管理的、高效的企业管理信息系统。它是通过科学方法和计算机信息技术,将企业运…...
【QT】如何获取屏幕(桌面)的大小或分辨率
目录1. QDesktopWidget 获取系统屏幕大小2. QScreen 获取系统屏幕大小3. geometry() 与 availableGeometry() 的区别1. QDesktopWidget 获取系统屏幕大小 QDesktopWidget 提供了详细的位置信息,其能够自动返回窗口在用户窗口的位置和应用程序窗口的位置 QDesktopW…...
ETL工具的选择
正确选择 ETL 工具,可以从 ETL 对平台的支持、对数据源的支持、数据转换功能、管理 和调度功能、集成和开放性、对元数据管理等功能出发,具体如下。 支持平台 随着各种应用系统数据量的飞速增长和对业务可靠性等要求的不断提高,人们对数据抽…...
SpringBoot仿天猫商城java web购物网站的设计与实现
1,项目介绍 基于 SpringBoot 的仿天猫商城拥有两种角色,分别为管理员和用户。 迷你天猫商城是一个基于SSM框架的综合性B2C电商平台,需求设计主要参考天猫商城的购物流程。 后端页面兼容IE10及以上现代浏览器,Chrome,Edge,Firebox…...
C#基础教程22 文件的输入与输出
C# 文件的输入与输出 一个 文件 是一个存储在磁盘中带有指定名称和目录路径的数据集合。当打开文件进行读写时,它变成一个 流。 从根本上说,流是通过通信路径传递的字节序列。有两个主要的流:输入流 和 输出流。输入流用于从文件读取数据(读操作),输出流用于向文件写入数…...
Ubuntu18.04 python 开发usb通信
一、安装环境 1.安装pip sudo python3 get-pip.py 或 sudo -i apt update apt install python3-pip 确定pip是否安装成功: xxx-desktop:~$ pip3 --versionpip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)2.安装pyusb pip3 install pyusb --use…...
RabbitMq 消息确认机制详解 SpringCloud
1 消息可靠性 消息从发送,到消费者接收,会经理多个过程,其中的每一步都可能导致消息丢失. #### 2 常见的丢失原因 发送时丢失: 生产者发送的消息未送达exchange 消息到达exchange后未到达queueMQ宕机,queue将消息丢失 consumer…...
后台导航布局
五、后台导航实例 参考链接: 页面后台导航制作 如何实现html后台导航iframe点击换url(代码) 如何消除html页面下边和右边的滚动条 html页面有多个滚动条时的优化 页面出现不必要的滚动条,怎么调试? 一个页面有两…...
设计模式——抽象工厂模式(创建型)
一、介绍抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。问题假设你正在开发一款家具商店模拟器。 你的代码中包括一些类, 用于表示:一系列相关产品, 例如 椅子Chair 、 沙发Sofa和…...
Java面试题--SpringMVC的执行流程
概要 SpringMVC是一种基于MVC(Model-View-Controller)框架的Web应用开发框架。下面是SpringMVC的详细执行流程。 客户端向DispatcherServlet发送请求。DispatcherServlet收到请求后,根据HandlerMapping(处理器映射)找…...
c# 32位程序突破2G内存限制
起因 在开发过程中,由于某些COM组件只能在32位程序下运行,程序不得不在X86平台下生成。而X86的32位程序默认内存大小被限制在2G。由于程序中可能存在大数量处理,期间对象若没有及时释放或则回收,内存占用达到了1.2G左右ÿ…...
【C语言】指针详解总结
指针1. 指针是什么2. 指针和指针类型2.1 指针-整数2.2 指针的解引用3. 野指针3.1 野指针成因3.2 如何规避野指针4. 指针运算4.1 指针-整数4.2 指针-指针4.3 指针的关系运算5. 指针和数组6. 二级指针7. 指针数组1. 指针是什么 指针是什么? 指针理解的2个要点…...
Java加解密(八)工具篇
目录Java加解密实用工具1 OpenSSL2 Keytool3 XCA4 KeyStore ExplorerJava加解密实用工具 1 OpenSSL OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。 例如Apache 使用它加…...
Go框架三件套(Web/RPC/ORM)
🧡 三件套介绍 Gorm Gorm 是一个已经迭代了10年的功能强大的 ORM 框架,在字节内部被广泛使用并且拥有非常丰富的开源扩展。 Kitex Kitex 是字节内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的主要特点,支持多协议并且拥有…...
HR问:假如公司给不到你期望的薪资怎么办?这个问题该如何体面地回答?
对大多数人而言,跳槽就是为了涨薪,工作就是为了挣钱。但如果面试时hr问:假如公司给不到你期望的薪资呢?面对这种问题,该怎么回答才体面?来看一波网友的机智回答:有人委婉拒绝,说“愿…...
LearnOpenGL-高级OpenGL-2.模板测试
本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject 文章目录简单理解模板测试模板介绍模板函数物体轮廓介绍代码给加载的模型添加轮廓简单理解 同深度测试一样…...
网站怎么做sem/网站优化排名金苹果系统
建立一个JDBC应用程序,本教程中以Java连接MySQL为一个示例,分六个步骤进行: 1. 导入包 在程序中包含数据库编程所需的JDBC类。大多数情况下,使用 import java.sql.* 就足够了,如下所示: //STEP 1. Import r…...
wordpress前端编辑器/网站制作推广
运行-〉regedit 打开下面两个位置,根据名称找出要删除的程序右键菜单。 1.[HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers]...所有文件的右键;2.[HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers]...文件夹的右键; 要是不放心可…...
卖主机网站/百度网址安全中心怎么关闭
前言由于目前的工作中,原生app大量嵌入h5页面,很多的功能需要h5来实现,但是由于h5需要从网络加载,在弱网状态或者请求资源大的时候必然出现白屏,再网上搜索后发现并没有一个通用的解决方案,其中VasSonic(手…...
企业网站需要在电信做哪些备案/建个网站需要多少钱?
没有所谓最好的教程,每个人的知识背景不一样,定位自然也不一样的。非要推荐一本的话,个人觉得目前市面上“最好”的一本入门教程之一是《Python编程:入门到实践》。说说我的推荐理由: 这本书虽然是国外作者写的&#x…...
网站建设的维护与更新/宁波网站推广大全
应用场景我们开发的控制台应用,在运行阶段很有可能被用户CtrlC终止或是被用户直接关闭。如果我们不希望用户通过CtrlC终止我们的程序,就需要对CtrlC或关闭事件作处理。处理方法在.net平台下Console类有个CancelKeyPress事件可以处理CtrlC,不过…...
廊坊网站建设技术外包/百度推广登录平台官网
目录 一、安装mongoDB安装包 二、配置 三、启动服务端 四、启动客户端 五、关闭服务端 六、关闭客户端 一、安装mongoDB安装包 1. cd /usr/local 2. mkdir mongodb 3. cd mongodb 4. wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.7.tgz 5. tar…...