如何优雅实现统一的响应对象?

一、常见场景
目前主流开发方式都是前后端分离的,定义一种统一的返回格式,在前后端进行沟通时是非常有必要的,减少大家的沟通成本,大家基于这个约定去理解,出现问题能够快速定位。 格式统一规范,也是减少联调挨骂的基本保障。接下来就介绍一下如何优雅实现统一的】、响应对象。

二、统一的响应对象一般包括哪些字段呢,根据我之前的项目经验,一般有以下几个字段,如下所示:

{
"code": 0,
"message": "成功",
"detailMessage": "成功",
"data": true,
"traceId": "8bca519e60b35b",
"spanId": "1540451004024094720",
"env": "dev"
}

code: 返回结果的状态码,通常都是6位,比如A业务:100000-199999,B业务:200000-299999,C业务:300000-399999,不同的数字开头代表不同的业务
message: 返回结果的描述消息,展示给用户看的
detailMessage: 内部开发人员看的消息(详细的错误信息,主要方便问题定位)
data: 返回给调用方的业务数据(通常都是json数据)
traceId: 分布式链路跟踪-traceId(通常与日志平台结合使用)
spanId: 分布式链路跨度-spanId,spanId组合在一起就是整个链路的trace
env: 当前服务部署的环境(比如dev、sit、uat、prod)

三、实现方案及实现步骤
1、定义一个通用的统一返回码接口:IRespResultCode.java,接口里面规范子类对象要实现的方法,例如:getCode(),getMessage(),getDetailMessage()。
2、定义一个通用的统一返回码对象:RespResultCode.java实现IRespResultCode接口 ,主要放通用的返回结果信息,例如:请求成功、系统异常、网络异常、参数不合法等信息。
3、定义一个处理返回结果的工具类RespResult.java,定义一些通用的返回结果的方法,例如返回成功结果的success方法、返回失败结果的error方法。
4、封装业务异常类BusinessException.java,继承运行时异常,业务层出现一些逻辑的错误可以抛出BusinessException异常。
5、定义通过全局异常拦截器GlobalExceptionHandler拦截各类异常,对返回结果的code和message做二次加工。

5.1 Springboot的全局异常查是通过两个注解@RestControllerAdvice和@ExceptionHandler来实现的。只有代码出错或者throw出来的异常才会被捕捉处理,如果被catch的异常,就不会被捕捉,除非catch之后再throw异常。@RestControllerAdvice:增强型控制器,对于控制器的全局配置放在同一个位置,全局异常的注解,放在类上。@RestControllerAdvice默认只会处理controller层抛出的异常,如果需要处理service层的异常,需要定义一个自定义的MyException来继承RuntimeException类,然后@ExceptionHandler(MyException.class)即可。

5.2 @ExceptionHandler:指明需要处理的异常类型以及子类。注解放在方法上面。

5.3 一般对业务方法,比如controller层返回的code通常有两种做法:
1)返回http code 200,对所有异常进行捕获,返回的message二次加工展示给调用方。
2)返回不同的http code,通过ResponseStatus对象控制不同的异常展示不同的status code。不好的地方,status code比较有限,使用起来不是很方便。GlobalExceptionHandler处理异常规则是:
.@ExceptionHandler(RuntimeException.class): 会先查看异常是否属于RuntimeException异常以及其子类,如果是的话,就用这个方法进行处理。
. 一个方法处理多个异常类的异常: @ExceptionHandler(value = {Exception.class, Throwable.class})
. 有多个@ExceptionHandler注解的方法时,会根据抛出异常类去寻找处理方法, 如果没有,就往上找父类,直到找到为止。

四、代码案例

controller层

package com.litian.dancechar.core.biz.blacklist.controller;

