【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:捕捉错误并处理。
  • finallyfinally 语句是可选的,无论异常是否发生、是否匹配、是否被处理,finally 都会执行。

一个 try 至少要有一个 catch 语句,或至少要有 1 1 1finally 语句。finally 不是用来处理异常的,也不会捕获异常,是为了做一些清理工作,如流的关闭、数据库连接的关闭等。

1.3.2 抛出异常

除用 try 语句处理异常外,还可以用 throwthrows 抛出异常。

执行 throw 语句的地方是一个异常抛出点,后面必须是一个异常对象,且必须写在函数中。

throwthrows 的用法见以下代码。

  • 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-Typeapplicaton/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 测试异常处理情况,则抛出下方错误信息:

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32F103单片机工程移植到航顺单片机HK32F103注意事项

一、简介 作为国内MCU厂商中前三阵营之一的航顺芯片&#xff0c;建立了世界首创超低功耗7nA物联网、万物互联核心处理器浩瀚天际10X系列平台&#xff0c;接受代理商/设计企业/方案商定制低于自主研发十倍以上成本&#xff0c;接近零风险自主品牌产品&#xff0c;芯片设计完成只…

《python程序语言设计》2018版第5章第48题以0,0为圆心 绘制10个左右的同心圆

在0&#xff0c;0点处绘制10个圆。 其实这个题先要记住python不会0&#xff0c;0为原点进行绘画。 它是按半径来画&#xff0c;所以我们要先把turtle这个小画笔送到它应该去的起点。&#xff08;我经常有这样的错觉&#xff0c;每次都是这样想办法把自己拉回来&#xff09; 我…

(学习笔记)数据基建-数据安全

&#xff08;学习笔记&#xff09;数据基建-数据安全 数据安全数据安全实施难点数据安全保障流程数据安全措施实施阶段数据安全如何量化产出数据安全思考 数据安全 数据安全问题是最近比较热的话题&#xff0c;数据泄漏引发的用户信任危机事件也比比皆是&#xff0c;以及跨部门…

AWS EMR Serverless

AWS概述 EMR Serverless 简介 在AWS概述一文中简单介绍过AWS EMR, 它是AWS提供的云端大数据平台。借助EMR可以设置集群以便在几分钟内使用大数据框架处理和分析数据。创建集群可参考官方文档&#xff1a;Amazon EMR 入门。但集群创建之后需要一直运行&#xff0c;用户需要管理…

42. 接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1…

Linux——PXE_FTP_EL8

PXE Kickstart &#xff08; el8 &#xff09; 使用两个网口一个用net接口用于下载服务和软件包&#xff0c;另一个为仅主机用于与其他的空主机相连 PXE(preboot execute environment) 预启动执行环境。支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启…

水库大坝安全监测系统打通监控数据“最后一公里”

一、概述 我国有水库8万座左右&#xff0c;其中土石坝多数&#xff0c;病险水库占水库也很多。众所周知&#xff0c;水库在防洪、兴利上具有重要的调节作用&#xff0c;如何保证水库安全&#xff0c;及合理有效的利用水资源&#xff0c;是水利建设者需要探讨的主要内容。科学技…

中国宠业新锐品牌展,2024苏州国际宠物展6月28日开展!

中国宠业新锐品牌展&#xff0c;2024苏州国际宠物展6月28日开展&#xff01; ​ 第2届华东国际宠物用品展览会(苏州)暨中国宠业新锐品牌展&#xff0c;将于6月28日-30日在苏州国际博览中心盛大举办&#xff0c;锁定年中市场黄金档期&#xff0c;同期以“NB展&#xff0c;更新鲜…

未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。.net 读取excel的时候报错(实测有效)

1. 下载AccessDatabaseEngine.exe 下载链接 添加链接描述 2. office excel是64为的需要安装【AccessDatabaseEngine.exe】、32位的【AccessDatabaseEngine_X64.exe】 3. 我的是64为&#xff0c;跳过32位安装检测 1. 找到下载的安装包 2.输入安装包文件全称并在后面加上/pas…

【Android】使用EventBus进行线程间通讯

EventBus 简介 EventBus&#xff1a;github EventBus是Android和Java的发布/订阅事件总线。 简化组件之间的通信 解耦事件发送者和接收者 在 Activities, Fragments, background threads中表现良好 避免复杂且容易出错的依赖关系和生命周期问题 Publisher使用post发出…

