SSM整合(三) | 异常处理器 - 项目异常的处理方案

news2024/10/6 12:25:02

文章目录

    • 异常处理器
      • 异常处理器快速入门
      • 项目异常处理

异常处理器

异常处理器快速入门

程序开发过程中不可避免的会遇到异常现象

在这里插入图片描述

出现异常现象的常见位置与常见原因如下

框架内部抛出的异常:因使用不规范导致

数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)

业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)

表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)

工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)

各个层级均出现异常,异常处理代码书写在哪一层都是不合适的

当出现异常, 我们让每一层的异常都不处理往上一层抛出, 所有的异常均抛出到表现层进行处理

表现层处理异常,如果每个方法中都单独书写try…catch…,代码书写量巨大且意义不强

采用AOP思想解决

SpringMVC提供了异常处理器:

集中的、统一的处理项目中出现的异常; 既然最终异常是在表现层进行统一处理, 那么我们异常处理器的类也需要写在表现层controller包下

@RestControllerAdvice类注解

定义在Rest风格开发的控制器增强类定义上方, 为Rest风格开发的控制器类做增强, 此注解自带@ResponseBody注解与@Component注解,具备对应的功能

@ExceptionHandler方法注解:

专用于异常处理的控制器方法上方, 用于设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行; 此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常

@RestControllerAdvice // 声明该类是用来做异常处理的
public class ProjectExceptionAdvice {
    @ExceptionHandler(Exception.class) // 声明该方法是拦截所有异常
    public Result doException(Exception ex) {
        // 返回异常提示
        return new Result(666, null, "出现异常");
    }
}

项目异常处理

项目中的异常不能和上面的处理方式一样

项目异常分类:

业务异常(BusinessException)

  • 规范的用户行为产生的异常
  • 不规范的用户行为操作产生的异常

系统异常(SystemException)

  • 项目运行过程中可预计且无法避免的异常, 例如服务器断电死机等

其他异常(Exception)

  • 编程人员未预期到的异常

项目异常处理方案:

针对业务异常(BusinessException): 发送对应消息传递给用户,提醒规范操作

针对系统异常(SystemException):

  • 发送固定消息传递给用户,安抚用户
  • 发送特定消息给运维人员,提醒维护
  • 记录日志

针对其他异常(Exception):

  • 发送固定消息传递给用户,安抚用户
  • 发送特定消息给编程人员,提醒维护(纳入预期范围内)
  • 记录日志

使用步骤:

  1. 创建一个exception包, 在该包下分别创建业务异常类和系统异常类:

创建业务异常类BusinessException继承自RuntimeException类

public class BusinessException extends RuntimeException {
    // 添加一个编号用于识别异常
    private Integer 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;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

创建系统异常SystemException继承自RuntimeException类

public class SystemException extends RuntimeException{
    // 添加一个编号用于识别异常
    private Integer 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 Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}
  1. 自定义异常编码(持续补充)
public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer SELECT_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer SELECT_ERR = 20040;

    public static final Integer SYSTEM_ERROR = 50001; // 系统异常
    public static final Integer SYSTEM_TIMEOUT_ERROR = 50002; // 请求超时
  public static final Integer SYSTEM_UNKNOW_ERROR = 59999; // 系统未知异常
    public static final Integer BUSINESS_ERROR = 60001; // 业务异常
}
  1. 触发自定义异常: 将可能出现的转换为自定义异常

示例: 使用系统异常

@GetMapping("/{id}")
public Result selectById(@PathVariable Integer id) {
    try {
        int i = 1/0;
    } catch (Exception e) {
        throw new SystemException(Code.SYSTEM_TIMEOUT_ERROR, "服务器访问超时, 请稍后重试", e);
    }

    Book book = bookService.selectById(id);
    boolean flag = book != null;
    Integer code = flag ? Code.SELECT_OK: Code.SELECT_ERR;
    String msg = flag ? "": "数据查询失败, 请重试!";
    return new Result(code, book, msg);
}

示例: 使用业务异常

@GetMapping("/{id}")
public Result selectById(@PathVariable Integer id) {
    if (id < 0) {
        throw new BusinessException(Code.BUSINESS_ERROR, "请进行合法的操作");
    }

    Book book = bookService.selectById(id);
    boolean flag = book != null;
    Integer code = flag ? Code.SELECT_OK: Code.SELECT_ERR;
    String msg = flag ? "": "数据查询失败, 请重试!";
    return new Result(code, book, msg);
}
  1. 处理器拦截系统异常和业务异常并处理
