欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringBoot项目如何做到统一异常处理

程序员文章站 2022-04-14 16:33:18
在项目中,难免会出现各种各样的异常,我们希望异常信息尽可能详细,包括响应状态码,响应的字符串异常信息,甚至操作时间等等,这样可以方便地快速定位到发生异常的位置.所以,一个项目中对于异常的处理就显得尤为重要.那么,小编就以SpringBoot框架,通过代码实例展示统一异常的处理方式. 1.首先我们简单 ......

在项目中,难免会出现各种各样的异常,我们希望异常信息尽可能详细,包括响应状态码,响应的字符串异常信息,甚至操作时间等等,这样可以方便地快速定位到发生异常的位置.所以,一个项目中对于异常的处理就显得尤为重要.那么,小编就以springboot框架,通过代码实例展示统一异常的处理方式.

1.首先我们简单搭建一个springboot框架的项目,项目名称是exceptionhandler(异常处理)

SpringBoot项目如何做到统一异常处理

2.导入相关依赖

导入lombok依赖,提供@getter注解

导入日期工具类jodatime,提供datetime.now()方法

<parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.1.8.release</version>
    </parent>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
        </dependency>
        <!--日期工具类:jodatime-->
        <dependency>
            <groupid>joda-time</groupid>
            <artifactid>joda-time</artifactid>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupid>org.springframework.boot</groupid>
                <artifactid>spring-boot-maven-plugin</artifactid>
            </plugin>
        </plugins>
    </build>

3.编写application.yml配置文件

注意这里添加了访问路径前缀

server:
  port: 8082
  servlet:
    context-path: /exception

4.编写springboot的启动类

package com.exception;

import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;

@springbootapplication
public class exceptionapplication {
    public static void main(string[] args) {
        springapplication.run(exceptionapplication.class, args);
    }
}

5.编写异常枚举类

异常枚举类中,应该列举出项目可能出现的所有异常类型,这里只拿数学计算异常举例

package com.exception.enums;

import lombok.getter;

/**
 * 异常枚举类
 */
@getter
public enum exceptionenum {
    artithmetic(500, "数学计算异常");
    private integer status;
    private string message;

    exceptionenum(integer status, string message) {
        this.status = status;
        this.message = message;
    }
}

6.编写自定义异常类

自定义异常类继承runtimeexception,同时runtimeexception继承exception类,而exception又继承throwable类,super方法最终也是throwable中的方法

SpringBoot项目如何做到统一异常处理

package com.exception.exceptions;

import com.exception.enums.exceptionenum;
import lombok.getter;

/**
 * 自定义异常类
 */
@getter
public class selfdefinedexception extends runtimeexception {
    private integer status;

    public selfdefinedexception(exceptionenum exceptionenum) {
        super(exceptionenum.getmessage());
        this.status = exceptionenum.getstatus();
    }

    public selfdefinedexception(exceptionenum exceptionenum, throwable cause) {
        super(exceptionenum.getmessage(), cause);
        this.status = exceptionenum.getstatus();
    }
}

7.编写统一异常返回结果类

package com.exception.entity;

import com.exception.exceptions.selfdefinedexception;
import lombok.getter;
import org.joda.time.datetime;

/**
 * 统一异常返回结果类
 */
@getter
public class exceptionresult {
    private integer status;
    private string message;
    private string timestamp;

    public exceptionresult(selfdefinedexception e) {
        this.status = e.getstatus();
        this.message = e.getmessage();
        this.timestamp = datetime.now().tostring("yyyy-mm-dd hh:mm:ss");
    }
}

8.编写统一异常拦截类

需注意两个spring注解的作用:

@controlleradvice:此注解默认情况下,会拦截所有加了@controller注解的类

@exceptionhandler():此注解用在方法上,括号内声明要处理的异常类型,可以指定多个,这里我们指定的是自定义异常

package com.exception.advice;

import com.exception.entity.exceptionresult;
import com.exception.exceptions.selfdefinedexception;
import lombok.extern.slf4j.slf4j;
import org.springframework.http.responseentity;
import org.springframework.web.bind.annotation.controlleradvice;
import org.springframework.web.bind.annotation.exceptionhandler;

/**
 * 统一异常拦截类
 */
@controlleradvice
@slf4j
public class basicexceptionadvice {
    @exceptionhandler(selfdefinedexception.class)
    public responseentity<exceptionresult> handlerexception(selfdefinedexception e) {//参数类型与要处理的异常类型必须匹配
        return responseentity.status(e.getstatus()).body(new exceptionresult(e));//body中的对象必须和responseentity中的对象一致
    }
}

9.编写测试类

package com.exception.controller;

import com.exception.enums.exceptionenum;
import com.exception.exceptions.selfdefinedexception;
import lombok.extern.slf4j.slf4j;
import org.springframework.http.responseentity;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.postmapping;
import org.springframework.web.bind.annotation.restcontroller;

@restcontroller
@slf4j
public class testcontroller {
    @getmapping("/test")
    public responseentity<string> login() {
        try {
            integer tempvalue = 10 / 0;
        } catch (exception e) {
            throw new selfdefinedexception(exceptionenum.artithmetic);//catch捕获异常后,这里throw抛出异常并未处理,所以后面的代码不会执行
        }
        return responseentity.ok("没发现异常,返回正确的字符串");
    }
}

10.测试结果

通过idea自带的http client进行测试,观察响应结果如下.这样我们就得到了

SpringBoot项目如何做到统一异常处理

总结:

因为项目中会出现各种各样的异常,所以我们通过一个异常枚举类将所有的异常进行列举.我们希望捕获自己定义的异常,所以编写了一个自定义异常类,同时我们希望响应的异常结果规则且详细,所以通过一个统一异常结果类来实现.最重要的是,我们还需要一个异常拦截类,这样在我们抛出自定义异常的时候,这个异常拦截类能够进行拦截,并将我们定义好的响应结果(也就是异常体所有信息)返回.