import com.litian.dancechar.core.biz.blacklist.conf.EnvConfig;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListAddOrEditDTO;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListReqDTO;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListRespDTO;
import com.litian.dancechar.core.biz.blacklist.service.SysBlackListService;
import com.litian.dancechar.framework.common.base.PageWrapperDTO;
import com.litian.dancechar.framework.common.base.RespResult;
import com.litian.dancechar.framework.common.validator.ValidatorUtil;
import com.litian.dancechar.framework.common.validator.groups.Update;
import com.litian.dancechar.framework.cache.redis.constants.LockConstant;
import com.litian.dancechar.framework.cache.redis.distributelock.annotation.Lock;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * 黑名单地址业务处理
 *
 * @author kyle0432
 * @date 2024/03/06 11:17
 */
@Api(tags = "黑名单相关api")
@RestController
@Slf4j
@RequestMapping(value = "/sys/blacklist/")
public class SysBlackListController {
    @Resource
    private SysBlackListService sysBlackListService;
    @Resource
    private EnvConfig envConfig;

    @ApiOperation(value = "分页查询黑名单列表", notes = "分页查询黑名单列表")
    @PostMapping("listPaged")
    public RespResult<PageWrapperDTO<SysBlackListRespDTO>> listPaged(@RequestBody SysBlackListReqDTO req) {
        return sysBlackListService.listPaged(req);
    }

    @ApiOperation(value = "查询黑名单列表", notes = "查询黑名单列表")
    @PostMapping("findList")
    public RespResult<List<SysBlackListRespDTO>> findList(@RequestBody SysBlackListReqDTO req) {
        return sysBlackListService.findList(req);
    }

    @ApiOperation(value = "新增黑名单保存", notes = "新增黑名单保存")
    @PostMapping("add")
    @Lock(keyPrefix = "mybatis/actinfo", lockFailMsg = LockConstant.REPEATED_SUBMIT, value = "#req.reqUrl")
    public RespResult<Boolean> add(@Validated @RequestBody SysBlackListAddOrEditDTO req) {
        log.info("进入新增黑名单....");
        return sysBlackListService.save(req);
    }

    @ApiOperation(value = "修改黑名单保存", notes = "修改黑名单保存")
    @PostMapping("update")
    public RespResult<Boolean> update(@RequestBody SysBlackListAddOrEditDTO req) {
        log.info("进入修改黑名单....");
        ValidatorUtil.validate(req, Update.class);
        return sysBlackListService.save(req);
    }
}

service层

package com.litian.dancechar.core.biz.blacklist.service;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.litian.dancechar.core.biz.blacklist.dao.entity.SysBlackListDO;
import com.litian.dancechar.core.biz.blacklist.dao.inf.SysBlackListDao;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListAddOrEditDTO;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListReqDTO;
import com.litian.dancechar.core.biz.blacklist.dto.SysBlackListRespDTO;
import com.litian.dancechar.core.init.ThreadPoolInit;
import com.litian.dancechar.framework.common.base.PageWrapperDTO;
import com.litian.dancechar.framework.common.base.RespResult;
import com.litian.dancechar.framework.common.util.DCBeanUtil;
import com.litian.dancechar.framework.common.util.PageResultUtil;
import com.litian.dancechar.framework.encrypt.util.EncryptUtil;
import com.litian.dancechar.framework.cache.redis.util.RedisHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 黑名单请求url服務
 *
 * @author kyle0432
 * @date 2024/03/06 13:13
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class SysBlackListService {
    @Resource
    private SysBlackListDao sysBlackListDao;
    @Resource
    private RedisHelper redisHelper;

    /**
     * 功能: 分页查询黑名单列表
     */
    public RespResult<PageWrapperDTO<SysBlackListRespDTO>> listPaged(SysBlackListReqDTO req) {
        PageHelper.startPage(req.getPageNo(), req.getPageSize());
        PageWrapperDTO<SysBlackListRespDTO> pageCommon = new PageWrapperDTO<>();
        PageResultUtil.setPageResult(EncryptUtil.handleDecryptList(sysBlackListDao.findList(req)), pageCommon);
        redisHelper.set("hello", "sgsg");
        System.out.println(redisHelper.get("hello"));
        for(int i=0; i<5;i++){
            ThreadPoolInit.getThreadPoolTaskExecutor().execute(()->{
                log.info("验证黑名单异步traceId不丢失");
            });
        }
        return RespResult.success(pageCommon);
    }

    /**
     * 功能:查询黑名单列表
     */
    public RespResult<List<SysBlackListRespDTO>> findList(SysBlackListReqDTO req) {
        return RespResult.success(sysBlackListDao.findList(req));
    }

    /**
     * 保存黑名单(新增或修改)
     *
     * @param req 黑名单对象
     * @return 保存结果
     */
    public RespResult<Boolean> save(SysBlackListAddOrEditDTO req) {
        if (StrUtil.isNotEmpty(req.getId())) {
            SysBlackListDO sysBlackListDO = sysBlackListDao.selectById(req.getId());
            if (sysBlackListDO != null) {
                DCBeanUtil.copyNotNull(sysBlackListDO, req);
                sysBlackListDao.updateById(sysBlackListDO);
            }
        } else {
            SysBlackListDO sysBlackListDO = new SysBlackListDO();
            DCBeanUtil.copyNotNull(sysBlackListDO, req);
            sysBlackListDao.insert(sysBlackListDO);
        }
        return RespResult.success(true);
    }
}

