SpringBoot自定义异常处理机制

说明:在完整的项目结构中,我们通常会创建一个自定义的异常处理机制,在系统可能出现异常的地方手动抛出这些异常,可以快速定位到异常代码片段,提供项目的可维护性。

本文介绍在SpringBoot项目中,搭建一套自定义异常处理机制。

统一响应结果

首先,创建一个统一响应结果类,如下,用于统一后台的返回结果,请求成功返回数据,请求失败返回错误信息;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** 后端统一返回结果*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> implements Serializable {private static final long serialVersionUID = 1L;/*** 编码:1成功 0和其他数字为失败*/private Integer code;/*** 错误信息*/private String msg;/*** 数据*/private T data;/*** 成功并返回** @param <T>* @return*/public static <T> Result<T> success() {Result<T> result = new Result<T>();result.code = 1;return result;}/*** 成功并返回数据** @param object* @param <T>* @return*/public static <T> Result<T> success(T object) {Result<T> result = new Result<T>();result.data = object;result.code = 1;return result;}/*** 失败,并返回信息** @param msg* @param <T>* @return*/public static <T> Result<T> error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}
}

然后,创建两个接口,用于用户登录,根据ID查找用户,如下:

(controller层)

import com.hezy.pojo.entity.User;
import com.hezy.pojo.vo.Result;
import com.hezy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/exception")
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/login")public Result login(@RequestBody User user){return userService.login(user);}@GetMapping("/get")public Result get(Integer id){return userService.getUser(id);}
}

(Service实现类,其中TODO表示待完成的部分)

import cn.hutool.core.util.ObjUtil;
import com.hezy.pojo.entity.User;
import com.hezy.pojo.vo.Result;
import com.hezy.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic Result login(User user) {// 对user进行校验if (!ObjUtil.isAllNotEmpty(user, user.getUsername(), user.getPassword())) {return Result.error("非法参数异常");}// TODO 根据用户名查询数据库,校验该用户是否存在if (true) {return Result.error("该用户不存在");}// TODO 保存用户信息到数据库return Result.success(user);}@Overridepublic Result getUser(Integer id) {// 对id进行校验if (id == null || id < 0) {return Result.error("非法参数异常");}// TODO 根据用户名查询数据库, 校验用户是否存在if (true) {return Result.error("该用户不存在");}return Result.success(new User(id, "张三", "123456"));}
}

(用户实体类)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {private static final long serialVersionUID = 1L;/*** id*/private Integer id;/*** 账号*/private String username;/*** 密码*/private String password;
}

启动项目,运行;

在这里插入图片描述

(测试登录接口,因为在if里面写死了,所以返回错误信息)

在这里插入图片描述


(测试获取用户对象接口,因为在if里面写死了,所以返回错误信息)

在这里插入图片描述

异常枚举

接下来,对上面的异常进行统一处理。

首先,创建一个异常的枚举类,里面包含了异常状态码,异常信息等,如下:

/*** 异常枚举类*/
public enum ExceptionEnum {PARAM_EXCEPTION(10001, "非法参数异常"),PARAM_LACK(10002, "参数不全异常"),UNKNOW_EXCEPTION(99999, "未知异常");private int status;private String message;ExceptionEnum(int status, String message) {this.status = status;this.message = message;}public int getStatus() {return status;}public String getMessage() {return message;}
}

自定义异常

创建一个自定义异常类,继承RuntimeException类,如下:

import com.hezy.enums.ExceptionEnum;/*** 自定义异常*/
public class MyException extends RuntimeException{/*** 异常枚举*/private ExceptionEnum exceptionEnum;public MyException(ExceptionEnum exceptionEnum) {super(exceptionEnum.getMessage());this.exceptionEnum = exceptionEnum;}public ExceptionEnum getExceptionEnum() {return exceptionEnum;}/*** 手动抛出异常* @param exceptionEnum* @return*/public static MyException throwException(ExceptionEnum exceptionEnum){return new MyException(exceptionEnum);}
}

再创建一个异常的controller,自定义捕获对应的异常,并打印信息;

import com.hezy.enums.ExceptionEnum;
import com.hezy.pojo.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理器*/
@RestControllerAdvice
@Slf4j
public class GlobalException {/*** 自定义异常* @param e* @return*/@ExceptionHandler(MyException.class)public Result handleException(MyException e){log.error(e.getMessage());return Result.builder().code(0).msg(e.getExceptionEnum().getMessage()).build();}/*** 全局异常* @param e* @return*/@ExceptionHandler(Exception.class)public Result handleException(Exception e){log.error(e.getMessage());return Result.builder().code(0).msg(ExceptionEnum.UNKNOW_EXCEPTION.getMessage()).build();}
}

