SpringBoot全局异常处理,返回数据附带http状态码,以及捕获404页面异常

发布时间 2023-07-10 21:51:35作者: 绿树荫下跑猫猫

SpringBoot全局异常处理,返回数据附带http状态码,以及捕获404页面异常

前言

全局异常处理对于编写网络接口程序来说至关重要,能省掉很多的判断语句,让逻辑更加清晰。springboot中的全局异常处理并不难。与网上大部分文章不同的是,我用springboot自带的ResponseEntity给返回结果加上了了http状态码。当然有些人的接口可能全部返回200状态也是可以,但是为了以后的兼容性,还是加上状态码比较好。

代码部分

1.定义一个枚举类

枚举类的作用:预先定义好一些常用的状态信息,便于集中状态信息的集中管理

当然这个类也可以不加,但是当编写大项目的时候会变得乱七八糟。

package com.test.exception;

public enum ExceptionEnum{
    //下面是一些预先定义的状态信息
    SUCCESS(200, true, "成功!"),
    SIGNATURE_NOT_MATCH(403,false,"服务器拒绝!"),
    NOT_FOUND(404, false,"未找到该资源!"),
    URL_NOT_FOUND(404, false,"URL不存在!"),
    INTERNAL_SERVER_ERROR(500, false,"服务器内部错误!");

    private final Integer resultCode;
    private final Boolean resultStatus;
    private final String resultMsg;
    //构造函数
    ExceptionEnum(Integer resultCode, Boolean resultStatus, String resultMsg) {
        this.resultCode = resultCode;
        this.resultStatus = resultStatus;
        this.resultMsg = resultMsg;
    }
    
    public Integer getResultCode() { return resultCode;  }
    public Boolean getResultStatus() { return resultStatus; }
    public String getResultMsg() { return resultMsg; }
}

2.统一信息返回格式

统一返回信息json格式为:

{
    "status":true,
    "data":{...},
    "msg":"获取成功"
}

统一信息返回类代码:

主要为了统一返回格式,这样前后端的开发才能更好的结合,代码编写更规范,更易于理解。

package com.test.exception;
import lombok.Data;

@Data
public class R {
    private Boolean status;
    private Object data;
    private String msg;

    public R() {
    }

    //完全自定义的返回,适用于没遇到过的情况
    public R(Boolean status, Object data, String msg) {
        this.status = status;
        this.data = data;
        this.msg = msg;
    }

    //status为true时,用于正常返回,即200状态
    public R(Object data, String msg) {
        this.status = true;
        this.data = data;
        this.msg = msg;
    }
    //status为false时,用于异常类的返回格式
    public R(String msg) {
        this.status = false;
        this.data = null;	//如果失败,data可以直接不反悔
        this.msg = msg;
    }
    //普通的已存在枚举类中的异常
    public R(ExceptionEnum exceptionEnum) {
        throw new MyExceptionHandler(exceptionEnum);
    }
}

3.自定义异常类

继承RuntimeException才能通过抛出这个类来触发异常处理。

这个类很重要,没有这个类不行,因为最终抛出去的就是这个类。

package com.test.exception;

public class MyExceptionHandler extends RuntimeException{
    private Integer code ;	//http状态码
    private Boolean status;
    private String msg ;
    //此构造函数用于枚举中已有的异常
    public MyExceptionHandler(ExceptionEnum exceptionEnum){
        super();
        this.code = exceptionEnum.getResultCode();
        this.status = exceptionEnum.getResultStatus();
        this.msg = exceptionEnum.getResultMsg();
    }
    //完全自定义
    public MyExceptionHandler(Integer code, Boolean status, String msg){
        super(msg);
        this.code = code;
        this.status = status;
        this.msg = msg;
    }
    //用于其他服务器拒绝的情况,比如具体的参数错误,参数格式错误等,这个可能用的比较多,所以单独一个,可自行扩展
    public MyExceptionHandler(Boolean status, String msg){
        super(msg);
        this.code = 403;
        this.status = status;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public Boolean getStatus() {
        return status;
    }

    public String getMsg() {
        return msg;
    }
}

4.全局异常处理函数

这个类也很重要,主要是捕获全局异常,并返回相应的数据。

package com.test.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestControllerAdvice
public class GlobalExceptionHandler {
    //处理普通系统异常
    @ExceptionHandler(value = Exception.class)
    public R systemException(Exception e){
        e.printStackTrace();
     	System.out.println("=======================>>"+e.getMessage()+"=============================");
        return new R(false,null,"系统内部异常,请联系管理员");
    }
    
    
    
    //处理自定义异常
    @ExceptionHandler(value = MyExceptionHandler.class)
    public ResponseEntity<R> myException(MyExceptionHandler e){
        e.printStackTrace();
        ResponseEntity<R> responseEntity;
        switch (e.getCode()){
            case 403:
                responseEntity =  ResponseEntity.status(HttpStatus.FORBIDDEN).body(new R(e.getMsg()));
                break;
            case 404:
                responseEntity =  ResponseEntity.status(HttpStatus.NOT_FOUND).body(new R(e.getMsg()));
                break;
            default:
                responseEntity =  ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new R(e.getMsg()));
                break;
        }

        return responseEntity;

    }
}

5.(补充)404页面不存在异常捕获

在进行全局异常处理的时候,如果访问的url不存在,并不会被全局异常处理捕获到,所以还需要一个类来专门处理页面不存在即url错误的异常信息。

package com.test.exception;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UrlNotFoundException implements ErrorController {
    @RequestMapping("/error")
    public R handle404Error() {
        // 处理自定义的url错误 404 错误逻辑
        return new R(ExceptionEnum.URL_NOT_FOUND);
    }
}

结语

当然,我这个异常处理的代码中还有不少值得优化的地方,但是整体的流程大体就是这么个流程,不会有太大的变化。