全局异常拦截和返回值封装

发布时间 2023-04-05 17:30:30作者: masy

全局异常拦截和返回值封装共分为五个类,分别是错误码枚举类、返回值封装类、自定义业务异常类、全局拦截类、全局返回值处理类。

错误码枚举类

用来定义返回值的错误码。

package com.masy.global.exception;

/**
 * @ClassName ErrorCode
 * @Description 错误码枚举
 * @Author masy
 * @Date 2023/4/322:18
 **/
public enum ErrorCode {


    /*成功*/
    SUCCESS(0, "成功"),
    FAIL(500, "失败"),

    SYSTEM_ERROR(10000, "系统异常"),

    PARAM_ERROR(10100, "参数异常"),

    USER_AUTH_FAIL(20001, "用户鉴权失败"),
    ;
    private Integer code;
    private String msg;

    ErrorCode(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static String getMsgByCode(Integer code) {
        for (ErrorCode ec : values()) {
            if (ec.getCode().equals(code)) {
                return ec.getMsg();
            }
        }
        return null;
    }
}

返回值封装类

用来将返回值统一封装。

package com.masy.global.exception;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * @ClassName Result
 * @Description 返回值封装
 * @Author masy
 * @Date 2023/4/322:18
 **/
public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1581329103599839148L;
    private boolean success;

    private Integer code;

    private String msg;

    private T data;

    private LocalDateTime timestamp = LocalDateTime.now();

    public Result() {
        this.success = true;
        this.code = ErrorCode.SUCCESS.getCode();
        this.msg = ErrorCode.SUCCESS.getMsg();
    }

    public Result(boolean success) {
        this.success = success;
        this.code = success ? ErrorCode.SUCCESS.getCode() : ErrorCode.FAIL.getCode();
        this.msg = success ? ErrorCode.SUCCESS.getMsg() : ErrorCode.FAIL.getMsg();
        this.timestamp = LocalDateTime.now();
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public void setData(T data) {
        this.data = data;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static <T> Result<T> success() {
        Result<T> res = new Result<>();
        res.setSuccess(true);
        res.setCode(ErrorCode.SUCCESS.getCode());
        res.setMsg(ErrorCode.SUCCESS.getMsg());
        return res;
    }

    public static <T> Result<T> success(T data) {
        Result<T> res = new Result<>();
        res.setSuccess(true);
        res.setCode(ErrorCode.SUCCESS.getCode());
        res.setMsg(ErrorCode.SUCCESS.getMsg());
        res.setData(data);
        return res;
    }

    public static <T> Result<T> fail(ErrorCode errorResponse) {
        Result<T> res = new Result<>();
        res.setSuccess(false);
        res.setCode(errorResponse.getCode());
        res.setMsg(errorResponse.getMsg());
        return res;
    }

    public static <T> Result<T> fail(ErrorCode errorResponse, T data) {
        Result<T> res = new Result<>();
        res.setSuccess(false);
        res.setCode(errorResponse.getCode());
        res.setMsg(errorResponse.getMsg());
        res.setData(data);
        return res;
    }

    public boolean isSuccess() {
        return success;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(LocalDateTime timestamp) {
        this.timestamp = timestamp;
    }
}

自定义业务异常类

用来抛出业务异常。

package com.masy.global.exception;

/**
 * @ClassName BusinessException
 * @Description 业务异常
 * @Author masy
 * @Date 2023/4/322:18
 **/
public class BusinessException extends RuntimeException {

    private ErrorCode errorCode;

    public BusinessException() {
        this.errorCode = ErrorCode.FAIL;
    }

    public BusinessException(ErrorCode errorCode) {
        this.errorCode = errorCode;
    }

    public ErrorCode getErrorCode() {
        return errorCode;
    }
}

全局异常拦截类

用来拦截抛出的异常,做处理。

package com.masy.global.exception;

import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


/**
 * @ClassName GlobalExceptionHandler
 * @Description 全局异常拦截
 * @Author masy
 * @Date 2023/4/322:18
 **/
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 空指针异常
     *
     * @param e 异常
     * @return com.masy.global.exception.Result<?>
     * @author masy
     * @date 2023/4/3 22:46
     */
    @ExceptionHandler(value = NullPointerException.class)
    public Result<?> handler(NullPointerException e) {
        return Result.fail(ErrorCode.SYSTEM_ERROR);
    }

    /**
     * 参数异常
     *
     * @param e 异常
     * @return com.masy.global.exception.Result<?>
     * @author masy
     * @date 2023/4/3 22:46
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result<?> handler(MethodArgumentNotValidException e) {
        return Result.fail(ErrorCode.PARAM_ERROR);
    }

    /**
     * 捕获业务异常
     *
     * @param e 异常
     * @return com.masy.global.exception.Result<?>
     * @author masy
     * @date 2023/4/3 22:46
     */
    @ExceptionHandler(value = BusinessException.class)
    public Result<?> handler(BusinessException e) {
        return Result.fail(e.getErrorCode());
    }

    /**
     * 捕获其他异常
     *
     * @param e 异常
     * @return com.masy.global.exception.Result<?>
     * @author masy
     * @date 2023/4/3 22:46
     */
    @ExceptionHandler(value = Exception.class)
    public Result<?> handler(Exception e) {
        return Result.fail(ErrorCode.FAIL);
    }
}

全局返回值处理类

用来将返回值统一封装,不用在每个接口中封装。

package com.masy.global.config;

import com.masy.global.exception.Result;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @ClassName ResponseResultAdvice
 * @Description 返回数据封装
 * @Author masy
 * @Date 2023/4/323:49
 **/
@RestControllerAdvice
public class ResponseResultAdvice implements ResponseBodyAdvice<Object> {

    /**
     * 跳过判断是否有返回值,直接调用beforeBodyWrite
     *
     * @param returnType    返回值类型
     * @param converterType
     * @return boolean
     * @author masy
     * @date 2023/4/3 23:50
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Result) {
            return body;
        } else {
            return Result.success(body);
        }
    }
}

使用

package com.masy.global.controller;

import com.alibaba.fastjson.JSON;
import com.masy.global.exception.BusinessException;
import com.masy.global.exception.ErrorCode;
import com.masy.global.exception.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName Test
 * @Description TODO
 * @Author masy
 * @Date 2023/4/322:54
 **/
@RestController
@RequestMapping("test")
public class Test {

    @GetMapping()
    public Map<String,String> test() {
        Map<String,String> map = new HashMap<>();
        map.put("a","1");
        return map;
    }

    @GetMapping("success")
    public Result<Map<String,String>> test1() {
        Map<String,String> map = new HashMap<>();
        map.put("a","1");
        return Result.success(map);
    }


    @GetMapping("fail")
    public Result<String> fail(){
        throw new BusinessException(ErrorCode.PARAM_ERROR);
    }
}

返回效果