最后,对前面业务实现类里面的代码进行修改,当参数校验错误时,直接抛出异常,如下:

import cn.hutool.core.util.ObjUtil;
import com.hezy.enums.ExceptionEnum;
import com.hezy.exception.MyException;
import com.hezy.pojo.entity.User;
import com.hezy.pojo.vo.Result;
import com.hezy.service.UserService;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic Result login(User user) {// 对user进行校验,其中user、username、password,都不能为空if (!ObjUtil.isAllNotEmpty(user, user.getUsername(), user.getPassword())) {throw new MyException(ExceptionEnum.PARAM_LACK);}// TODO 根据用户名查询数据库,校验该用户是否存在if (true) {return Result.error("该用户不存在");}// TODO 保存用户信息到数据库return Result.success(user);}@Overridepublic Result getUser(Integer id) {// id == null,参数不全异常if (id == null) {throw new MyException(ExceptionEnum.PARAM_LACK);}// id < 0,非法参数异常if (id < 0) {throw new MyException(ExceptionEnum.PARAM_EXCEPTION);}// TODO 根据用户名查询数据库, 校验用户是否存在if (true) {return Result.error("该用户不存在");}return Result.success(new User(id, "张三", "123456"));}
}

启动项目,测试;

(当user中的username为空时)

在这里插入图片描述

在这里插入图片描述

(当获取对象的id < 0时)

在这里插入图片描述

在这里插入图片描述

当发生其他未知异常时,如post请求的接口,我们使用get方式发送时;

在这里插入图片描述

就会被全局异常捕获到,并在控制台打印报错信息;

在这里插入图片描述

如果此时,需要新增一个异常,只需要在ExceptionEnum(异常枚举类)中新增一个枚举项即可,如下:

(新增一个登录异常)

/*** 异常枚举类*/
public enum ExceptionEnum {PARAM_EXCEPTION(10001, "非法参数异常"),PARAM_LACK(10002, "参数不全异常"),LOGIN_EXCEPTION(10003, "登录异常"),UNKNOW_EXCEPTION(99999, "未知异常");private int status;private String message;ExceptionEnum(int status, String message) {this.status = status;this.message = message;}public int getStatus() {return status;}public String getMessage() {return message;}
}

总结

通过异常枚举类 + 自定义异常类 + SpringBoot的异常处理注解,可以实现对项目量身定做一套异常处理机制,根据项目中出现的异常,来返回对应的异常信息,非常方便。

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

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

相关文章

ssm党务政务服务热线平台源码和论文答辩PPT

摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计…

Vue3的watch函数中,第三个参数配置对象详细分析

在Vue 3的watch函数中&#xff0c;第三个参数是一个配置对象&#xff0c;用于定义如何执行watch函数。下面是几个常用的配置项的讲解&#xff0c;并附上代码示例&#xff1a; 1、immediate immediate&#xff1a;当设置为true时&#xff0c;会在初始渲染时立即执行watch函数。…

C++11改进单例模式

单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 C11之前&#xff0c;实现一个通用的泛型单例模式时&#xff0c;会遇到一个问题&#xff1a;这个泛型单例要能够创建所有的类型对象&#xff0c;但是这些类型的构造函数形参可能尽不相同&#xff0c;…

Appium:进行iOS自动化测试遇到的问题与解决方案

问题与解决方案 在使用Appium进行iOS自动化测试时&#xff0c;可能会遇到各种问题。 以下是一些常见的问题及其解决方案&#xff1a; 无法启动inspector问题 最新版本的Appium已经将内置的inspector独立了出去&#xff0c;需要单独安装inspector进行调试。确保inspector对应…

任意密码重置+CRRF

一、XSS漏洞 在商城的搜索处&#xff0c;输入标准语句的传参直接就可以弹窗 二、逻辑漏洞-用户枚举 在用户注册界面&#xff0c;点击发送验证码&#xff0c;然后用BURP发包 更改手机号传参&#xff0c;这里手机号传参没有进行加密&#xff0c;直接用手机号的位置进行爆破 正确的…

LeetCode力扣每日一题(Java):9、回文数

一、题目 二、解题思路 1、我的思路 当x<0时&#xff0c;x一定不是回文数&#xff0c;直接返回false 当x>0且x<10时&#xff0c;x一定是回文数&#xff0c;直接返回true x>10时&#xff0c;先将x转为字符串。将数字转成字符串方法挺多的&#xff0c;以下是&…

06、基于内容的过滤算法Tensorflow实现

06、基于内容的过滤算法Tensorflow实现 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。全部工程可从最上方链接下载。 05、基于梯度下降的协同过滤算法中已经介绍了协同过滤算法的基本实现方法&#xff0c;但是这种方法仅…

