【Spring Boot】异常处理

news2024/12/25 1:01:58

异常处理

  • 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为空
    @Override
    public String getErrorPath() {
        return null;
    }

    //一定要添加url映射,指向error
    @RequestMapping
    public 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")
    @ResponseBody
    public 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.coloradmin.cn/o/1806557.html

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

相关文章

【小沐学Python】Python实现Web服务器(CentOS下打包Flask)

文章目录 1、简介2、下载Python3、编译Python4、安装PyInstaller5、打包PyInstaller6、相关问题6.1 ImportError: urllib3 v2 only supports OpenSSL 1.1.1, currently the ssl module is compiled with OpenSSL 1.0.2k-fips 26 Jan 2017. See: https://github.com/urllib3/url…

seerfar选品功能,OZON运营插件工具seerfar

在当今这个数字化、信息化的时代&#xff0c;电子商务的飞速发展使得越来越多的商家开始关注如何更高效地运营自己的在线店铺。其中&#xff0c;选品作为电商运营的重要一环&#xff0c;直接影响着店铺的流量、转化率和利润。在OZON这样的电商平台上&#xff0c;如何快速、准确…

Incredibuild for Mac 来了!

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

联合体和枚举<C语言>

导言 在C语言中除了结构体外&#xff0c;联合体和枚举也是自定义类型&#xff0c;联合体主要用于节省空间&#xff0c;在同一块内存存储多种类型的数据&#xff0c;而枚举可以提高代码的可读性、可维护性。 联合体&#xff08;union&#xff09; 它还有个更容易理解的名字&…

Triton学习笔记

b站链接&#xff1a;合集Triton 从入门到精通 文章目录 算法名词解释&#xff1a;scheduler 任务调度器model instance、inference和requestbatching 一、Triton Inference Server原理1. Overview of Trition2. Design Basics of Trition3. Auxiliary Features of Trition4. A…

C语言:定义和使用结构体变量

定义和使用结构体变量 介绍基础用法1.定义结构体2. 声明结构体变量3. 初始化和访问结构体成员4. 使用指针访问结构体成员5. 使用结构体数组 高级用法6. 嵌套结构体7. 匿名结构体8. 结构体和动态内存分配9. 结构体作为函数参数按值传递按引用传递 介绍 在C语言中&#xff0c;结…

找出链表倒数第k个元素-链表题

LCR 140. 训练计划 II - 力扣&#xff08;LeetCode&#xff09; 快慢指针。快指针臂慢指针快cnt个元素到最后&#xff1b; class Solution { public:ListNode* trainingPlan(ListNode* head, int cnt) {struct ListNode* quick head;struct ListNode* slow head;for(int i …

抓住时机的核心:坚持学习准备着

在这个快节奏的时代&#xff0c;时间对于每个人来说都是宝贵的。能否在合适的时间做正确的事情&#xff0c;往往决定了我们成功的概率。但同时&#xff0c;我们也要认识到&#xff0c;逆风翻盘虽少&#xff0c;却并非不可能。在这个过程中&#xff0c;投资自己&#xff0c;投资…

【python】错误SyntaxError: invalid syntax的解决方法总结

解决Python报错&#xff1a;【Python】错误SyntaxError: invalid syntax的解决方法总结 SyntaxError是Python编程中常见的错误之一&#xff0c;它表明代码中有语法错误。这种错误可能由多种原因引起&#xff0c;包括但不限于拼写错误、错误的缩进、缺少括号等。本文将介绍几种常…

1-什么是护网行动

1.什么是护网行动 2016年&#xff0c;公安部会同民航局、国家电网组织开展了“护网2016”网络安全攻防演习活动。同年&#xff0c;《网络安全法》颁布&#xff0c;出台网络安全演练相关规定:关键信息基础设施的运营者应“制定网络安全事件应急预案&#xff0c;并定期进行演练”…

LeetCode338比特位计数

题目描述 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 解析 动态规划&#xff0c;将当前的数的最后一位去掉&#xff0c;然后判断去掉的最后一位是0还是1。…

展会邀请 | 龙智即将亮相2024上海国际嵌入式展,带来安全合规、单一可信数据源、可追溯、高效协同的嵌入式开发解决方案

2024年6月12日至14日&#xff0c;备受全球嵌入式系统产业和社群瞩目的2024上海国际嵌入式展&#xff08;embedded world china 2024&#xff09;即将盛大开幕&#xff0c;龙智将携行业领先的嵌入式开发解决方案亮相 640展位 。 此次参展&#xff0c;龙智将全面展示专为嵌入式行…

类似crossover的容器软件有哪些 除了crossover还有什么 Mac虚拟机替代品

CrossOver是Mac用来运行exe文件的一款软件&#xff0c;但是并不是所有的exe文件CrossOver都支持运行。想要在Mac上运行exe文件的方法并不是只有使用CrossOver这一种&#xff0c;那么有没有类似的软件也可以实现exe文件在Mac上运行呢&#xff1f; CrossOver类似软件有哪些 1、Pl…

[Cloud Networking] Layer 2

文章目录 1. 什么是Mac Address?2. 如何查找MAC地址&#xff1f;3. 二层数据交换4. [Layer 2 Protocol](https://blog.csdn.net/settingsun1225/article/details/139552315) 1. 什么是Mac Address? MAC 地址是计算机的唯一48位硬件编码&#xff0c;嵌入到网卡中。 MAC地址也…

Spring Boot 实现动态数据源配置

前言 之前在CSDN博客以及某站看了教程&#xff0c;不免觉得有点不知如何下手&#xff0c;好在最后融合了以下&#xff0c;得出了一个比较简单的配置动态数据源的过程。 首先项目是Spring Boot的单体项目&#xff0c;我们的需求是要连接多个数据库&#xff0c;那么就需要配置多个…

CleanMyMac2028永久破解版苹果mac电脑垃圾清理软件

CleanMyMac&#xff0c;这款苹果mac电脑垃圾清理软件简直就是我的救星啊&#xff01;以前总是被电脑上的各种垃圾文件困扰&#xff0c;不知道如何彻底清理。自从用了CleanMyMac&#xff0c;我的电脑就像重新获得了新生一样&#xff01; 它的功能强大到让我惊叹不已&#xff01;…

深度学习复盘与论文复现C

文章目录 4、Distributed training4.1 GPU architecture 5、Recurrent neural network5.1 The basic structure of RNN5.2 Neural networks without hidden states5.3 Recurrent neural networks with hidden states5.4 summary 6、Language Model Dataset (lyrics from Jay Ch…

Java 泛型类,泛型方法,泛型接口和通配符(用来限定类和方法的使用范围)

测试类 package Genericity;import java.util.ArrayList;public class test {public static void main(String[] args) {// 使用泛型方法添加元素ArrayList<String> list new ArrayList<>();MyToolClass.ListAdd(list,"fdsf","dsfa");System…

Unity协程学习心得

前言 个人总结的一些Unity协程学习心得&#xff0c;如有不对请在评论区指出一起学习&#xff01;感谢。 在Unity编程中谈到异步逻辑&#xff0c;可以考虑使用协程来实现。协程&#xff08;Coroutine&#xff09;在Unity中的主要作用就是把一个任务暂停&#xff08;挂起&#…

动态IP在云计算中的应用与优势(短效IP的作用)

一、云计算概述 云计算是指通过互联网将计算资源和服务提供给用户的一种模式。它具有高灵活性、可扩展性和成本效益等特点&#xff0c;使得企业能够快速响应市场变化&#xff0c;降低IT投入成本。云计算的核心优势在于其资源的动态分配和高效利用。 二、动态IP在云计算中的角…