Spring:项目中的统一异常处理和自定义异常

news/2024/9/28 20:56:31/

介绍异常的处理方式。在项目中,都会进行自定义异常,并且都是需要配合统一结果返回进行使用。

1.背景引入

(1)背景介绍

为什么要处理异常?如果不处理项目中的异常信息,前端访问我们后端就是显示访问失败的,所以我们需要处理。但是单单处理还不够,还需要将信息返回给前端;因为异常是一类问题,所以我们可以统一进行处理,也就是统一异常处理。

(2)没有处理异常时

看一段代码:

@Slf4j
@RequestMapping("/test")
@RestController
public class TestController {@RequestMapping("/hello")public String hello() {log.info("我被前端调用了,嘤嘤嘤~");int a = 10/0;return "hello";}}

通过url进行访问:

后端日志:

所以这就是没有进行异常处理的后果

(3)简单处理异常后

下面这段代码就会对异常进行捕获,并且返回异常的具体信息

@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {@ExceptionHandler(Exception.class)public String exception(Exception e) {log.warn(e.getMessage());return e.getMessage();}
}

前端:

这样前端就知道了明确的异常信息,但是实际异常不会单独使用,都是作为一个Message封装到统一结果中进行返回。

2.异常使用方法

我们先在代码中定义一个简单的统一结果返回,用于介绍和学习异常

import lombok.Data;@Data
public class Result {private String message;private int code;public Result(String message,int code) {this.message = message;this.code = code;}public static Result fail(String message) {return new Result(message,1314);}}

(1)统一异常模版

controller:

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RequestMapping("/test")
@RestController
public class TestController {@RequestMapping("/hello")public String hello() {int a = 10/0;return "hello";}@RequestMapping("/heihei")public Result heihei() {return Result.fail("只因你实在是太美~");}}

异常捕获: 

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;@Slf4j
@ResponseBody
@RestControllerAdvice
public class ExceptionAdvice {@ExceptionHandlerpublic Result exception(Exception e) {log.error(e.getMessage(), e);return Result.fail(e.getMessage());}
}

我们通过前端就行访问:

即时后端发生了异常,前端也能收到格式化的数据,大大提高了可读性。

(2)注解解析

写法一:类@RestControllerAdvice + 方法@ExceptionHandler

表示该类下的所有方法返回的都是数据

写法二:类@ControllerAdvice + 方法@ResponseBody + 方法@ExceptionHandler

表示该方法返回数据

写法三:类@ControllerAdvice + 类@ResponseBody + 方法@ExceptionHandler

表示该类下的所有方法返回的都是数据

其他写法:可以指定捕获异常的类型,也就是在@ExceptionHandler后面加上括号,指定异常的对象

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {@ExceptionHandler(Exception.class)public Result exception(Exception e) {log.error(e.getMessage(), e);return Result.fail(e.getMessage());}
}

为什么要加上@ResponseBody注解,不加的时候默认返回视图,就会产生异常,也就是下面的效果

3.使用自定义异常

这里的自定义异常也就是定义一个异常类,然后作为@ExceptionHandler捕获的对象

(1)先自定义一个普通的异常

步骤:实现Exception类或者其子类,然后写构造方法(记得先初始化父类),可以看情况重写几个方法

于是我们得到下面的自定义异常类

public class ApplicationException extends RuntimeException{//自定义的错误结果(里面包含错误码和错误信息)protected Result errorResult;//用于throw new ApplicationException(Result.fail("我走的是构造方法"))这种情况public Result getErrorResult() {return errorResult;}/*** 构造方法  用于填充信息*/public ApplicationException(Result errorResult) {super(errorResult.getMessage());this.errorResult = errorResult;}public ApplicationException(String message) {super(message);}public ApplicationException(Throwable cause) {super(cause);}public ApplicationException(String message, Throwable cause) {super(message, cause);}
}

(2)再定义全局异常处理器

这里的全局异常处理器就是上面的统一异常处理,只需要多捕获一个自定义异常就可以了。

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {@ExceptionHandler(ApplicationException.class)public Result applicationExceptionHandler (ApplicationException e) {e.printStackTrace();// 打印日志if (e.getErrorResult() != null) {return e.getErrorResult();}// 一般不会为null,构造方法已经限制住了,但是保险一些if (e.getMessage() == null || e.getMessage().equals("")) {return Result.fail(e.getMessage());}// 返回具体的异常信息return Result.fail(e.getMessage());}//兜底捕获异常@ExceptionHandler(Exception.class)public Result exception(Exception e) {log.error(e.getMessage(), e);return Result.fail(e.getMessage());}
}

大致情况就这么写,接下来解析一下统一异常中的几种校验情况


http://www.ppmy.cn/news/1530695.html

相关文章

C++入门day4-面向对象编程(下)

前言:C入门day3-面向对象编程(中)-CSDN博客 初识:继承特性 继承的基础语法 class A{ public:int a; }; class B:public A { public:int b; }; B类通过继承A类后,内部会继承一个int变量 a:从下图我们可以…

Java 14Java 15新特性概述

一、Java 14 发布于2020年3月17日。Java 14主要新特性如下: JEP 305:Pattern Matching for instanceof (Preview)instanceof 的模式匹配(预览) JEP 358:Helpful NullPointerExceptions 有用的 NullPointerExceptions…

应用DFX能力介绍

一、HarmonyOS生态DFX能力范围 围绕开发者,构建三方应用和设备从开发到维护全生命周期所必需、有竞争力、有特色的调试调优、定位、维护能力。 二、HarmonyOS DFX能力全集 三、DFX设计主要范围 1、HiLog 日志分类 日志常用命令 日志级别 日志规则 2、HiAppEvent 完…

Llama 3.2来了,多模态且开源!AR眼镜黄仁勋首批体验,Quest 3S头显价格低到离谱

如果说 OpenAI 的 ChatGPT 拉开了「百模大战」的序幕,那 Meta 的 Ray-Ban Meta 智能眼镜无疑是触发「百镜大战」的导火索。自去年 9 月在 Meta Connect 2023 开发者大会上首次亮相,短短数月,Ray-Ban Meta 就突破百万销量,不仅让马…

详细分析Mysql中的定时任务(Event事件)

目录 前言1. 基本知识2. Event事件3. Demo 前言 基本的知识推荐阅读: 详细分析Mysql触发器的基本使用(图文解析)详细分析SQL Server触发器的基本知识详细分析Corn表达式(附Demo) 特性事件定时任务触发器触发条件基于…

校园美食导航:Spring Boot技术的美食发现之旅

第二章 系统分析 2.1 可行性分析 可行性分析的目的是确定一个系统是否有必要开发、确定系统是否能以最小的代价实现。其工作主要有三个方面,分别是技术、经济和社会三方面的可行性。我会从这三个方面对网上校园周边美食探索及分享平台进行详细的分析。 2.1.1技术可行…

【Webpack】生命周期

概述 Webpack 的生命周期是指从启动到结束整个过程中会经历的一系列步骤。简单来说,Webpack 的生命周期分为以下几个主要阶段: 1)初始化:Webpack 读取配置文件,初始化参数。 2)编译:根据入口文…

银从初级个人理财_09_第三章第三节

一、单选题 一般而言,在面对通货膨胀压力的情况下,()投资具有保值增值的作用。 现金 固定收益产品 黄金 储蓄 房地产信托是指房地产拥有者将该房地产委托给信托公司,由信托公司按照委托者的要求进行()。 物业经营 租赁、经营 租售 …