晶振十大品牌

晶振是电路的心脏&#xff0c;特别对抖动、稳定度有要求&#xff0c;当然除了稳定度&#xff0c;抖动&#xff0c;还对环境温度有要求&#xff0c;优秀的厂商如下&#xff1a; 链接&#xff1a; 晶振十大品牌-晶振品牌-振荡器品牌-Maigoo品牌榜

【端午安康,给大家讲个“网络”故事,深刻一下!】

牛马我&#x1f434;上周又挨锤了&#xff0c; 网络是不稳定的&#xff0c;博学多知的你可能知道&#xff0c;可能不知道。但假如没亲身经历过&#xff0c;知不知道都不深刻&#xff0c;牛马踩了个网络的坑&#xff0c;深刻了&#xff0c;这里分享下&#xff0c; 一个真相 无…

neo4j入门并使用案例说明

1、neo4j是什么 Neo4j是一个高性能的NoSQL图形数据库&#xff0c;它将结构化数据存储在网络&#xff08;在数学角度称为图&#xff09;上&#xff0c;而不是传统的表中。Neo4j是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎。它因其高性能、轻量级、易嵌入和…

docker安装rabbitmq详解

目录 1、安装 1-1.查看rabbitmq镜像 1-2.下载Rabbitmq的镜像 1-3.创建并运行rabbitmq容器 1-4.查看启动情况 1-5.启动web客户端 1-6.访问rabbitmq的客户端 2..遇到的问题 解决方法: 1、安装 1-1.查看rabbitmq镜像 docker search rabbitmq 1-2.下载Rabbitmq的镜像 拉…

企业应如何选择安全合规的内外网文件摆渡系统?

网络隔离是一种安全措施&#xff0c;旨在将网络划分为不同的部分&#xff0c;以减少安全风险并保护敏感信息。常见的隔离方式像物理隔离、逻辑隔离、防火墙隔离、虚拟隔离、DMZ区隔离等&#xff0c;将网络隔离成内网和外网。内外网文件摆渡通常指在内部网络&#xff08;内网&am…

OrangePi Kunpeng Pro深度评测:性能与体验的完美融合

文章目录 一、引言二、硬件开箱与介绍1.硬件清单2.硬件介绍 三、软件介绍四、性能测试1. 功率测试2. cpu测试2.1 单线程cpu测试2.2 多线程cpu测试 五、实际开发体验1. 搭建API服务器2. ONNX推理测试3. 在线推理平台 五、测评总结1. 能与硬件配置2. 系统与软件3. 实际开发体验个…

144、二叉树的前序递归遍历

题解&#xff1a; 递归书写三要素&#xff1a; 1&#xff09;确定递归函数的参数和返回值。要确定每次递归所要用到的参数以及需要返回的值 2&#xff09;确定终止条件。操作系统也是用栈的方式实现递归&#xff0c;那么如果不写终止条件或者终止条件写的不对&#xff0c;都…

Maven项目的创建

目录 1、Maven简介配置&#xff08;1&#xff09;设置本地仓库&#xff08;2&#xff09;修改Maven的jdk版本&#xff08;3&#xff09;添加国内镜像源添加到idea中 2、常用命令3、IDEA2023创建Maven项目&#xff08;1&#xff09;Maven和Maven Archetype区别&#xff08;1-1&a…

内存管理--3.用幻灯片讲解C++手动内存管理

用幻灯片讲解C手动内存管理 1.栈内存的基本元素 2.栈内存的聚合对象 3.手动分配内存和释放内存 注意&#xff1a;手动分配内存&#xff0c;指的是在堆内存中。 除非实现自己的数据结构&#xff0c;否则永远不要手动分配内存! 即使这样&#xff0c;您也应该通过std::allocator…

rv1126-rv1109-openssh-密码秘钥等功能修改

1.openssh是允许外部登录的工具 2.真的是很复杂的设备 3.移植分布,怎么得到我们想要的openssh 去网上自己寻找安装包下载; 4.怎么预制进arm主板,把编译出来的openssh放进去 其中除了ssh_config和sshd_config;其他都是秘钥,公钥和私钥; root账户走的秘钥的修改,不改是默认的r…