Spring Boot 统一返回格式与统一异常处理

        需求背景:这一天,前端 阿签 兴高采烈地来到公司,打卡后来到工位,打开电脑准备工作。昨天后端小伙伴刚提交了新的功能接口,又是联调接口的一天。原本兴致很高的 阿签 调着调着心里有点毛躁起来,这TM接口返回格式怎么和之前的接口又不一样,抛出异常时也是各种各样的。无疑增加 签哥 我的工作量吗?

为解决这一问题,对接口返回格式、异常进行了统一处理。

一、接口返回格式统一

(1)新建状态枚举类

        定义状态枚举类 StatusCodeEnum 。便于后续使用

package com.hy.globalexception.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/***
 * <p>
 * 统一返回值状态码
 * </p>
 * @author hou yi
 * @date 2021/7/24 19:13
 **/
@Getter
@AllArgsConstructor
public enum StatusCodeEnum {
    /**
     * 描述
     */
    PARAMETER_ERROR(102, "参数错误"),
    SUCCESS(200, "请求成功"),
    GLOBAL_EXCEPTION(301, "统一异常处理"),
    FAIL(500, "请求失败"),
    ;

    /**
     * 状态码
     */
    private final Integer code;

    /**
     * 状态描述
     */
    private final String type;
}

(2)新建 接口、异常返回格式公用封装类

        定义 ResultWrapper 返回格式公用封装类。 注:这里定义成泛型类。

package com.hy.globalexception.config;

import com.hy.globalexception.enums.StatusCodeEnum;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;

/***
 * <p>
 * 接口、异常返回格式封装类
 * </p>
 * @author hou yi
 * @date 2021/9/30 14:58
 **/
@Data
@Accessors(chain = true)
public class ResultWrapper<T> implements Serializable {

    /**
     * 状态码
     */
    private Integer code;

    /**
     * 提示语
     */
    private String msg;

    /**
     * 数据
     * */
    private T data;

    /***
     * 请求成功。无返回数据值
     * @return 、
     */
    public static <T> ResultWrapper<T> successBuilder(T t){
        return new ResultWrapper<T>()
                .setCode(StatusCodeEnum.SUCCESS.getCode())
                .setMsg(StatusCodeEnum.SUCCESS.getMsg())
                .setData(t);
    }

    /***
     * 请求失败。无返回数据值
     * @return 、
     */
    public static <T>  ResultWrapper<T> failBuilder(T t){
        return new ResultWrapper<T>()
                .setCode(StatusCodeEnum.FAIL.getCode())
                .setMsg(StatusCodeEnum.FAIL.getMsg())
                .setData(t);
    }


}

 (3)看一下效果

        1)新建一个controller进行测试

package com.hy.globalexception.controller;

import com.hy.globalexception.config.ResultWrapper;
import com.hy.globalexception.service.ExceptionTestService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/***
 * <p>
 *  统一返回值格式 测试 控制器
 * </p>
 * @author hou yi
 * @date 2021/9/30 14:29
 **/
@RestController
@RequestMapping("resultTest")
public class ResultTestController {

    @GetMapping
    public ResultWrapper<Object> find() {
        // 注:实际开发中业务不在这里写,这里主要是方便测试
        Map<String, Object> map = new HashMap<>();
        map.put("name", "百里守约");
        map.put("level", "T0");
        map.put("property", "射手");

        return ResultWrapper.successBuilder(map);
    }

}

运行项目,启动完成后,使用 postman 工具看一下效果。效果如下:

 

二、统一异常处理

注:这里使用到上述 接口返回格式统一 中的两个工具类。

 (1)新建控制层全局异常处理类

        新建控制层全局异常处理类 GlobalExceptionHandle 。

package com.hy.globalexception.config;

import com.hy.globalexception.enums.StatusCodeEnum;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/***
 * <p>
 *  控制层全局异常处理
 * </p>
 * @author hou yi
 * @date 2021/9/30 15:23
 **/
@RestControllerAdvice
@SuppressWarnings("all")
public class GlobalExceptionHandle {

    @ExceptionHandler(RuntimeException.class)
    public ResultWrapper<Object> customException(RuntimeException e) {
        return new ResultWrapper()
                .setCode(StatusCodeEnum.GLOBAL_EXCEPTION.getCode())
                .setMsg(e.getMessage());
    }

}

 (2)新建参数校验异常统一异常类

        新建参数校验异常统一异常类 ValidateHandler 。

package com.hy.globalexception.config;

import com.hy.globalexception.enums.StatusCodeEnum;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/***
 * <p>
 * 参数校验异常统一处理
 * </p>
 * @author hou yi
 * @date 2021/9/30 15:23
 **/
@ControllerAdvice
@SuppressWarnings("all")
public class ValidateHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                                  HttpHeaders headers,
                                                                  HttpStatus status,
                                                                  WebRequest request) {
        final StringBuilder builder = new StringBuilder();
        for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
            final String message = fieldError.getDefaultMessage();
            builder.append(message);
            break;
        }
        return ResponseEntity.ok(new ResultWrapper()
                .setCode(StatusCodeEnum.PARAMETER_ERROR.getCode())
                .setMsg(builder.toString()));
    }
}

 (3)自定义 异常类

        新建 自定义异常类 CustomException 。

package com.hy.globalexception.config;

/***
 * <p>
 *  自定义异常
 * </p>
 * @author hou yi
 * @date 2021/9/30 15:23
 **/
public class CustomException extends RuntimeException{

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

}

以上三种异常类创建完成后,创建一个 controller 来看看具体效果。注:有service 层及其他的工具类,具体可参考源码。

package com.hy.globalexception.controller;

import com.hy.globalexception.config.ResultWrapper;
import com.hy.globalexception.service.ExceptionTestService;
import com.hy.globalexception.vo.ParamVo;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;

/***
 * <p>
 *  异常测试 控制器
 * </p>
 * @author hou yi
 * @date 2021/9/30 14:29
 **/
@RestController
@RequestMapping("exceptionTest")
public class ExceptionTestController {

    @Resource
    private ExceptionTestService exceptionTestService;

    @GetMapping
    public ResultWrapper<Object> find() {
        // 这里定义产生一个异常,让全局异常去捕获
        int i = 1/0;
        return ResultWrapper.successBuilder(null);
    }

    @PostMapping
    public ResultWrapper<Object> save() {
        // 异常定义在业务层。
        exceptionTestService.save();
        return ResultWrapper.successBuilder(null);
    }

    @PostMapping("custom")
    public ResultWrapper<Object> custom() {
        // 业务层 抛出一个 自定义异常
        exceptionTestService.custom();
        return ResultWrapper.successBuilder(null);
    }

    @PostMapping("validate")
    public ResultWrapper<Object> custom(@RequestBody @Valid ParamVo paramVo) {
        // ParamVo 中参数校验失败,抛出异常, 由 ValidateHandler 处理
        return ResultWrapper.successBuilder(null);
    }

}

效果图如下:

 

 

 以上就是整个 统一返回格式与统一异常处理 的过程,从此以后,阿签不在为接口感到心情烦躁,每一天都是美好的。

附源码地址:

GitHub - MEETYUKEE/global-exception: 统一接口返回格式、统一异常处理 demoicon-default.png?t=L892https://github.com/MEETYUKEE/global-exception.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值