@RestControllerAdvice // 声明该类是用来做异常处理的
public class ProjectExceptionAdvice {
    @ExceptionHandler(SystemException.class) // 拦截系统异常
    public Result doSystemException(SystemException e) {
        // 记录日志...
        // 发送消息给运维...
        // 发送邮件给开发人员..
        // 返回异常提示
        return new Result(e.getCode(), null, e.getMessage());
    }

    @ExceptionHandler(BusinessException.class) // 拦截业务异常
    public Result doBusinessException(BusinessException e) {
        // 返回异常提示
        return new Result(e.getCode(), null, e.getMessage());
    }

    @ExceptionHandler(Exception.class) // 其他异常: 拦截所有的异常
    public Result doException(Exception ex) {
        // 记录日志...
        // 发送消息给运维...
        // 发送邮件给开发人员..
        // 返回异常提示
        return new Result(Code.SYSTEM_UNKNOW_ERROR, null, "系统繁忙请稍后再试");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479430.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据&#xff0c;你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块&#xff0c;它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中&#xff0c;我们将介绍 statsmodel 库的基础知识、如何…

【技巧】Excel序号设置自动更新

做Excel表格的时候&#xff0c;我们经常需要设置序号&#xff0c;在输入序号的时候&#xff0c;你是不是这样做&#xff1f;手动输入序号1&#xff0c;再向下填充&#xff0c;当遇到有不想要的内容&#xff0c;点删除后&#xff0c;发现中间的序号就不连贯了&#xff0c;再手动…

二十五、OSPF高级技术——开销值、虚链路、邻居建立、LSA、多进程

文章目录 调试指令&#xff08;三张表&#xff09;1、邻居表&#xff1a;dis ospf peer brief2、拓扑表&#xff08;链路状态数据库&#xff09;&#xff1a;dis ospf lsdb3、路由表&#xff1a;dis ip routing-table 一、OSPF 开销值/度量值&#xff08;cost&#xff09;1、co…

代码审计笔记之开篇

思想 代码审计是从软件测试发展而来&#xff0c;早起一般采用常规软件测试与渗透测试的手段来发现源码漏洞&#xff0c;但是随着软件规模的越来越大&#xff0c;架构越来越复杂&#xff0c;安全漏洞和后门也越来越多越来越隐蔽&#xff0c;这使得传统的软件测试方法很难检出源…

【Java入门合集】第二章Java语言基础(一)

【Java入门合集】第二章Java语言基础&#xff08;一&#xff09; 博主&#xff1a;命运之光 专栏JAVA入门 学习目标 掌握变量、常量、表达式的概念&#xff0c;数据类型及变量的定义方法&#xff1b; 掌握常用运算符的使用&#xff1b; 掌握程序的顺序结构、选择结构和循环结构…

C/C++每日一练(20230501)

目录 1. 对链表进行插入排序 &#x1f31f;&#x1f31f; 2. 找出小于平均值的数 ※ 3. 二叉树的最大深度 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 对链表进行…

【五一创作】Apollo(入门)

Apollo(入门) Quick Start 配置中心是一种统一管理各种应用配置的基础服务组件 Apollo&#xff08;阿波罗&#xff09;是携程框架部门研发的分布式配置中心&#xff0c;能够集中化管理应用不同环境、不同集群的配置&#xff0c;配置修改后能够实时推送到应用端&#xff0c;并且…

Springboot 实战一个依赖解决XSS攻击

1. 什么是XSS介绍 XSS: Cross Site Scripting&#xff0c;为不和层叠样式表(Cascading Style Sheets, CSS) 的缩写混淆&#xff0c;故将跨站脚本攻击缩写为XSS。 恶意攻击者往Web页面里插入恶意Script代码&#xff0c;当用户浏览该页之时&#xff0c;嵌入其中 Web里面的Scrip…

【高并发】并发数据结构与多核编程

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于多处理器编程的艺术进行的&#xff0c;每个知识点的修正和深入主要…

【JavaEE初阶】认识线程(Thread)

目录 &#x1f33e; 前言 &#x1f33e; 了解线程 &#x1f308;1.1 线程是什么&#xff1f; &#x1f308;1.2 一些基本问题 &#x1f33e;2、创建线程的方式 &#x1f308; 2.1 继承Thread类 &#x1f308; 2.2 实现Runnable接口并重写run()方法 &#x1f308; 注意…

有哪些好的学习方法?学霸们自己在用,却不愿意透露的

临近期末,很多家长都在跟我咨询,怎么才能提升孩子的学习效率? 原因就是,每天看着自己的孩子学习到深夜,但不少内容还是记不住, 学习和复习的效果非常的不理想。 今天,给大家分享的方法,是我自己一直也都在用的方法,效果非常的棒。 学长Ron,江苏某省重点高中毕业,高…

给公司搭建一个人才库系统,前台(信息填写+简历上传)后台(筛选功能+下载简历)

首先指出目前代码的不足之处&#xff1a; 如果公司使用&#xff0c;代码还存在风险问题&#xff0c;需要增加防火墙、防PHP攻击、后台加验证等操作 以下指南&#xff1a; 1.Mod Security 和 Fail2Ban 是开源的安全软件&#xff0c;您可以在宝塔面板上安装和配置这些软件来增强您…

【JUC】ThreadLocal

【JUC】ThreadLocal 文章目录 【JUC】ThreadLocal1. 概述2. Thread、ThreadLocal、ThreadLocalMap 关系2.1 Thread 和 ThreadLocal2.2 ThreadLocal 和 ThreadLocalMap2.3 三者之间的关系 1. 概述 ThreadLocal 提供线程局部变量。这些变量与正常的变量不同&#xff0c;因为每一…

Java 基础入门篇(一)—— Java 概述

文章目录 一、Java 概述二、Java 的产品 JDK2.1 JDK 安装2.2 Java与 Javac 介绍2.3 Java 程序的开发步骤 三、Java 程序的执行原理四、JDK 的组成五、Java 的跨平台工作原理 一、Java 概述 Java 是 sun 公司在 1995 年推出的一门计算机高级编程语言&#xff0c;其语言风格接近人…

音视频技术开发周刊 | 291

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 谷歌将 AI 芯片团队并入云计算部门 追赶微软和亚马逊 OpenAI推出的ChatGPT获得一定成功&#xff0c;微软是OpenAI的重要投资者&#xff0c;它将ChatGPT植入必应搜索&#…

Java 基础入门篇(三)—— 数组的定义与内存分配

文章目录 一、数组的定义1.1 静态初始化数组1.2 动态初始化数组1.3 数组的访问 二、数组的遍历三、数组的内存图 ★3.1 Java 的内存分配3.2 数组的内存图3.3 两个数组变量指向同一个数组对象 四、数组使用的常见问题补充&#xff1a;随机数 Random 类 一、数组的定义 数组就是…

机器视觉工程师职场四点“心态>交流=思路>知行合一”

视觉人机器视觉团队,他们热爱机器视觉行业,爱学习,爱分享。这一路上,首先感谢粉丝们805天一如既往的支持。我想团队拥有这些粉丝,是富有的,也是我们一直创作的动力。 是否记得毕业季,自己的豪言壮语。希望你毕业三年后,无论结果如何,不忘初心,继续前行。 机器视觉工程…

Dart - 爬取Android Studio历史版本信息

文章目录 前言开发环境开发过程1. 遵循robots协议2. 页面结构分析3. Dart项目创建4. Dart项目运行与调试5. 第三库依赖6. 项目完整源码 运行结果最后 前言 整理Android Studio历史版本信息时发现有点多&#xff0c;于是想一劳永逸写一个简单的爬虫抓取一下数据并生成我想要的格…

【ansys】网格划分-优化、改善网格质量、修复网格、减小skewness、增大Orthogonal Quality的技巧

一、分析几何结构网格划分拓扑关系&#xff0c;调整网格尺寸 优化策略1&#xff1a;如果发现质量差的网格单元聚集在某一个实体附近&#xff0c;基本说明是这个实体的网格划分定义存在优化的地方。 例如下面这个几何模型。一个薄壁状长方体&#xff0c;加上一个模具框架&#x…

代码优美,搬砖不累:探索高质量代码之路

一、 前言 写出高质量代码是每个程序员的追求&#xff0c;也是提高自己编程能力的必经之路。高质量的代码可以提高软件的可维护性、可读性、可扩展性和可移植性等&#xff0c;降低软件开发和维护的成本。本文将介绍一些如何写出高质量代码的实用技巧和方法。 二、高质量代码的…