通用返回结果对象

package com.litian.dancechar.framework.common.base;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.litian.dancechar.framework.common.trace.TraceHelper;
import com.litian.dancechar.framework.common.util.SystemConfigUtil;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * 通用返回结果对象
 *
 * @author kyle0432
 * @date 2024/03/05 21:25
 */
@Data
public class RespResult<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 结果码
     */
    private Integer code = RespResultCode.OK.getCode();

    /**
     * 结果信息
     */
    private String message = RespResultCode.OK.getMessage();

    /**
     * 详细的错误消息(开发看)
     */
    private String detailMessage = RespResultCode.OK.getDetailMessage();

    /**
     * 返回结果的数据对象
     */
    private T data;

    /**
     * 分布式链路traceId
     */
    private String traceId;

    /**
     * 分布式链路spanId
     */
    private String spanId;

    /**
     * 服务部署的环境
     */
    private String env;

    public RespResult() {
    }

    public RespResult(Integer code) {
        this.code = code;
    }

    public RespResult(Integer code, String message) {
        this.code = code;
        this.message = message;
        this.traceId = TraceHelper.getCurrentTrace().getTraceId();
        this.spanId = TraceHelper.getCurrentTrace().getSpanId();
        this.env = SystemConfigUtil.getEnv();
    }

    public RespResult(Integer code, String message, String detailMessage) {
        this.code = code;
        this.message = message;
        this.detailMessage = detailMessage;
        this.traceId = TraceHelper.getCurrentTrace().getTraceId();
        this.spanId = TraceHelper.getCurrentTrace().getSpanId();
        this.env = SystemConfigUtil.getEnv();
    }

    public RespResult(Integer code, String message, String detailMessage, String traceId, String spanId, String env) {
        this.code = code;
        this.message = message;
        this.detailMessage = detailMessage;
        this.traceId = traceId;
        this.spanId = spanId;
        this.env = env;
    }

    public RespResult(IRespResultCode respResultCode) {
        this.code = respResultCode.getCode();
        this.message = respResultCode.getMessage();
        this.detailMessage = respResultCode.getDetailMessage();
        this.traceId = TraceHelper.getCurrentTrace().getTraceId();
        this.spanId = TraceHelper.getCurrentTrace().getSpanId();
        this.env = SystemConfigUtil.getEnv();
    }

    public RespResult(IRespResultCode respResultCode, String traceId, String spanId, String env) {
        this.code = respResultCode.getCode();
        this.message = respResultCode.getMessage();
        this.detailMessage = respResultCode.getDetailMessage();
        this.traceId = traceId;
        this.spanId = spanId;
        this.env = env;
    }

    @JsonIgnore
    public boolean isOk() {
        return RespResultCode.OK.getCode().equals(code);
    }

    @JsonIgnore
    public boolean isNotOk() {
        return !this.isOk();
    }

    public static <T> RespResult<T> error(IRespResultCode apiResultCode) {
        return new RespResult<T>(apiResultCode);
    }

    public static <T> RespResult<T> error(IRespResultCode apiResultCode, T data) {
        return new RespResult<T>(apiResultCode).setData(data);
    }

    public static <T> RespResult<T> error(IRespResultCode apiResultCode, Object... params) {
        return new RespResult<T>(apiResultCode.getCode(), String.format(apiResultCode.getMessage(), params));
    }

    public static <T> RespResult<T> error(IRespResultCode apiResultCode, T data, Object... params) {
        return new RespResult<T>(apiResultCode.getCode(), String.format(apiResultCode.getMessage(), params))
                .setData(data);
    }

    public static <T> RespResult<T> error(String msg) {
        return new RespResult<T>(RespResultCode.SYS_EXCEPTION.getCode(), msg, msg);
    }

    public static <T> RespResult<T> error(String msg, String detailMessage) {
        return new RespResult<T>(RespResultCode.SYS_EXCEPTION.getCode(), msg, detailMessage);
    }

    public static <T> RespResult<T> error(String msg, T data) {
        return new RespResult<T>(RespResultCode.SYS_EXCEPTION.getCode(), msg, msg).setData(data);
    }

    public static <T> RespResult<T> error(String msg, String detailMessage, T data) {
        return new RespResult<T>(RespResultCode.SYS_EXCEPTION.getCode(), msg, detailMessage).setData(data);
    }

    public static <T> RespResult<T> error(Integer code, String msg) {
        return new RespResult<T>(code, msg, msg);
    }


    public static <T> RespResult<T> error(Integer code, String msg, String detailMessage) {
        return new RespResult<T>(code, msg, detailMessage);
    }

    public static <T> RespResult<T> error(Integer code, String msg, T data) {
        return new RespResult<T>(code, msg, msg).setData(data);
    }

    public static <T> RespResult<T> error(Integer code, String msg, String detailMessage, T data) {
        return new RespResult<T>(code, msg, detailMessage).setData(data);
    }

    public static <T> RespResult<T> error(List<Object> codeAndMsgList) {
        return new RespResult<>(Integer.valueOf(codeAndMsgList.get(0).toString()),
                codeAndMsgList.get(1).toString(), codeAndMsgList.get(1).toString());
    }

    public static <T> RespResult<T> error(List<Object> codeAndMsgList, T data) {
        RespResult<T> ar = error(codeAndMsgList);
        ar.setData(data);
        return ar;
    }

    public static RespResult<Void> success() {
        return new RespResult<>(RespResultCode.OK);
    }

    public static <T> RespResult<T> success(T data) {
        RespResult<T> ar = new RespResult<T>(RespResultCode.OK);
        ar.setData(data);
        return ar;
    }

    public RespResult<T> setRespMessage(IRespResultCode respResultCode) {
        this.code = respResultCode.getCode();
        this.message = respResultCode.getMessage();
        this.detailMessage = respResultCode.getDetailMessage();
        return this;
    }

    public String getMessage() {
        return message;
    }

    public RespResult<T> setMessage(String msg) {
        this.message = msg;
        return this;
    }

    public String getDetailMessage() {
        return detailMessage;
    }

    public RespResult<T> setDetailMessage(String detailMessage) {
        this.detailMessage = detailMessage;
        return this;
    }

    public RespResult<T> setMessage(String msg, Object... params) {
        this.message = String.format(msg, params);
        return this;
    }

    public T getData() {
        return data;
    }

    public RespResult<T> setData(T data) {
        this.data = data;
        return this;
    }
}

