《springboot实战》第六章 实现自定义全局异常处理

news2025/1/12 12:01:55

前言

springboot实现自定义全局异常处理,以及统一返回数据。

1、分析

首先,实现全局异常的流程
在这里插入图片描述
从图中可以看到,实现全局异常会需要这样几个类:

  • 自定义异常接口类
  • 自定义异常枚举类
  • 自定义异常类
  • 自定义异常处理类
  • 自定义全局响应类

2、创建所需类

2.1、为了代码解耦,创建一个接口类出来,定义自定义接口所需要的方法

/**
 * Http状态信息接口
 */
public interface HttpStatusInfoInterface {

    int getCode();

    String getMessage();

}

2.2、定义一个枚举类,实现上述接口,重写上述接口的两个方法来操作这个枚举类内部的各个具体枚举值

后续方便管理所有错误枚举的错误信息以及code码,通过构造方法传入code值和message或者直接传入一个枚举值都行

/**
 * Http状态码
 */
public enum HttpStatusEnum implements HttpStatusInfoInterface{

    //定义状态枚举值
    SUCCESS(200 , "成功!"),
    BODY_NOT_MATCH(400 , "数据格式不匹配!"),
    NOT_FOUND(404 , "访问资源不存在!"),
    INTERNAM_SERVER_ERROR(500 , "服务器内部错误!"),
    SERVER_BUSY(503 , "服务器正忙,请稍后再试!"),
    REQUEST_METHOD_SUPPORT_ERROR(10001 , "当前请求方法不支持!"),
    REQUEST_DATA_NULL(10002 , "当前请求参数为空!"),
    USER_NOT_EXISTS(10003 , "该用户不存在!"),
    USER_INVALID(10004 , "当前登录信息已生效,请重新登录!"),
    PASSWORD_ERROR(10005 , "密码错误!"),
    USER_NAME_LOCK(10006 , "该账号已被锁定!");

    //状态码
    private int code;

    //提示信息
    private String message;

    //构造方法
    HttpStatusEnum(int code , String message) {
        this.code = code;
        this.message = message;
    }

    @Override
    public int getCode() {
        return this.code;
    }

    @Override
    public String getMessage() {
        return this.message;
    }

}

2.3、自定义一个异常类

就像空指针异常类、IO流异常类一样。此处自定义的异常类属于异常类,所有肯定是要继承一个异常类的,此处需要继承RuntimeException,原因如下:
RuntimeException相比Exception来讲,他是在程序运行时才会爆出异常,在编译时是不会出现异常的,这就表示,如果你throw了一个RuntimeException,不需要做额外操作;而throw一个Exception,程序会要求你try-catch,否则你根本启动不了程序,程序会提示(必须对其进行捕获或声明以便抛出)

import com.xxxx.springbootmybatis.common.HttpStatusEnum;
import lombok.Data;

@Data
public class HttpException extends RuntimeException{

    //错误码
    private int code;

    //错误信息
    private String message;

    // 默认构造函数
    public HttpException() {
        super();
    }

    public HttpException(HttpStatusEnum httpStatusEnum) {
        super(String.valueOf(httpStatusEnum.getCode()));
        this.code = httpStatusEnum.getCode();
        this.message = httpStatusEnum.getMessage();
    }

}

2.4、封装统一返回类

封装返回值类BaseResponse类和RespGenerator类都是属于规范方法返回值结构体的类,也有利于一致化后端所有接口的返回结构,方便前端读取所需要的数据。
HttpResult类:规定返回值结构。
HttpResultGenerator类:将逻辑处理后的数据包装转换成HttpResult类进行返回给前端。

import lombok.Data;

/**
 * http 统一返回类
 * @param <T>
 */
@Data
public class HttpResult<T> {

    private Integer code;

    private String message;

    private T data;

    //构造方法
    public HttpResult(Integer code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    //默认构造函数
    public HttpResult() {
        super();
    }
}

public class HttpResultGenerator {

    //正常返回时调用方法
    public static HttpResult success(Object data) {
        return new HttpResult(HttpStatusEnum.SUCCESS.getCode() , "接口调用成功!" , data);
    }


    //失败时调用方法(入参是异常枚举)
    public static HttpResult fail(HttpStatusEnum httpStatusEnum) {
        return new HttpResult(httpStatusEnum.getCode() , httpStatusEnum.getMessage() , null);
    }

    //失败时调用方法(提供给GlobalExceptionHandler类使用)
    public static HttpResult fail(int code ,  String message) {
        return new HttpResult(code , message , null);
    }

}

2.5、自定义异常处理类

@RestControllerAdvice注解是@ResponseBody和@ControllerAdvice的组合。

@ResponseBody注解:通常用来将java对象转成JSON对象,返回给前端JSON数据。
@ControllerAdvice注解:结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
@ExceptionHandler注解统一处理某一类异常,从而能够减少代码重复率和复杂度,value值为什么异常类型,就处理什么异常类型的逻辑。

import lombok.extern.slf4j.Slf4j;
import com.xxxx.springbootmybatis.common.HttpResult;
import com.xxxx.springbootmybatis.common.HttpResultGenerator;
import com.xxxx.springbootmybatis.common.HttpStatusEnum;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 自定义异常处理类
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
	
