SpringBoot自定义异常处理机制

news2024/9/30 1:34:26

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

本文介绍在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 {

    @Autowired
    private 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 {

    @Override
    public 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);
    }

    @Override
    public 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 {

    @Override
    public 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);
    }

    @Override
    public 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.coloradmin.cn/o/1283591.html

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

相关文章

万字长文带你搞定MMUTLBTWU

最近一直在学习内存管理&#xff0c;也知道MMU是管理内存的映射的逻辑IP&#xff0c;还知道里面有个TLB。 今天刚刚好看到了几篇前辈的文章&#xff0c;很是不错&#xff0c;于是这里来一起学习一下吧。 PART 一&#xff1a;MMU 架构篇 MMU&#xff08;Memory Management Uni…

解决在Linux中进行redis的主从复制时出现的从机可以获取到主机的信息,主机获取不到从机的信息~

主机&#xff1a; 从机1&#xff1a; 从机2&#xff1a; 出现上述的原因是我在redis.conf中设置了密码&#xff0c;那么就导致了我在进行主从复制时&#xff0c;需要进行密码验证&#xff0c;然后我在网上查阅了很多资料&#xff0c;有的说让在从机中指定密码&#xff0c;有的说…

12.04 二叉树中等题

513. 找树左下角的值 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 思路&#xff1a;找到最低层中最左侧的节点值&#xff0c;比较适合层序遍历&#xff0c;返回最…

按升序输出各个字符串。

编写程序&#xff0c;设计并实现如下功能&#xff1a;从键盘输入多个字符串&#xff0c;按升序输出各个字符串。

笔记66:自注意力和位置编码

本地笔记地址&#xff1a;D:\work_file\&#xff08;4&#xff09;DeepLearning_Learning\03_个人笔记\3.循环神经网络\第10章&#xff1a;动手学深度学习~注意力机制 a a a a a a a a a a a a a a a a a a a

YOLOv8-Seg改进:简单高效的模块-现代反向残差移动模块 (iRMB) | | ICCV2023 EMO

🚀🚀🚀本文改进:设计了一种面向移动端应用的简单而高效的现代反向残差移动模块 (Inverted Residual Mobile Block, iRMB),它吸收了类似 CNN 的效率来模拟短距离依赖和类似 Transformer 的动态建模能力来学习长距离交互,引入YOLOV8 🚀🚀🚀YOLOv8-seg创新专栏:h…

艾瑞:央国企数字化升级,低代码首选得帆云!

中国权威咨询机构艾瑞咨询最新发布了《2023年央国企数字化升级研究报告》。 THE NEW RESEARCH 报告认为 央国企作为中国特色社会主义的重要物质基础和政治基础&#xff0c;肩负着推动经济发展和增强社会价值的重要责任&#xff0c;必须在数字化升级中发挥引领作用。当前&#…

5.【自动驾驶与机器人中的SLAM技术】2D点云的scan matching算法 和 检测退化场景的思路

目录 1. 基于优化的点到点/线的配准2. 对似然场图像进行插值&#xff0c;提高匹配精度3. 对二维激光点云中会对SLAM功能产生退化场景的检测4. 在诸如扫地机器人等这样基于2D激光雷达导航的机器人&#xff0c;如何处理悬空/低矮物体5. 也欢迎大家来我的读书号--过千帆&#xff0…

详解十大经典排序算法(四):希尔排序(Shell Sort)

算法原理 希尔排序是一种基于插入排序的排序算法&#xff0c;也被称为缩小增量排序。它通过将待排序的序列分割成若干个子序列&#xff0c;对每个子序列进行插入排序&#xff0c;然后逐步缩小增量&#xff0c;最终使整个序列有序。 算法描述 希尔排序&#xff08;Shell Sort&am…

【软考S01计算机系统知识】E01 中央处理单元