通用返回码对象

package com.litian.dancechar.framework.common.base;

/**
 * 通用返回码对象
 *
 * @author kyle0432
 * @date 2024/03/05 21:25
 */
public enum RespResultCode implements IRespResultCode {
    /**
     * 成功
     */
    OK(0, "成功", "成功"),
    /**
     * socket超时异常
     */
    SOCKET_TIMEOUT_EXCEPTION(-2, "socket 超时异常", "socket 超时异常"),
    /**
     * io异常
     */
    IO_EXCEPTION(-3, "io 异常", "io 异常"),
    /**
     * 系统异常
     */
    SYS_EXCEPTION(-1, "服务发生了一点小故障,请稍后重试", "系统异常"),
    /**
     * 参数不合法
     */
    ERR_PARAM_NOT_LEGAL(100000, "参数不合法", "参数不合法"),
    /**
     * 请勿重复操作
     */
    REPEATED_OPERATE(100001, "请勿重复操作", "请勿重复操作"),
    /**
     * 请求太频繁,请稍后重试
     */
    REPEATED_BUSY(100002, "请求太频繁,请稍后重试", "请求繁忙,请稍后重试"),
    /**
     * 远程接口频繁异常,系统熔断
     */
    EXTERNAL_SERVICE_EXCEPTION(100003, "远程接口频繁异常,系统熔断", "远程接口频繁异常,系统熔断"),
    /**
     * 数据库有重复的记录
     */
    ERR_CONSTRAINT_VIOLATION(100004, "数据库记录重复", "数据库记录重复");

