【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.mzph.cn/news/850789.shtml

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

相关文章

树莓派 5 AI 套件(Hailo-8L)使用教程

系列文章目录 前言 The Raspberry Pi AI Kit Raspberry Pi AI 套件将 Raspberry Pi M.2 HAT 与 Hailo AI 加速模块捆绑在一起&#xff0c;供 Raspberry Pi 5 使用。套件包含以下内容&#xff1a; 包含神经处理单元&#xff08;NPU&#xff09;的 Hailo AI 模块Raspberry Pi M.…

STM32 proteus + STM32Cubemx仿真教程(第二课按键教程)

文章目录 前言一、STM32按键的原理二、STM32Cubemx创建工程三、proteus仿真电路图四、程序代码编写4.1函数介绍4.2使用按键点亮LED灯 总结 前言 本篇文章开始带大家学习如何使用proteus和STM32Cubemx来完成STM32的学习&#xff0c;第二节课我们先来学习按键的用法。 proteus使…

五款软件推荐:U盘数据不小心删除了?帮你快速找回!

U盘数据不小心删除了怎么恢复&#xff1f;U盘是一种便携式存储设备&#xff0c;因其小巧轻便而广受欢迎。但是&#xff0c;U盘也常常会遇到数据丢失的问题。当U盘数据丢失时&#xff0c;需要找到一款可靠的数据恢复软件来恢复数据。 接下来为大家推荐5款好用的免费U盘数据恢复软…

Python 使用scrapy框架

1、安装scrapy 2、使用scrapy创建项目,在终端命令行 执行如下命令&#xff0c;会创建一个myproject项目 scrapy startproject myproject 3、创建完成后&#xff0c;目录结构如下 4、cd myproject进入项目 ,执行scrapy genspider weather ******&#xff0c;会在spiders下创建…

Incredibuild for Mac 来了!

Mac 开发者在寻找适合自己需求的工具时可能会遇到一些困难&#xff0c;因为 Mac 操作系统相对封闭&#xff0c;不像其他系统那样开放和灵活。尽管如此&#xff0c;Mac 开发者在开发应用程序时的需求&#xff08;比如功能、效率等&#xff09;和使用其他操作系统的开发者是类似的…

Linux中安装Docker,并使用Docker安装MySQL和Redis

1、安装docker 1卸载系统之前的docker yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine2、安装Docker-CE #安装必须的依赖 sudo yum install -y yum-utils \device-map…

LINUX----进程替换,exec族函数

execl族函数的作用 exel族函数用于调用一个已经存在的可执行程序,将该程序的运行需要的代码区和数据区的数据覆盖原进程,这样就可以实现在一个进程中调度另一个进程. 简单实现一个小功能来看一看 mytest.c #include <stdio.h> #include <unistd.h>int main(){print…

抽象的java入门1.3.0

前言&#xff1a; 在1.2.0版本中我们介绍了public class hello {}并从中提取出两个新概 修饰符和作用域 public class hello {public static void main(String[] args) {System.out.println("Hello World");} } 正片&#xff1a; 这一期把剩余的内容刨析出来 pub…

【Redis学习笔记04】Jedis客户端(上)

Java客户端操作Redis Java生态丰富&#xff0c;自定义的客户端非常多&#xff0c;常见的有Jedis、Lettuce、以及Spring整合后的RedisTemplate&#xff0c;但是对于初学者而言&#xff0c;从Jedis开始入门学习是非常容易上手的&#xff0c;因为Jedis中的API与原生Redis命令高度…

Android Bugreport分析工具:ChkBugReport教程

安装&#xff1a; 如果下载地址过期请看原仓库地址的wiki&#xff0c;或许会有更新&#xff1a;https://github.com/sonyxperiadev/ChkBugReport/wiki 提前下载好如下文件&#xff1a; ​​​​​​http://sonyxperiadev.github.io/ChkBugReport/download/chkbugreport (Lau…

