后端优化之通用返回对象与全局异常处理器

通用返回对象

1.通用返回对象

目的:给对象补充一些信息,告诉前端这个请求在业务层面上是成功还是失败

200、404、500、502


//通常我们的返回结果
{
    "name": taoha
   
}

//使用统一对象后正常的返回
{
    "code": 0 //业务状态码
    "data": {
    	"name": "taoha"
	},
	"message": "ok"
}



//使用统一对象后异常的返回
{
    "code": 50001  //业务状态码
    "data": null
    "message": "用户操作异常..."
}
/**
 * 通用返回类
 *
 * @param <T>
 * @author taoha
 */
@Data
public class BaseResponse<T> implements Serializable {

    private int code;

    private T data;

    private String message;

    private String description;

    public BaseResponse(int code, T data, String message, String description) {
        this.code = code;
        this.data = data;
        this.message = message;
        this.description = description;
    }

    public BaseResponse(int code, T data, String message) {
        this(code, data, message, "");
    }

    public BaseResponse(int code, T data) {
        this(code, data, "", "");
    }

    public BaseResponse(ErrorCode errorCode) {
        this(errorCode.getCode(), null, errorCode.getMessage(), errorCode.getDescription());
    }
}

返回成功对象效果:

在这里插入图片描述

需要将原本控制器中的方法的类型和返回对象进行包装

优点: 返回了统一的对象

缺点:每个返回对象中的属性都需要亲自手敲,可能出现错误,例如(message:ok message:okk)

改进:写一个工具类,让工具类帮助我们返回一个成功或失败的BaseResponse对象

2.定义一个工具类

/**
 * 返回工具类
 *
 * @author taoha
 */
public class ResultUtils {

    /**
     * 成功
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> BaseResponse<T> success(T data) {
        return new BaseResponse<>(0, data, "ok");
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode) {
        return new BaseResponse<>(errorCode);
    }

    /**
     * 失败
     *
     * @param code
     * @param message
     * @param description
     * @return
     */
    public static BaseResponse error(int code, String message, String description) {
        return new BaseResponse(code, null, message, description);
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode, String message, String description) {
        return new BaseResponse(errorCode.getCode(), null, message, description);
    }

    /**
     * 失败
     *
     * @param errorCode
     * @return
     */
    public static BaseResponse error(ErrorCode errorCode, String description) {
        return new BaseResponse(errorCode.getCode(), errorCode.getMessage(), description);
    }
}

效果:

在这里插入图片描述

接着针对失败返回

在这里插入图片描述

-1 或 null 的指向性不是特别好,前端或者后端并不知道这个-1所代表的错误具体是什么

解决:定义一个通用的错误码或定义一套错误码规范: 可以定义一个枚举值对象

3.定义一个枚举值对象

/**
 *
 * 错误码
 * @Author   taoha
 */


public enum ErrorCode {

    SUCCESS(0, "ok", ""),
    PARAMS_ERROR(40000, "请求参数错误", ""),
    NULL_ERROR(40001, "请求数据为空", ""),
    NOT_LOGIN(40100, "未登录", ""),
    NO_AUTH(40101, "无权限", ""),
    SYSTEM_ERROR(50000, "系统内部异常", "");

    private final int code;

    /**
     * 状态码信息
     */
    private final String message;

    /**
     * 状态码描述(详情)
     */
    private final String description;


    ErrorCode(int code, String message, String description) {
        this.code = code;
        this.message = message;
        this.description = description;
    }
        public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public String getDescription() {
        return description;
    }

}

返回失败对象效果:

在这里插入图片描述

优点:通过定义错误码规范,返回的错误更具有指向性

全局异常处理器

使用统一返回对象时,还有一种情况,就是程序的报错是由于运行时异常导致的结果,有些异常是我们在业务中抛出的,有些是无法提前预知。

因此,我们需要定义一个统一的全局异常,在全局捕获所有异常,并且做适当处理,并作为同一对象返回

设计思路:
1.自定一个异常类,捕获针对项目或业务的异常;
2.使用@ExceptionHandler注解捕获自定义异常和通用异常;
3.使用@ControllerAdvice集成@ExceptionHandler的方法到一个类中;
4.异常的对象信息补充到统一结果枚举中;

4.自定义业务异常类

/**
 * 自定义异常类
 *
 * @author taoha
 */
public class  BusinessException extends RuntimeException {

    private final int code;

    private final String description;

    public BusinessException(String message, int code, String description) {
        super(message);
        this.code = code;
        this.description = description;
    }

    public BusinessException(ErrorCode errorCode) {
        super(errorCode.getMessage());
        this.code = errorCode.getCode();
        this.description = errorCode.getDescription();
    }

    public BusinessException(ErrorCode errorCode, String description) {
        super(errorCode.getMessage());
        this.code = errorCode.getCode();
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }
}

效果:

在这里插入图片描述

区别:第一个框是直接返回,现在是抛出异常

同理service中:

在这里插入图片描述
上面是我们可提前预知的业务异常,而对于一些不可预知的系统异常,我们是不能直接返回给前端的

因此我们还需要一个全局异常处理器:

1.捕获代码中所有(业务异常和系统异常)的异常,内部消化,让前端感知到更详细的业务报错/信息,

2.同时屏蔽掉项目框架本身的异常(不暴露服务器内部状态)

3.集中处理,eg:记录日志

5.封装全局异常处理器

实现:

1.SpringAOP:在调用方法前后进行额外的处理

package com.th.usercenter.exception;

import com.th.usercenter.common.BaseResponse;
import com.th.usercenter.common.ErrorCode;
import com.th.usercenter.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全集异常处理器
 * @author taoha
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    //业务异常
    @ExceptionHandler(BusinessException.class)
    public BaseResponse businessExceptionHandle(BusinessException e){
        log.error("businessException: "+ e.getMessage(),e);
        return ResultUtils.error(e.getCode(),e.getMessage(),e.getDescription());
    }
    //系统异常
    @ExceptionHandler(RuntimeException.class)
    public BaseResponse runtimeExceptionHandle(BusinessException e){
        log.error("businessException",e);
        return ResultUtils.error(ErrorCode.SYSTEM_ERROR,e.getMessage(),"");
    }

}

项目结构:

在这里插入图片描述

总结:

1. 通用返回对象 
   		目的:给对象补充一些信息,告诉前端这个请求在业务层面上是成功还是失败
 自定义错误码 
返回类支持返回正常和错误
2.  封装全局异常处理 
  a.  定义业务异常类 
    ⅰ. 相对于 java 的异常类,支持更多字段
    ⅱ. 自定义构造函数,更灵活 / 快捷的设置字段
  b.  编写全局异常处理器
作用: 
    ⅰ. 捕获代码中所有的异常,内部消化,让前端得到更详细的业务报错 / 信息
    ⅱ. 同时屏蔽掉项目框架本身的异常(不暴露服务器内部状态)
    ⅲ. 集中处理,比如记录日志
实现: 
    ⅰ. Spring AOP:在调用方法前后进行额外的处理
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值