    /**
     * 错误码
     */
    private Integer code;

    /**
     * 错误消息
     */
    private String message;

    /**
     * 详细的错误消息(开发看)
     */
    private String detailMessage;

    RespResultCode(Integer code, String message, String detailMessage) {
        this.code = code;
        this.message = message;
        this.detailMessage = detailMessage;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    @Override
    public String getDetailMessage() {
        return detailMessage;
    }
}

基础的返回码对象

package com.litian.dancechar.framework.common.base;

/**
 * 基础的返回码对象
 *
 * @author kyle0432
 * @date 2024/03/06 9:25
 */
public interface IRespResultCode {
    /**
     * 结果码
     */
    Integer getCode();

    /**
     * 返回消息
     */
    String getMessage();

    /**
     * 详细的错误消息(开发看)
     */
    String getDetailMessage();
}

base模块返回码对象枚举

package com.litian.dancechar.base.enums;

import com.litian.dancechar.framework.common.base.IRespResultCode;

/**
 * base模块返回码对象枚举
 *
 * @author kyle0432
 * @date 2024/03/05 21:25
 */
public enum BaseRespResultCode implements IRespResultCode {
    ERR_SOURCE_NOT_EMPTY(200000, "渠道不能为空", "渠道不能为空");

    /**
     * 错误码
     */
    private Integer code;

    /**
     * 错误消息
     */
    private String message;

    /**
     * 详细的错误消息(开发看)
     */
    private String detailMessage;

    BaseRespResultCode(Integer code, String message, String detailMessage) {
        this.code = code;
        this.message = message;
        this.detailMessage = detailMessage;
    }

    @Override
    public Integer getCode() {
        return code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    @Override
    public String getDetailMessage() {
        return detailMessage;
    }
}

traceId和spanId工具类

package com.litian.dancechar.framework.common.trace;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.hutool.core.util.StrUtil;
import com.litian.dancechar.framework.common.util.DCMd5Util;
import org.slf4j.MDC;
import org.springframework.core.NamedThreadLocal;

import java.util.UUID;

/**
 * traceId和spanId工具类
 *
 * @author kyle0432
 * @date 2024/03/05 23:15
 */
public class TraceHelper {
    public static final ThreadLocal<Trace> CURRENT_SPAN = new NamedThreadLocal<>("TraceId Context");