一分钟有60秒,这个有趣的原因你知道吗?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

像素坐标系与图像坐标系

前言 在数字图像处理中&#xff0c;经常会看到使用 (x, y) 表示图像中的某个像素点。 在一些图像处理库&#xff0c;例如 Pillow 、OpenCV 、Numpy 中也会使用到坐标系处理图像的像素点。 介绍 无论是像素坐标系还是图像坐标系&#xff0c;其原理都是一样的&#xff1a; 以…

UI学习(二)

UI学习&#xff08;二&#xff09; 文章目录 UI学习&#xff08;二&#xff09;布局子视图手动布局自动布局 导航控制器导航控制器基础导航控制器的切换导航栏工具栏 分栏控制器分栏控制器协议部分的内容UITableView基础部分相关的协议函数高级协议与单元格 多界面传值 布局子视…

2024年6月9日 (周日) 叶子游戏新闻

万能嗅探: 实测 网页打开 某视频号、某音、某红薯、某站&#xff0c;可以做到无水印的视频和封面下载功能哦&#xff0c;具体玩法大家自行发挥吧。 《Funko Fusion》发布新预告 20款影视作品齐聚一堂第三人称动作游戏新作《Funko Fusion》今日发布最新实机演示。该游戏融合了整…

Linxu: Dynamic debug 简介

文章目录 1. 前言2. 什么是 Dynamic debug (dyndbg) ?3. Dynamic debug (dyndbg) 的使用3.1 开启 Dynamic debug (dyndbg) 功能3.2 使用 Dynamic debug (dyndbg) 功能 4. Dynamic debug (dyndbg) 的实现4.1 内核接口 dynamic_pr_debug() 的实现4.2 debugfs 导出控制节点 contr…

力扣hot100学习记录(十二)

94. 二叉树的中序遍历 给定一个二叉树的根节点 root&#xff0c;返回它的中序遍历。 题意 给定一个二叉树&#xff0c;返回它的中序遍历 思路 采用递归的思想&#xff0c;只要根节点不为空&#xff0c;则一直递归遍历左子树&#xff0c;然后将根节点的值存入结果&#xff0c;…

AutoCAD Mechanical机械版专业的计算机辅助设计软件安装包下载安装!

AutoCAD机械版作为一款专业的计算机辅助设计软件&#xff0c;不仅具备卓越的二维绘图功能&#xff0c;更是拥有令人瞩目的3D建模工具&#xff0c;为机械设计师们提供了前所未有的创作空间。 在AutoCAD机械版的3D建模环境中&#xff0c;用户可以借助一系列简洁明了的命令&#…

数智融通 创新发展|亚信科技携AntDB、Data OS与隐私计算产品,赋能企业高质量发展

5月21日&#xff0c;亚信科技在云端举办了一场别开生面的研讨会——“数智融通 创新发展”&#xff0c;聚焦企业数智化升级的前沿话题。资深产品经理和技术架构师们面对面深入交流&#xff0c;分享创新成果与实战案例&#xff0c;共同探索企业数智化转型的新路径。 图1&#xf…

网络安全形势与WAF技术分享

我一个朋友的网站&#xff0c;5月份时候被攻击了&#xff0c;然后他找我帮忙看看&#xff0c;我看他的网站、网上查资料&#xff0c;不看不知道&#xff0c;一看吓一跳&#xff0c;最近几年这网络安全形势真是不容乐观&#xff0c;在网上查了一下资料&#xff0c;1、中国信息通…

基础数据结构 -- 栈

1. 简介 堆栈又名栈&#xff08;stack&#xff09;&#xff0c;他是计算机科学中最基础的数据结构之一。可以算是一种受限制的线性结构&#xff0c;&#xff0c;具有后进先出&#xff08;LIFO&#xff0c; Last In First Out&#xff09;的特性。由于此特性&#xff0c;堆栈常用…