SpringBoot集成i18n(多语言)

配置文件 spring: messages: basename: il8n/messages # 配置国际化资源文件路径 fallback-to-system-locale: true # 是否使用系统默认的语言环境作为备选项 国际化配置 import org.springframework.context.annotation.Bean; import org.spr…

Spring中通知是什么

面向切面编程 这个切面是哪个面 面向切面编程&#xff08;Aspect-Oriented Programming&#xff0c;AOP&#xff09;是一种编程范式&#xff0c;它通过切面&#xff08;Aspect&#xff09;来分离横切关注点&#xff08;Cross-cutting Concerns&#xff09;和核心业务逻辑。 在…

MySQL-宋红康-(课P14-P15)-基本查询语句(Select)

b站视频&#xff1a; 14-最基本的SELECT...FROM结构_哔哩哔哩_bilibili 8.4 基本查询(Select)语句 数据table: emp员工表创建如下 # 员工表 CREATE TABLE EMP (EMPNO INT PRIMARY KEY, -- 员工编号ENAME VARCHAR(10), -- 员工名称JOB VARCHAR(9), -- 工…

10、SQL注入——数据库基础

文章目录 一、数据库概述二、数据库分类Mysql数据库连接方法 三、识别数据库四、SQL语法4.1 SQL基本语法4.2 高级操作 一、数据库概述 数据库&#xff08;database&#xff09;&#xff1a;存储在磁盘、磁带、光盘或其他外存介质上、按一定结构组织在一起的相关数据的集合。数…

webpack对项目进行优化

对项目进行优化是提高性能和效率的关键&#xff0c;以下是一些实用的Webpack优化技巧&#xff1a; 代码拆分&#xff08;Code Splitting&#xff09;&#xff1a;将代码拆分为多个小块&#xff0c;按需加载。通过配置splitChunks插件&#xff0c;可以将公共代码提取到单独的文件…

常见代码优化案例记录

1. 使用StringBuilder优化字符串拼接&#xff1a; // 不优化的写法 String result ""; for (int i 0; i < 1000; i) {result i; }// 优化的写法 StringBuilder resultBuilder new StringBuilder(); for (int i 0; i < 1000; i) {resultBuilder.append(i)…

龙迅分配器LT86102UXE/LT86104UX,HDMI一分二/HDMI一分四

龙迅LT86102UXE描述; Lontium LT86102UXE HDMI2.0分配器具有1&#xff1a;2的分配器&#xff0c;符合HDMI2.0/1.4规范&#xff0c;最大6Gbps高速数据速率&#xff0c;自适应均衡RX输入和预先强调的TX输出&#xff0c;以支持长电缆应用程序&#xff0c;内部TX通道交换灵活的PCB…

部分c++11特性介绍

在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合并称为C98/03标…

Day50力扣打卡

打卡记录 三个无重叠子数组的最大和 链接 滑动窗口 class Solution:def maxSumOfThreeSubarrays(self, nums: List[int], k: int) -> List[int]:n, ans len(nums), []sum1 sum2 sum3 0maxsum1idx, maxsum12idx 0, ()maxsum1 maxsum12 total 0for i in range(2 * …

01 高等数学.武忠祥.0基础

第一章 函数与极限 01映射与函数 02 函数概念 对应法则 定义域 常见函数 函数的几种特性 周期函数不一定有最小周期。 涉及额外与复习 存在与任意的关系

在python中自己定义一个方法,但是没有写return XXX会有什么影响

【多么痛的领悟&#xff0c;找了两个小时的错误&#xff01;&#xff01;&#xff01;发现是少写个return】 print(data.task_ID) AttributeError: NoneType object has no attribute task_ID** 然后一句一句找&#xff0c;我找啊找&#xff01;&#xff01;&#xff01;&…

MYSQL练题笔记-高级查询和连接-简单题3题

写了下面的前3道题。 一、每位经理的下属员工数量 看到题目就知道和之前的至少有5名下属的经理很相似&#xff0c;嘿嘿写对了就不做过多的讲解了。 二、员工的直属部门相关表和题目如下 刚开始觉得很简单&#xff0c;但是仔细想想这道题有两个输出&#xff0c;觉得想不出来&a…

C语言数组(上)

# 数组的概念 数组是一组相同类型元素的集合。数组中存放的是一个或多个数据&#xff0c;但是数组中的元素个数不能为零&#xff1b;数组中存放的所有元素&#xff08;数据&#xff09;的类型必须是相同的。 数组分为一维数组和多维数组&#xff0c;多维数组一般比较多见的是二…