E01 中央处理单元 计算机系统硬件基本组成中央处理单元组成功能 多核 CPU 计算机系统硬件基本组成 计算机系统由硬件和软件组成&#xff0c;基本硬件系统由 运算器、控制器、存储器、输入设备 和 输出设备 5大部件组成&#xff1b; 中央处理单元&#xff1a; 运算器、控制器等…

【MySQL语言汇总[DQL,DDL,DCL,DML]以及使用python连接数据库进行其他操作】

MySQL语言汇总[DQL,DDL,DCL,DML] SQL分类1.DDL:操作数据库&#xff0c;表创建 删除 查询 修改对数据库的操作对表的操作复制表&#xff08;重点&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2.DML:增删改表中数据3.DQL&#xff1a;查询表中的记录…

hnust 湖科大 创业基础考察课程结课作业 创业计划书+路演PPT 资源下载

hnust 湖科大 创业基础考察课程结课作业 创业计划书 资源下载 资源详尽&#xff0c;图文并茂&#xff0c;开箱即用&#xff0c;附赠若干模板 资源预览图 创业计划书word 路演PPT 赠品 下载链接 链接&#xff1a;https://pan.baidu.com/s/1p1n6qwM5Jx6bB96ifAJmiw?pwd1111 …

Autosar MCAL-RH850P1HC Port配置

文章目录 PortPortGroupPortPin PortFilterGroupConfigDigital Filter Clock Selection0Digital Filter Clock Selection1 PortGeneralCritical Section ProtectionDev Error DetectDevice NameMax ModeSet Pin Default Modee ApiSet Pin Modee ApiSet to Dio Alt Modee ApiUse…

Ubuntu22.04 交叉编译mp4V2 for Rv1106

一、配置工具链环境 sudo vim ~/.bashrc在文件最后添加 export PATH$PATH:/opt/arm-rockchip830-linux-uclibcgnueabihf/bin 保存&#xff0c;重启机器 二、下载mp4v2 下载路径&#xff1a;MP4v2 | mp4v2 三、修改CMakeLists.txt 四、执行编译 mkdir build cd buildcmak…

ubuntu16.04升级openssl

Ubuntu16.04 默认带的openssl版本为1.0.2 查看&#xff1a;openssl version 1.下载openssl wget https://www.openssl.org/source/openssl-1.1.1.tar.gz 编译安装 tar xvf openssl-1.1.1.tar.gz cd openssl-1.1.1 ./config make sudo make install sudo ldconfig 删除旧版本 su…

springboot的常用注解

声明解释这个对象&#xff08;类或者其他&#xff09;组件相关 名称作用Controller用于修饰MVC中controller层的组件SpringBoot中的组件扫描功能会识别到该注解&#xff0c;并为修饰的类实例化对象&#xff0c;通常与RequestMapping联用&#xff0c;当SpringMVC获取到请求时会…

DistributionBalancedLoss

Distribution-Balanced Loss P I ( x k ) P^I(x^k) PI(xk) 1 C ∑ y i k 1 1 n i {1\over C}\sum\limits_{y_i^k1}{1\over{n_i}} C1​yik​1∑​ni​1​&#xff0c; P i C ( x k ) P^C_i(x^k) PiC​(xk) 1 C 1 n i {1\over C}{1\over{n_i}} C1​ni​1​ r i k _i^k ik​ P i …

目标检测——R-CNN系列检测算法总结

R-CNN系列算法详细解读文章&#xff1a; R-CNN算法解读SPPNet算法解读Fast R-CNN算法解读Faster R-CNN算法解读Mask R-CNN算法解读 目录 1、概述1.1 获取目标候选框1.2 候选框提取特征1.3 候选框分类及边框回归 2、R-CNN系列算法概述2.1 R-CNN算法2.2 SPPNet算法2.3 Fast R-CN…

C++作业5

完成沙发床的多继承&#xff08;有指针成员&#xff09; 代码&#xff1a; #include <iostream>using namespace std;class Bed { private:double *money; public:Bed(){cout << "Bed::无参构造函数" << endl;}Bed(double money):money(new doub…