    public static String genTraceId(){
        return DCMd5Util.getTraceId(UUID.randomUUID().toString());
    }

    public static String genSpanId(){
        return Convert.toStr(new SnowflakeGenerator().next());
    }

    public static String getTraceId(){
        return MDC.get(Trace.TRACE);
    }

    /**
     * 设置traceId
     */
    public static void setCurrentTrace(String traceId) {
        if (StrUtil.isBlank(traceId)) {
            traceId = genTraceId();
        }
        Trace trace = new Trace();
        trace.setTraceId(traceId);
        trace.setSpanId(genSpanId());
        MDC.put(Trace.TRACE, trace.getTraceId());
        MDC.put(Trace.PARENT_SPAN, trace.getSpanId());
        CURRENT_SPAN.set(trace);
    }

    /**
     * 获取traceId
     */
    public static Trace getCurrentTrace() {
        Trace trace = CURRENT_SPAN.get();
        if (trace == null) {
            trace = new Trace();
            trace.setTraceId(genTraceId());
            trace.setSpanId(genSpanId());
            MDC.put(Trace.TRACE, trace.getTraceId());
            MDC.put(Trace.PARENT_SPAN, trace.getSpanId());
            CURRENT_SPAN.set(trace);
        } else{
            // spanId每次不一样,重新生成
            trace.setSpanId(genSpanId());
            MDC.put(Trace.PARENT_SPAN, trace.getSpanId());
            CURRENT_SPAN.set(trace);
        }
        return trace;
    }

    /**
     * 清空traceId
     */
    public static void clearCurrentTrace() {
        CURRENT_SPAN.set(null);
        CURRENT_SPAN.remove();
    }
}

获取系统配置工具类

package com.litian.dancechar.framework.common.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.extra.spring.SpringUtil;
import com.litian.dancechar.framework.common.config.SystemEnvConfig;
import org.springframework.stereotype.Component;

/**
 * 获取系统配置工具类
 *
 * @author kyle0432
 * @date 2024/03/05 18:57
 */
@Component
public class SystemConfigUtil {
    /**
     * 获取部署环境信息
     */
    public static String getEnv() {
        if( SpringUtil.getApplicationContext() != null){
            return Convert.toStr(SpringUtil.getBean(SystemEnvConfig.class).getEnv(), "dev");
        }
        return "dev";
    }

}

定义业务异常类

package com.litian.dancechar.framework.common.exception;

/**
 * 业务异常类
 *
 * @author kyle0432
 * @date 2024/03/05 21:15
 */
public class BusinessException extends RuntimeException {
	private static final long serialVersionUID = 1L;

	public BusinessException(String msg) {
        super(msg);
    }

    public BusinessException(Throwable cause) {
        super(cause);
    }

    public BusinessException(String message, Throwable cause) {
        super(message,cause);
    }