    //处理自定义异常
    @ExceptionHandler(value = HttpException.class)
    public HttpResult<Object> baseExceptionHandler(HttpException e) {
        log.error("发生业务异常!原因是:{}" , e.getMessage());
        return HttpResultGenerator.fail(e.getCode() , e.getMessage());
    }

    //处理空指针异常
    @ExceptionHandler(value = NullPointerException.class)
    public HttpResult<Object> exceptionHandler(Exception e) {
        log.error("发生异常!原因是:{}" , e);
        return HttpResultGenerator.fail(HttpStatusEnum.INTERNAM_SERVER_ERROR);
    }

}

3、测试

新建一个测试controller。

3.1、测试自定义异常全局处理效果

@Slf4j
@RestController
@CrossOrigin("*")
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/loginTest")
    public HttpResult loginTest(@RequestParam(value="name" ,required=false) String userName,
                                @RequestParam(value="pwd" ) String password ) {
        // URL: http://127.0.0.1/user/loginone?userName=zs&pwd=123
        log.info("userName:{} , password:{}" , userName , password);
        if(StringUtils.isEmpty(userName)) {
            throw new HttpException(HttpStatusEnum.USER_NOT_EXISTS);
        } else {
            return HttpResultGenerator.success("登录校验成功");
        }
    }
}

3.2、用postman测试,若username没有传值,会抛出自定义异常

在这里插入图片描述

3.3、控制台结果

2023-04-19 17:47:51.411 |-INFO  [http-nio-80-exec-3] com.hqyj.springbootmybatis.controller.UserController [54] -| userName: , password:123
2023-04-19 17:47:51.411 |-ERROR [http-nio-80-exec-3] com.hqyj.springbootmybatis.common.exception.GlobalExceptionHandler [21] -| 发生业务异常!原因是:该用户不存在!

在这里插入图片描述

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

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

相关文章

藏在GPT背后的治理分歧:那些赞同和反对的人们|AI百态(下篇)

AGI的火种正在燎原。 一面是无可否认的AI生产力&#xff0c;正在赋能千行百业&#xff1b;而另一面&#xff0c;这团火似乎烧向了我们不可控的隐秘角落。 在《AI百态&#xff08;上篇&#xff09;——ChatGPT的“N宗罪”》中&#xff0c;我们提到监管重锤在落下&#xff0c;意大…

安装 Docker和基本操作实验文档

一、安装 Docker 目前 Docker 只能支持 64 位系统。 systemctl stop firewalld.service setenforce 0 #安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 yum-utils&#xff1a;提供了 yum-config-manager 工具。device mapper&#xff1a; 是Li…

分布式系统概念和设计-操作系统中的支持和设计

分布式系统概念和设计 操作系统支持 中间件和底层操作系统的关系&#xff0c;操作系统如何满足中间件需求。 中间件需求:访问物理资源的效率和健壮性&#xff0c;多种资源管理策略的灵活性。 任何一个操作系统的目标都是提供一个在物理层&#xff08;处理器&#xff0c;内存&a…

【网络安全】Xss漏洞

xss漏洞 xss漏洞介绍危害防御方法xss测试语句xss攻击语句1. 反射性xss2.存储型xss3.DOM型xssdvwa靶场各等级渗透方法xss反射型&#xff08;存储型方法一致&#xff09;LowMediumHightimpossible Dom型LowMediumHight xss漏洞介绍 定义&#xff1a;XSS 攻击全称跨站脚本攻击&am…

Twitter|GraphJet:推特的实时内容推荐(论文+源码解读)

以下内容具有主观性&#xff0c;有些问题的理解和回答不一定准确&#xff0c;仅供参考。翻译不确定的后面都有原文。 1.论文 1.1论文的动机是什么&#xff1f; 作者在追溯基于图推荐的系统的进化过程&#xff0c;发现了两大趋势&#xff08;更快更广&#xff09;。 趋势一是…

MySQL ,MyBatis 1.参数占位符 2. ParameterType 3. SQL 语句中特殊字符处理

1.参数占位符&#xff1a; 1&#xff09;#{}&#xff1a;执行sql时&#xff0c;会将#仔占位符替换为&#xff1f;&#xff0c;将来自动设置参数值 2&#xff09;${}&#xff1a;拼SQL。会存在SQL注入问题 3.使用时机&#xff1a; * 参数传递&#xff0c;都使用#{} *如果要对表名…

Elasticsearch:保留字段名称

作为 Elasticsearch 用户&#xff0c;我们从许多不同的位置收集数据。 我们使用 Logstash、Beats 和其他工具来抓取数据并将它们发送到 Elasticsearch。 有时&#xff0c;我们无法控制数据本身&#xff0c;我们需要管理数据的结构&#xff0c;甚至需要在摄取数据时处理字段名称…

