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

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

任意密码重置+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…

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;存储在磁盘、磁带、光盘或其他外存介质上、按一定结构组织在一起的相关数据的集合。数…

龙迅分配器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 函数概念 对应法则 定义域 常见函数 函数的几种特性 周期函数不一定有最小周期。 涉及额外与复习 存在与任意的关系

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

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

C语言数组(上)

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

跨域问题与解决-gatway

3.6.1.什么是跨域问题 跨域&#xff1a;域名不一致就是跨域&#xff0c;主要包括&#xff1a; 域名不同&#xff1a; www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com域名相同&#xff0c;端口不同&#xff1a;localhost:8080和localhost8081 跨域问题&a…

ADB命令集锦,一起来学吧

前言 在测试APP时&#xff0c;我们常常会用到adb命令来协助测试&#xff0c;那么adb命令到底是什么&#xff1f;有什么用&#xff1f;怎么用&#xff1f; 今天我就整理了一些工作中常用的adb知识点&#xff0c;希望对大家有所帮助。 ADB学习全攻略 ADB是什么&#xff1f; a…

三种定时器的实现方式

一、Scheduled Schedule是Spring框架提供的一种简单的定时任务调度方法&#xff0c;通过注解的方式即可实现定时任务的调度。它适用于简单的定时任务需求&#xff0c;例如每隔一段时间执行一次任务或者在特定时间执行任务。Scheduled可以轻松地集成到Spring应用中&#xff0c;…

LangChain的函数,工具和代理(四):使用 OpenAI 函数进行标记(Tagging) 提取(Extraction)

在上一篇博客LangChain中轻松实现OpenAI函数调用 中我们学习了如何使用Pydantic来生成openai的函数描述对象&#xff0c;并且通过在langchain中调用Pydantic生成的函数描述变量来轻松实现openai的函数调用功能&#xff0c;在此基础上今天我们再介绍两个非常实用的功能&#xff…

2024年,Rust和Go学哪个更好?

Rust vs. Go&#xff0c;在2024年&#xff0c;应该选择哪一个&#xff1f;或者说应该选择哪种语言——GoLang还是Rust。这可能是许多程序员在选择语言时考虑的一个问题。选择理想的编程语言被视为在这个不断变化的环境中取得成功的重要抉择。 GoLang和Rust是当今使用的最年轻的…

【黑马甄选离线数仓day08_会员主题域开发】

1. 会员主题域需求说明 1.1 各类会员数量统计 说明&#xff1a;公司为了对不同会员进行不同的营销策略&#xff0c;对各类会员的数量都非常敏感&#xff0c;比如注册会员、消费会员、复购会员、活跃会员、沉睡会员。不仅需要看新增数量还要看累积数量。 指标&#xff1a;新增…

二十九、微服务案例完善(数据聚合、自动补全、数据同步)

目录 一、定义 二、分类 1、桶(Bucket)聚合: 2、度量(Metric&#xff09;聚合: 3、管道聚合&#xff08;Pipeline Aggregation&#xff09;&#xff1a; 4、注意&#xff1a; 参与聚合的字段类型必须是: 三、使用DSL实现聚合 聚合所必须的三要素&#xff1a; 聚合可配…