    public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writeableStackTrace) {
        super(message,cause, enableSuppression, writeableStackTrace);
    }

}

全局异常类

package com.litian.dancechar.framework.common.exception;

import com.litian.dancechar.framework.common.base.RespResult;
import com.litian.dancechar.framework.common.base.RespResultCode;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * 全局异常类
 *
 * @author kyle
 * @date 2024/03/06 14:15
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public RespResult<Void> handleError(MethodArgumentTypeMismatchException e) {
        log.error("Method Argument Type Mismatch:{}", e.getMessage(), e);
        return RespResult.error("Method Argument Type Mismatch");
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public RespResult<Void> handleError(MissingServletRequestParameterException e) {
        log.error("Method Request Parameter :{}", e.getMessage(), e);
        return RespResult.error("Method Request Parameter");
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RespResult<Void> handleError(MethodArgumentNotValidException e) {
        log.error("Method Request Not Valid :{}", e.getMessage(), e);
        BindingResult bindingResult = e.getBindingResult();
        FieldError fieldError = bindingResult.getFieldError();
        String message = String.format("%s:%s", fieldError.getField(), fieldError.getDefaultMessage());
        return RespResult.error(RespResultCode.ERR_PARAM_NOT_LEGAL.getCode(),
                RespResultCode.ERR_PARAM_NOT_LEGAL.getMessage(),
                message);
    }

    @ExceptionHandler(BindException.class)
    public RespResult<Void> handleError(BindException e) {
        log.error("Bind Exception :{}", e.getMessage(), e);
        FieldError fieldError = e.getFieldError();
        String message = String.format("%s:%s", fieldError.getField(), fieldError.getDefaultMessage());
        return RespResult.error(RespResultCode.ERR_PARAM_NOT_LEGAL.getCode(), message);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public RespResult<Void> handleError(ConstraintViolationException e) {
        log.error("Constraint Exception :{}", e.getMessage(), e);
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        ConstraintViolation<?> violation = violations.iterator().next();
        String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName();
        String message = String.format("%s:%s", path, violation.getMessage());
        return RespResult.error(RespResultCode.ERR_CONSTRAINT_VIOLATION.getCode(), message);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public RespResult<Void> handleError(HttpMessageNotReadableException e) {
        log.error("Http Message Not Readable Exception :{}", e.getMessage(), e);
        return RespResult.error("请求的参数类型与方法接收的参数类型不匹配, 请检查!");
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public RespResult<Void> handleError(HttpRequestMethodNotSupportedException e) {
        log.error("Http Request Method Not Support Exception :{}", e.getMessage(), e);
        String message = String.format("%s方法类型不支持,请检查!", e.getMethod());
        return RespResult.error(message);
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public RespResult<Void> handleError(HttpMediaTypeNotSupportedException e) {
        log.error("Http Media Type Not Support Exception :{}", e.getMessage(), e);
        String message = String.format("不支持%s content-type,请检查!", e.getContentType());
        return RespResult.error(message);
    }

    @ExceptionHandler(ParamException.class)
    public RespResult<Void> handleError(ParamException e) {
        log.error("参数不合法 :{}", e.getMessage(), e);
        return RespResult.error(RespResultCode.ERR_PARAM_NOT_LEGAL.getCode(),
                RespResultCode.ERR_PARAM_NOT_LEGAL.getMessage(), e.getMessage());
    }

    @ExceptionHandler(DistributeLockException.class)
    public RespResult<Void> handleError(DistributeLockException e) {
        log.error("分布式锁Distribute Lock Exception :{}", e.getMessage(), e);
        return RespResult.error(RespResultCode.REPEATED_OPERATE.getCode(),
                RespResultCode.REPEATED_OPERATE.getMessage(), e.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public RespResult<Void> handleError(BusinessException e) {
        log.error("业务出现异常 :{}", e.getMessage(), e);
        return RespResult.error(RespResultCode.SYS_EXCEPTION.getCode(),
                RespResultCode.SYS_EXCEPTION.getMessage(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    //@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR, reason = "系统内部错误")
    public RespResult<Void> handleError(Exception e) {
        log.error("全局异常信息,异常堆栈信息 :{}", e.getMessage(), e);
        return RespResult.error(RespResultCode.SYS_EXCEPTION.getCode(),
                RespResultCode.SYS_EXCEPTION.getMessage(), e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public RespResult<Void> handleError(Throwable e) {
        log.error("Throwable Server Exception :{}", e.getMessage(), e);
        return RespResult.error(RespResultCode.SYS_EXCEPTION.getCode(),
                RespResultCode.SYS_EXCEPTION.getMessage(), e.getMessage());
    }
}

五、结果演示

成功响应结果集

失败响应结果集 

 tranceId的记录,方便根据tranceId追踪日志

当前环境配置 

  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值