腾讯云轻量服务器测评:4核8G12M带宽流量CPU限制说明

腾讯云轻量4核8G12M服务器446元一年&#xff0c;之前是4核8G10M配置&#xff0c;现在公网带宽和月流量包整体升级&#xff0c;系统盘为180GB SSD盘&#xff0c;每月2000GB免费流量&#xff0c;如果是选择买赠专区的4核8G12M配置是518元15个月&#xff0c;腾讯云百科来详细说下4…

MyBatis插入时获取自增id

关于MyBatis在插入时获取自增id 1.1 注释方法 Insert("insert into book(bid, bname, price, number, cratedate) values(null,#{bname},#{price},#{number},#{cratedate}) ")int add(Book book); //注意&#xff1a;在mapper中是不能重载的这里我特意写为add01Ins…

【力扣-JZ22】链表中倒数第k个结点

&#x1f58a;作者 : Djx_hmbb &#x1f4d8;专栏 : 数据结构 &#x1f606;今日分享 : "把手插进米堆的原因 " : 因为米堆类似于高密度的流体&#xff0c;会给人的手带来较大的压强&#xff0c;这种压强促进静脉血回流&#xff0c;会让人感到生理上的舒服。 文章目…

临床决策曲线分析如何影响预测模型的使用和评价

目前&#xff0c;临床决策曲线分析&#xff08;clinical decision curve analysis, DCA&#xff09;在业界已经被超过1500文献使用&#xff0c;也被多个主流的临床杂志所推荐&#xff0c;更被写进了临床预测模型撰写标准&#xff08;TRIPOD&#xff09;中&#xff0c;但是许多预…

OpenCV实例(七)汽车检测

OpenCV实例&#xff08;七&#xff09;汽车检测 1.概述2.代码实例3.代码功能 作者&#xff1a;Xiou 1.概述 对于图像和视频检测中的目标类型并没有具体限制&#xff0c;但是&#xff0c;为了使结果的准确度在可接受范围内&#xff0c;需要一个足够大的数据集&#xff0c;包括…

mongodb数据库索引介绍与优化选择

数据库开发系列 文章目录 数据库开发系列前言一、基础篇二、提高篇总结 前言 一、基础篇 MongoDB 索引 索引通常能够极大的提高查询的效率&#xff0c;如果没有索引&#xff0c;MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。 这种扫描全集合的查…

broadcast自动扩展/合并与分割/基本运算

文章目录 一、broadcastKey ideamatch from last dim 二、合并catstack 三、拆分split&#xff1a; 四、基本运算matmulAn examplematmulpowerexp logapproximationclamp 五、统计属性总结 一、broadcast Key idea ▪ Insert 1 dim ahead ▪ Expand dims with size 1 to same…

测试概念篇

目录 调试和测试的区别软件测试的概念软件测试和软件开发的区别优秀的测试人员应该具什么素质为什么要做测试软件的生命周期什么是Bug什么是需求测试用例是什么产品的生命周期软件测试贯穿于软件的整个生命&#xff0c;如如何贯穿&#xff1f;开发模型瀑布模型&#xff08;面向…

【java】反射基础

Class类 import java.io.*; import java.util.Scanner;public class Main {public static void main(String[] args) throws ClassNotFoundException {Class<String> clazz String.class; //使用class关键字&#xff0c;通过类名获取Class<?> clazz2 Class.f…

SpringBoot源码学习系列——运行流程分析

前文SpringBoot源码学习系列——构造流程分析对SpringApplication的实例化流程进行了介绍&#xff0c;完成了基本配置文件的加载及初始化&#xff0c;本文对其run方法进行介绍&#xff0c;看看Spring Boot是如何启动运行的。 run方法核心流程 可以看到&#xff0c;SpringAppli…

主机串口—虚拟机串口—linux系统串口之间的关系(实现主机和虚拟机之间的串口通信)

目录 1、准备工具 2、实现机理 3、实现过程 4、虚拟机串口 —— Linux系统串口文件 1、准备工具 VSPD&#xff1a;作用是在主机上创建虚拟串口 VSPD 下载&#xff1a;VSDP 汉化版下载VSPD 配置教程&#xff1a;VSPD虚拟串口工具实用工具–小白入门篇 | 码农家园 串口调…

MES功能设计规格书

软件功能结构 项目实施方案 概述 按总体规划&#xff0c;MES项目分三个阶段实施&#xff0c;第一阶段先在终端电器制造部和控制电器制造部进行试点实施。 第一阶段目标 建立基本的MES系统框架&#xff0c;提供工厂建模等基础功能。将目前的Excel生产排程纳入到系统管理&…

wps宏编辑器API关于msgbox和inputbox的使用说明

WPS宏编辑器API参考关于函数列举了3个&#xff1a;DoEvents、InputBox和MsgBox&#xff0c;其中DoEvents有点不好理解&#xff0c;应该在什么场景下使用也缺乏官网指导说明&#xff0c;因此本文重点讲述InputBox和MsgBox的使用说明。 1、DoEvents 处理进程的消息队列中的消息…