异常场景分析
优质博文:IT-BLOG-CN
为了防止黑客从前台异常信息,对系统进行攻击。同时,为了提高用户体验,我们都会都抛出的异常进行拦截处理。
一、异常处理类
Java
把异常当做是破坏正常流程的一个事件,当事件发生后,就会触发处理机制。Java
有一套独立的异常处理机制,在遇到异常时,方法并不返回任何值(返回值属于正常流程),而是抛出一个封装了错误信息的对象。
Throwable
所有的异常对象都派生于Throwable
类的一个实例。在一个Throwable
里面可以获取如下信息:
■ 获取堆栈跟踪信息。源代码中哪个类,哪个方法,第几行出现了问题……从当前代码到最底层的代码调用链都可以查出来。追踪获取底层的异常信息。
■ 获取没抛出来的其他Throwable
。一次只能抛出一个异常,如果发生了多个异常,其他异常就不会被抛出,这时可以通过加入suppressed
异常列表来解决(JDK7 以后才有)
Throwable
类只有两个直接继承者:Error
和Exception
。然后Exception
又分为RuntimeException
和CheckedException
。
Error
在Java
中, 由系统环境问题引起的异常,一般都继承于 Error 类。对于Error
类:
■ 一般开发者不要自定义Error
子类,因为它代表系统级别的错误。与一般的程序无关。
■ 在Java
异常处理机制中,Error
不强制捕获或声明,也就是不强制处理。因为程序本身对此类错误无能为力。一般情况下我们只要把堆栈跟踪信息记录下来就行。
Exception
在Java
中,除了系统环境问题引起的异常,一般都继承于Exception
类。Exception
分为RuntimeException
和CheckedException
。CheckedException
必须要捕获或声明。而RuntimeException
不强制。
CheckedException
: 在Java
中,直接或间接因为“资源”问题引起的异常,一般属于检查异常CheckedException
。检查异常继承于Exception
,而不继承于RuntimeException
。对于检查异常:
■ 必须捕获或声明
■ 交给关心这个异常的方法处理
■ 异常处理器应该引导用户接下来怎么办,至少做到安全退出
RuntimeException
: 在Java
中,由于接口方法使用不当造成的异常,一般属于RuntimeException
,也就是运行时异常。对于RuntimeException
:
■ 如果你调用服务方法的方式不正确,你应该马上修改代码,避免发生RuntimeException
■ 如果是用户方法调用你的方法的方式不正确,你应该立刻抛出RuntimeException
,强制让使用者修正代码或改变使用方式,防止问题蔓延
■ 一般情况下,不要捕获或声明RuntimeException
。因为问题在于你的程序本身有问题,如果你用异常流程处理了,反而让正常流程问题一直存在
Uncheck Exception
Error
和RuntimeException
统称为非检查异常。两者的共同点就是都不被强制捕获或声明。实际上两者描述问题的范围完全没有交集。
二、Java 异常处理机制
【1】抛出异常: 当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
【2】捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着 Java 程序的终止。
对于运行时异常、错误或可查异常,Java 技术所要求的异常处理方式有所不同。
■ 由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java 规定,运行时异常将由 Java 运行时系统自动抛出,允许应用程序忽略运行时异常。
■ 对于方法运行中可能出现的 Error,当运行方法不欲捕捉时,Java 允许该方法不做任何抛出声明。因为,大多数 Error 异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
■ 对于所有的可查异常,Java 规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
■ 能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者 Java 运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是 Java 代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
■ 任何 Java 代码都可以抛出异常,如:自己编写的代码、来自 Java 开发环境包中代码,或者 Java 运行时系统。无论是谁,都可以通过 Java 的 throw 语句抛出异常。
■ 从方法中抛出的任何异常都必须使用 throws 子句。捕捉异常通过 try-catch 语句或者 try-catch-finally 语句实现。
总体来说,Java 规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的 RuntimeException 和 Error。
捕获异常
【1】try-catch 语句:在 Java 中,异常通过 try-catch 语句结束。关键词 try 后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java 方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由 Java 运行时系统试图寻找匹配的 catch 子句以捕获异常。若有匹配的 catch 子句,则运行其异常处理代码,try-catch 语句结束。
匹配的原则是:如果抛出的异常对象属于 catch 子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与 catch 块捕获的异常类型相匹配。
需要注意的是,一旦某个 catch 捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个 try-catch 语句结束。其他的 catch 子句不再有匹配和捕获异常类型的机会。对于有多个 catch 子句的异常程序而言,应该尽量将捕获底层异常类的 catch 子句放在前面,同时尽量将捕获相对高层的异常类的 catch 子句放在后面。否则,捕获底层异常类的 catch 子句将可能会被屏蔽。
【2】try-catch-finally 语句:try-catch 语句还可以包括第三部分,就是 finally 子句。它表示无论是否出现异常,都应当执行的内容。
无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。在以下 4 种特殊情况下,finally 块不会被执行:
■ 在 finally 语句块中发生了异常。
■ 在前面的代码中用了 exit()退出程序。
■ 程序所在的线程死亡。
■ 关闭 CPU。
三、全局异常处理
编写一个异常拦截类,如下:@ControllerAdvice
,顾名思义,这是一个增强的Controller
。使用这个Controller
,可以实现三个方面的功能:①、全局异常处理;②、全局数据绑定;③、全局数据预处理;灵活使用这三个功能,可以帮助我们简化很多工作,需要注意的是,这是SpringMVC
提供的功能,在SpringBoot
中可以直接使用,下面分别来看。
import com.edu.tools.R;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** @description:* @author: zzx* @createDate: 2020/6/2* @version: 1.0*/
@ControllerAdvice
public class GlobalExceptionHandler {//很重要,括号类制定需要拦截的异常,也可以进行定制化@ExceptionHandler(Exception.class)@ResponseBodypublic R error(Exception e){e.printStackTrace();//R表示我们给前端返回的接口格式return R.error().message("执行全局异常处理。。。");}
}
测试:
四、自定义异常处理
【1】创建自定义异常类继承RuntimeException
类。
/*** @description: 自定义异常类,包含了有参合无参构造器* @author: zzx* @createDate: 2020/6/2* @version: 1.0*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BusinessException extends RuntimeException {private Integer code;//状态码private String msg;//异常消息
}
【2】将自定义的异常类添加到拦截的Handler
中
/*** @description:* @author: zzx* @createDate: 2020/6/2* @version: 1.0*/
@ControllerAdvice
public class GlobalExceptionHandler {//拦截自定义异常@ExceptionHandler(BusinessException.class)@ResponseBodypublic R error(BusinessException e){e.printStackTrace();return R.error().code(e.getCode()).message(e.getMsg());}
}
【3】在业务代码根据需求进行手动抛出即可,业务代码展示:throw new BusinessException
(20001,“手动异常抛出”);
/*** <p>* 讲师 前端控制器* </p>** @author zhengzhaoxiang* @since 2020-06-01*/
@RestController
@RequestMapping("/eduservice/edu-teacher")
public class EduTeacherController {@Autowiredprivate EduTeacherService eduTeacherService;/*** @Description 获取所有数据* @Author zhengzhaoxiang* @Date 2020/6/2 15:27* @Param []* @Return void*/@GetMapping("findAll")public R findAll(){List<EduTeacher> list = eduTeacherService.list(null);try{int i = 1/0;} catch (Exception e){//手动抛出异常throw new BusinessException(20001,"手动异常抛出");}return R.ok().data("items",list);}
}
自定义异常处理类测试:
五、案例
某日11点23分 xxx处理中量(5s)智能检测发现异常下降60%
事后分析得知其根因是: 修改模板配置时,多配了个占位符%S
导致字符串格式化的方法出错,程序未进行异常捕获,输入页加载查询接口失败,前端页面进行降级,关闭了入口,影响用户操作。
研发团队给出的解决方案:针对读取配置文案异常需要进行捕获降级,不能影响业务主流程。
案例分析
针对这类错误,以往的解决方案通常是打补丁式的修正,即:针对已发生异常的配置项进行容错处理(对解析函数添加try…catch
,如上方)。
然而,每一次异常几乎都是发生在不同的配置上,也就是说我们的补丁对于生产事件的产生几乎没有任何抑制作用。补丁式修正只能治标而不能治本,我们需要一种能治本的方案。下面就让我来给大家介绍这么一种方案(如果您有更好的方案,望不吝赐教)
最佳实践
程序初始化时将所有配置读取并解析后保存为本地变量,应用每次直接读取本地Config
变量。监听QConfig
,当配置发生变化时调用步骤1的方法重新解析配置文件。如果解析时发生异常,记录错误日志/报警,并使用旧的配置。示例代码:
public class ConfigStatic {private static final Logger LOGGER = LoggerFactory.getLogger(ConfigStatic.class);private static ConfigStatic instance = new ConfigStatic();private static final String TITLE = "ConfigStatic";private final boolean initializeSuccess;static {// 将ConfigStatic.refresh注册至ConfigurationFunc,当配置发生变化的时候ConfigStatic.refresh将被调用ConfigurationFunc.registerListener(TITLE, ConfigStatic::refresh);}private ConfigStatic() {initializeSuccess = initialize();}public static ConfigStatic getInstance() {return instance;}private static void refresh() {// 创建新配置(构造函数会调用initialize进行初始化)ConfigStatic newConfig = new ConfigStatic();if (newConfig.initializeSuccess) {// 如果新实例初始化成功,将其替换为instanceinstance = newConfig;}}private Set<Integer> hsFcAddjustPriceAgencyId;// 此处省略其他配置...private boolean initialize() {final String title = "ConfigStatic.initialize";try {this.directCompareNormalAirlines = ConfigurationFunc.getHashSet("yPlusXProductConfig", ",");// 此处省略其他配置...return true;} catch (Exception ex) {LogManager.build(title, ex).error();return false;}}
}
相关文章:
异常场景分析
优质博文:IT-BLOG-CN 为了防止黑客从前台异常信息,对系统进行攻击。同时,为了提高用户体验,我们都会都抛出的异常进行拦截处理。 一、异常处理类 Java把异常当做是破坏正常流程的一个事件,当事件发生后,…...
Leetcode: 0001-0010题速览
Leetcode: 0001-0010题速览 本文材料来自于LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解 遵从开源协议为知识共享 版权归属-相同方式…...
计算机的错误计算(一百一十二)
摘要 计算机的错误计算(六十三)与(六十八)以及(六十九)分别探讨了大数与 附近数以及 附近数 的余切函数的计算精度问题。本节讨论余切序列(即迭代 )的计算精度问题。 余切序列是指…...
C++基础(7)——STL简介及string类
目录 1.STL简介 1.1什么是 1.2STL的历史版本 1.3STL的六大组件 编辑 1.4有用的网址 2.string类 2.1string的多种定义方式 2.2string的插入 2.2.1尾插(push_back) 2.2.2insert插入 2.3拼接(append) 2.4删除 2.4.1尾…...
配置Nginx以支持通过HTTPS回源到CDN
要配置Nginx以支持通过HTTPS回源到CDN,你需要确保Nginx已正确配置SSL,并且能够处理来自CDN的HTTPS请求。以下是一个简化的Nginx配置示例,它配置了SSL并设置了代理服务器参数以回源到CDN: server {listen 443 ssl;server_name you…...
yolov10+strongsort的目标跟踪实现
此次yolov10deepsort不论是准确率还是稳定性,再次超越了之前的yolodeepsort系列。 yolov10介绍——实时端到端物体检测 YOLOv10 是清华大学研究人员在 UltralyticsPython 清华大学的研究人员在 YOLOv10软件包的基础上,引入了一种新的实时目标检测…...
C# 字符与字符串
本课要点: 1、字符类Char的使用 2、字符串类String的使用 3、可变字符串****StringBuilder 4、常见错误 一 何时用到字符与字符串 问题: 输出C#**课考试最高分:**98.5 输出最高分学生姓名:张三 输出最高分学生性别&#x…...
在Ubuntu 16.04上使用LEMP安装WordPress的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 WordPress 是互联网上最流行的 CMS(内容管理系统)。它允许您在 MySQL 后端和 PHP 处理的基础上轻松设置灵…...
显示器放大后,大漠识图识色坐标偏移解决方法
原因分析: 显示器分辨率较高,DPI设置放大125% or 150% or 200%,游戏打开时也会默认会根据显示器的放大比例自行放大,但是大漠综合管理工具抓图不会放大; 解决方法: 1、大漠综合管理…...
C++容器之list基本使用
目录 前言 一、list的介绍? 二、使用 1.list的构造 2.list iterator的使用 3.list capacity 🥇 empty 🥇size 4.list element access 🥇 front 🥇 back 5.list modifiers 🥇 push_front 🥇 po…...
Redis-哨兵
概念 Redis Sentinel 相关名词解释 注意: 哨兵机制不负责存储数据,只是对其它的redis-server进程起到监控的作用哨兵节点,也会搞一个集合,防止一个挂了 ⼈⼯恢复主节点故障 用户监控: 实际开发中,对于服务器后端开发,监控程序,是很重要的 服务器长期运行,总会有一些意外,…...
Pikachu-Sql-Inject - 基于时间的盲注
基于时间的盲注: 就是前端的基于time 的盲注,什么错误信息都看不到,但是还可以通过特定的输入,判断后台的执行时间,从而确定注入。 mysql 里函数sleep() 是延时的意思,sleep(10)就是数据库延时10 秒返回内…...
JAVA开源项目 旅游管理系统 计算机毕业设计
本文项目编号 T 063 ,文末自助获取源码 \color{red}{T063,文末自助获取源码} T063,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…...
景联文科技入选《2024中国AI大模型产业图谱2.0版》数据集代表厂商
近日,大数据产业领域头部媒体数据猿携手上海大数据联盟联合发布了备受瞩目的《2024中国AI大模型产业图谱2.0版》。以大数据与AI为代表的智能技术为主要视角,聚焦全产业链,为业内提供更为专业直观的行业指导。 景联文科技凭借高质量数据集&…...
【C语言】内存函数的使用和模拟实现
文章目录 一、memcpy的使用和模拟实现二、memmove的使用和模拟实现三、memset的使用四、memcmp的使用 一、memcpy的使用和模拟实现 在之前我们学习了使用和模拟实现strncpy函数,它是一个字符串函数,用来按照给定的字节个数来拷贝字符串,那么问…...
在WPF中实现多语言切换的四种方式
在WPF中有多种方式可以实现多语言,这里提供几种常用的方式。 一、使用XML实现多语言切换 使用XML实现多语言的思路就是使用XML作为绑定的数据源。主要用到XmlDataProvider类. 使用XmlDataProvider.Source属性指定XML文件的路径或通过XmlDataProvider.Document指定…...
30min 的OpenCV learning Note
1.安装python和pycharm与环境搭配 打开Windows终端:(winR)(一般使用清华镜像网站安装库比较快) pip install opencv-contrib-python -i https://pypi.mirrors.ustc.edu.cn/simple 或者 python -m pip install open…...
C--编译和链接见解
欢迎各位看官!如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论 感谢各位看官的支持!!! 一:翻译环境和运行环境 在ANSIIC的任何一种实现中,存在两个不同的环境1,…...
【QT Quick】基础语法:基础类与控件
QML 的基础类和控件中,我们可以看到主要的几个分类:基础控件类、窗口类以及组件类。以下是对这些控件及其属性、继承关系等的详细讲解: 控件关系总结 QtObject 是所有 QML 对象的基类。它定义了基础属性,主要用于逻辑和数据封装…...
使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南
使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南 本文详细介绍了如何在 2375 端口未开放的情况下,通过 SSH 连接 Docker 服务器并在 Idea 中进行开发。通过修改用户权限、生成密钥对以及配置 SSH 访问,用户可以安全地远程操作…...
Gas费用是什么?
Gas费用是什么? 每5个Byte 需要1个GasGasLimit 用来限制合约最多执行多少次运算GasPrice 每次计算需要支付的费用在Web3的语境中,尤其是在以太坊(Ethereum)这样的区块链平台上,Gas费是一个核心概念。以下是关于Gas费的详细解释: 1. 定义 Gas是以太坊网络上的计算单位,…...
大语言模型(LLM)的子模块拆拆分进行联邦学习;大语言模型按照多头(Multi-Head)拆分进行联邦学习
目录 大语言模型(LLM)的子模块拆拆分进行联邦学习 方式概述 简单示例 大语言模型按照多头(Multi-Head)拆分进行联邦学习 场景设定 多头拆分与联邦学习 示例说明 大语言模型(LLM)的子模块拆拆分进行联邦学习 大语言模型(LLM)的子模块拆分进行联邦学习,主要涉及…...
Qt 概述
1. Qlabel HelloWorld 程序 使用纯代码实现 // widget.cpp Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 给当前这个lable对象,指定一个父对象QLabel* label new QLabel(this);// C语言风格的字符串可以直接…...
移动应用的界面配置-手机银行APP
设置登录界面为线性布局,组件垂直居中排列设置主页为滚动模式,包括布局、添加背景图片设置按钮样式,包括形状、边框线的宽度和颜色 设置登录界面 设置界面为线性布局,组件垂直居中排列 --android:gravity"center_vertical…...
微服务nginx解析部署使用全流程
目录 1、nginx介绍 1、简介 2、反向代理 3、负载均衡 2、安装nginx 1、下载nginx 2、解压nginx安装包 3、安装nginx编辑 1、执行configure命令 2、执行make命令 4、启动nginx 1、查找nginx位置并启动 2、常用命令 3、反向代理 1、介绍反向代理配置 1、基础配置…...
华硕天选笔记本外接音箱没有声音
系列文章目录 文章目录 系列文章目录一.前言二.解决方法第一种方法第二种方法 一.前言 华硕天选笔记本外接音箱没有声音,在插上外接音箱时,系统会自动弹出下图窗口 二.解决方法 第一种方法 在我的电脑上选择 Headphone Speaker Out Headset 这三个选项…...
Unity中Socket_TCP异步连接,加入断线检测以及重连功能
1、服务端 using System; using System.Collections.Generic; using System.Text; #region 命名空间 using System.Net; using System.Net.Sockets; using System.Threading; using UnityEngine; #endregionnamespace AsynServerConsole {/// <summary>/// Tcp协议异步通…...
Android build子系统(01)Ninja构建系统解读
说明:本文将解读Ninja构建系统,这是当前Android Framework中广泛使用的构建工具。我们将从Ninja的起源和背景信息开始,逐步解读Ninja的优势和核心原理,并探讨其一般使用场景。然后介绍其在Android Framework中的应用及相关工具&am…...
徐老师的吉祥数
题目背景 文件读写 输入文件avoid.in 输出文件avoid.out 限制 1000ms 512MB 题目描述 众所周知, 3这个数字在有些时候不是很吉利,因为它谐音为 “散” 所以徐老师认为只要是 3的整数次幂的数字就不吉利 现在徐老师想知道,在某个范围[l,r] …...
使用html写一个能发起请求的登录界面
目录 head部分 内联样式部分 body部分 login-form类的div myModal类的div id script部分 总的代码 界面与操作演示 <!DOCTYPE html> <html lang"en"> <!DOCTYPE html> 这是文档类型声明,告诉浏览器这是一个 HTML文档。 <…...
制作游戏需要学什么/廊坊seo外包公司费用
泽塔奥特曼是最近很火的新生代奥特曼,他需要借用其他奥特曼的力量才能和怪兽对抗,单凭泽塔奥特曼本身,发挥的力量根本不够。最近,泽塔奥特曼的新形态非常拉风。“德尔塔天爪”形态借用了“捷德奥特曼”“贝利亚奥特曼”和“赛罗奥…...
网站是做百度快照推广好/网站关键词排名批量查询
1. 安装 这里以安装hadoop-0.20.2为例 先安装java,参考这个 去着下载hadoop 解压 tar -xzf hadoop-0.20.22. 配置 修改环境变量 vim ~/.bashrc export HADOOP_HOME/home/rte/hadoop-0.20.2 #这里为实际hadoop解压的目录位置 export PATH$PATH:$HADOOP_HOME/bin source ~/.bas…...
山东高端网站建设服务商/百度权重排名查询
由于目前用户使用测试计划时选择的用例数较多(1000条),测试计划执行时间经常需要3000秒,也就是执行一个测试计划在30min - 60min,甚至更多 准备通过执行策略优化测试计划执行的所需要的时间,提高效率 执行…...
天津百度网站排名优化/深圳网站建设优化
使用 NumPy 随机生成矩阵 在科学计算领域中,随机数生成是一种常见的需求。在 Python 中,NumPy 库提供了众多生成随机矩阵的函数,可以轻松地实现随机数生成。本文将详细介绍 NumPy 中生成随机矩阵的各种方法。 np.random.rand()np.random.rand() 函数用于返回 [0, 1) 之间的…...
网站公安备案咨询电话/专门做推广的公司
一、首先需要先取消保护 必须CtrlA,然后右键单元格格式,解锁所有单元格 二、给指定的行或列设置保护 三、将这几行保护,选择锁定 四、验证效果 此时完成...
县新闻网站建设方案/网站页面的优化
语法定义 用abstract关键字修饰的类,则该类就是抽象类应用场景 a、在某些情况下,某个父类只知道其子类应该具有怎样的方法, 但无法准确知道子类如何实现这些方法,即:约束子类应该具有哪些方法。 b、从多个具有相同…...