统一异常处理ControllerAdvice

我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况。通过使用@ControllerAdvice定义统一的异常处理类,统一处理异常信息。方便统一生成记录错误日志信息和异常处理。

1、全局错误代码:

package com.tumake.common.core.constant;

import java.io.Serializable;

/**
 * @Auther: stc66@qq.com
 * @Date: 2021/9/1
 * @Description: com.tumake.common.core.constant
 * @Version: 1.0
 */
public enum ResultCode implements Serializable {
    SUCCESS(200, "操作成功"),
    FAILURE(400, "业务异常"),
    UN_AUTHORIZED(401, "请求未授权"),
    NOT_FOUND(404, "404 没找到请求"),
    MSG_NOT_READABLE(400, "消息不能读取"),
    METHOD_NOT_SUPPORTED(405, "不支持当前请求方法"),
    MEDIA_TYPE_NOT_SUPPORTED(415, "不支持当前媒体类型"),
    REQ_REJECT(403, "请求被拒绝"),
    INTERNAL_SERVER_ERROR(500, "服务器异常"),
    PARAM_MISS(400, "缺少必要的请求参数"),
    PARAM_TYPE_ERROR(400, "请求参数类型错误"),
    PARAM_BIND_ERROR(400, "请求参数绑定错误"),
    PARAM_VALID_ERROR(400, "参数校验失败");

    public final int code;
    public final String message;

    public int getCode() {
        return this.code;
    }

    public String getMessage() {
        return this.message;
    }

    private ResultCode(final int code, final String message) {
        this.code = code;
        this.message = message;
    }
}

2、全局消息:

package com.tumake.common.core.vo;

import com.tumake.common.core.constant.ResultCode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.Optional;

/**
 * 返回消息
 *
 * @Auther: stc66@qq.com
 * @Date: 2021/9/1
 * @Description: com.tumake.common.core.vo
 * @Version: 1.0
 */
@ApiModel(description = "返回信息")
public class ResultData<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "状态码", required = true)
    private int code;

    @ApiModelProperty(value = "是否成功", required = true)
    private boolean success;

    @ApiModelProperty("承载数据")
    private T data;

    @ApiModelProperty(value = "返回消息", required = true)
    private String msg;

    private ResultData(ResultCode resultCode) {
        this(resultCode, (T) null, resultCode.getMessage());
    }

    private ResultData(ResultCode resultCode, String msg) {
        this(resultCode, (T) null, msg);
    }

    private ResultData(ResultCode resultCode, T data) {
        this(resultCode, data, resultCode.getMessage());
    }

    private ResultData(ResultCode resultCode, T data, String msg) {
        this(resultCode.getCode(), data, msg);
    }

    private ResultData(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.success = ResultCode.SUCCESS.code == code;
    }

    public ResultData() {
    }

    public static boolean isSuccess(@Nullable ResultData<?> result) {
        return (Boolean) Optional.ofNullable(result).map((x) -> {
            return ObjectUtils.nullSafeEquals(ResultCode.SUCCESS.code, x.code);
        }).orElse(Boolean.FALSE);
    }

    public static boolean isNotSuccess(@Nullable ResultData<?> result) {
        return !isSuccess(result);
    }

    public static <T> ResultData<T> data(T data) {
        return data(data, "操作成功");
    }

    public static <T> ResultData<T> data(T data, String msg) {
        return data(200, data, msg);
    }

    public static <T> ResultData<T> data(int code, T data, String msg) {
        return new ResultData(code, data, data == null ? "暂无承载数据" : msg);
    }

    public static <T> ResultData<T> success(String msg) {
        return new ResultData(ResultCode.SUCCESS, msg);
    }

    public static <T> ResultData<T> success(ResultCode resultCode) {
        return new ResultData(resultCode);
    }

    public static <T> ResultData<T> success(ResultCode resultCode, String msg) {
        return new ResultData(resultCode, msg);
    }

    public static <T> ResultData<T> fail(String msg) {
        return new ResultData(ResultCode.FAILURE, msg);
    }

    public static <T> ResultData<T> fail(int code, String msg) {
        return new ResultData(code, (Object) null, msg);
    }

    public static <T> ResultData<T> fail(ResultCode resultCode) {
        return new ResultData(resultCode);
    }

    public static <T> ResultData<T> fail(ResultCode resultCode, String msg) {
        return new ResultData(resultCode, msg);
    }

    public static <T> ResultData<T> status(boolean flag) {
        return flag ? success("操作成功") : fail("操作失败");
    }

    public int getCode() {
        return this.code;
    }

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

    public boolean isSuccess() {
        return this.success;
    }

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

    public T getData() {
        return this.data;
    }

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

    public String getMsg() {
        return this.msg;
    }

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

    public String toString() {
        return "ResultData(code=" + this.getCode() + ", success=" + this.isSuccess() + ", data=" + this.getData() + ", msg=" + this.getMsg() + ")";
    }
}

3、全局异常处理:

package com.tumake.common.core.exception;

import com.tumake.common.core.constant.ResultCode;
import com.tumake.common.core.vo.ResultData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @Auther: stc66@qq.com
 * @Date: 2021/9/5
 * @Description: com.tumake.common.core.exception
 * @Version: 1.0
 */
@Slf4j
@ControllerAdvice
public class GlobalException {

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public ResultData<String> readableException(HttpMessageNotReadableException e) {
        log.error("入参为空,数据转换异常", e);
        return ResultData.fail(ResultCode.PARAM_MISS);
    }
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultData<String> bindException(BindException e) {
        StringBuffer sb = new StringBuffer();
        e.getFieldErrors()
                .forEach(fieldError -> sb.append(fieldError.getField() + ":" + fieldError.getDefaultMessage()).append(","));
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        log.error("参数绑定异常", e);
        return ResultData.fail(ResultCode.PARAM_BIND_ERROR, sb.toString());
    }

    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public ResultData<String> runtimeException(RuntimeException e) {
        log.error("运行异常", e);
        return ResultData.fail(ResultCode.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResultData<String> exception(Exception e) {
        log.error("系统未知异常", e);
        return ResultData.fail(ResultCode.INTERNAL_SERVER_ERROR);
    }
}

 

posted @ 2021-09-05 16:35  滔天蟹  阅读(224)  评论(0编辑  收藏  举报