《Spring Boot应用进阶:打造优雅的错误处理机制与全局异常拦截器》

简介: 《Spring Boot应用进阶:打造优雅的错误处理机制与全局异常拦截器》

本文主要介绍自己在工作中在处理抛出异常类和封装响应类处理的模板总结。

对于后端程序员来说,抛出异常和返回响应别提有多重要了对吧。其实在真正的企业级开发中,这步工作也不需要你去做,公司都给你封装好了的,你直接用就行。由于我最近从0到1负责了一个完整的项目,在最近的后期优化过程中,我需要考虑重新设计 自定义异常类与统一响应,所以特此总结该文,以供学习。

自定义异常类AppException

自定义异常类AppException需要继承至 RuntimeException运行时异常。

public class AppException extends RuntimeException{
    private int code = 500;
    private String msg = "服务器异常";
    public AppException(AppExceptionCodeMsg appExceptionCodeMsg){
        super();
        this.code = appExceptionCodeMsg.getCode();
        this.msg = appExceptionCodeMsg.getMsg();
    }
    public AppException(int code,String msg){
        super();
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

封装业务有关的枚举类AppExceptionCodeMsg

利用枚举类将常用的业务异常进行配置,封装:

INVALID_CODE(10000,"验证码无效"),
USERNAME_NOT_EXISTS(10001,"用户名不存在"),
USER_CREDIT_NOT_ENOUTH(10002,"用户积分不足");

这样做的好处是,配置灵活,不需要去硬编码。

完整的枚举类如下:

//这个枚举类中定义的都是跟业务有关的异常
public enum AppExceptionCodeMsg {
    INVALID_CODE(10000,"验证码无效"),
    USERNAME_NOT_EXISTS(10001,"用户名不存在"),
    USER_CREDIT_NOT_ENOUTH(10002,"用户积分不足");
    ;
    private int code ;
    private String msg ;
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    AppExceptionCodeMsg(int code, String msg){
        this.code = code;
        this.msg = msg;
    }
}

全局异常拦截器Handler

这个拦截器的作用就是在抛出异常之前进行拦截,先判断是不是要抛出你自定义的异常,如果不是则放行。

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = {Exception.class})
    @ResponseBody
    public <T> Resp<T> exceptionHandler(Exception e){
        //这里先判断拦截到的Exception是不是我们自定义的异常类型
        if(e instanceof AppException){
            AppException appException = (AppException)e;
            return Resp.error(appException.getCode(),appException.getMsg());
        }
        //如果拦截的异常不是我们自定义的异常(例如:数据库主键冲突)
        return Resp.error(500,"服务器端异常");
    }
}

响应类模板Resp

其实这个响应类模板网上到处都是,自己也可以随意找到,以下是我的模板:

public class Resp<T> {
    //服务端返回的错误码
    private int code = 200;
    //服务端返回的错误信息
    private String msg = "success";
    //我们服务端返回的数据
    private T data;
    private Resp(int code,String msg,T data){
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static <T> Resp success(T data){
        Resp resp = new Resp(200, "success", data);
        return resp;
    }
    public static <T> Resp success(String msg,T data){
        Resp resp = new Resp(200,msg, data);
        return resp;
    }
    public static <T> Resp error(AppExceptionCodeMsg appExceptionCodeMsg){
        Resp resp = new Resp(appExceptionCodeMsg.getCode(), appExceptionCodeMsg.getMsg(), null);
        return resp;
    }
    public static <T> Resp error(int code,String msg){
        Resp resp = new Resp(code,msg, null);
        return resp;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public T getData() {
        return data;
    }
}

案例展示 || Demo

接下来我将用一个SpringBoot项目综合上述异常类与响应类综合展示具体情况,看官们也可以自行下载demo直接在自己的电脑上跑起来学习。

项目结构

│  pom.xml
├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─linghu
│  │  │          └─demo
│  │  │              │  DemoApplication.java
│  │  │              │
│  │  │              ├─controller
│  │  │              │      DemoController.java
│  │  │              │
│  │  │              ├─exception
│  │  │              │      AppException.java
│  │  │              │      AppExceptionCodeMsg.java
│  │  │              │      GlobalExceptionHandler.java
│  │  │              │
│  │  │              └─resp
│  │  │                      Resp.java
│  │  │
│  │  └─resources
│  │          application.yml
│  │
│  └─test
│      └─java

pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>exceptiondemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

DemoController

web层api代码设计如下:

@RestController
public class DemoController {
    @GetMapping("demo")
    public Resp<String> demo1(String name){
        if("ok".equals(name)){
            return Resp.success("succ");
        }
        if("err".equals(name)){
            //抛业务相关的异常
            throw new AppException(AppExceptionCodeMsg.USERNAME_NOT_EXISTS);
        }
        if("errcode".equals(name)){
            throw new AppException(AppExceptionCodeMsg.INVALID_CODE);
        }
        if("0".equals(name)){
            int i=1/0;
        }
        //检查用户积分是否足够,如果不够,就抛出异常
        if("notenough".equals(name)){
            throw new AppException(AppExceptionCodeMsg.USER_CREDIT_NOT_ENOUTH);
        }
        return Resp.success("default");
    }
    @GetMapping("list")
    public Resp<List> list(){
        List<String> list = Arrays.asList("zhangsan","lisi","wangwu");
        return Resp.success(list);
    }
}

实际执行结果

大家可以自行下载代码跑一跑学习一下。

Demo案例Git地址 | Gitee

该教程其实很简单,欢迎大家下载学习!

完整Demo如下:

《Exception_Auto_Demo》

目录
相关文章
|
7月前
|
Java 开发者 UED
Spring Boot的全局异常处理机制
【2月更文挑战第13天】
404 0
|
2月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
48 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
5月前
|
JSON Java 数据库
Spring Boot中的全局异常处理
主要讲解了Spring Boot 的全局异常处理,包括异常信息的封装、异常信息的捕获和处理,以及在实际项目中,我们用到的自定义异常枚举类和业务异常的捕获与处理,在项目中运用的非常广泛,基本上每个项目中都需要做全局异常处理。
|
7月前
|
安全 前端开发 Java
Spring Security 自定义异常失效?从源码分析到解决方案
Spring Security 自定义异常失效?从源码分析到解决方案
|
7月前
|
JSON 前端开发 Java
统一异常处理:让Spring Boot项目异常更优雅
统一异常处理:让Spring Boot项目异常更优雅
56 1
|
7月前
|
前端开发 Java 数据安全/隐私保护
Spring Boot3自定义异常及全局异常捕获
Spring Boot3自定义异常及全局异常捕获
599 1
|
7月前
|
前端开发 Java UED
如何使用 Spring Boot 实现全局异常处理
如何使用 Spring Boot 实现全局异常处理
|
JSON 安全 Java
Spring Boot之全局异常处理:404异常为何捕获不到?
Spring Boot之全局异常处理:404异常为何捕获不到?
1620 0
Spring Boot之全局异常处理:404异常为何捕获不到?
|
存储 JSON 缓存
Spring 统一异常处理的方式
Spring 统一异常处理的方式
93 0
|
Java Spring
Spring Boot 监听器、拦截器以及过滤器的作用、差异?
Spring Boot 监听器、拦截器以及过滤器的作用、差异?
231 0
下一篇
DataWorks