rest-spring-boot-starter

rest-spring-boot-starter

基于spring boot,统一业务异常处理,统一返回格式包装

依赖

<dependency>
    <groupId>tk.fishfish</groupId>
    <artifactId>rest-spring-boot-starter</artifactId>
    <version>1.0.0.RELEASE</version>
</dependency>

统一业务异常处理

@RestController
public class DemoController {

    @GetMapping("/list")
    public List<String> list() {
        throw new BizException(10001, "xxx错误");
    }

}

业务异常统一处理:

{
    "code": 10001,
    "msg": "xxx错误",
    "data": null
}

统一返回格式包装

@RestController
public class DemoController {

    @GetMapping("/list")
    public List<String> list() {
        return Arrays.asList("1", "2");
    }

}

返回值进行包装,忽略org.springframework.http.ResponseEntity值类型。

{
    "code": 0,
    "msg": null,
    "data": [
        "1",
        "2"
    ]
}

原理

定义统一格式:

{
    "code": 返回码,
    "msg": 描述,
    "data": 数据
}

约定:

  • code:-1,代表全局异常处理的错误;0,成功;正数,业务错误码
  • msg:一段描述
  • data:真正的数据

异常处理

使用org.springframework.web.bind.annotation.RestControllerAdvice,全局捕获异常。

package tk.fishfish.rest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理,优先级为100
 *
 * @author 奔波儿灞
 * @since 1.0
 */
@Order(100)
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(BizException.class)
    public ApiResult<Void> handleBizException(BizException e) {
        LOG.warn("handle bizException", e);
        Integer code = e.getCode();
        String msg = e.getMessage();
        return ApiResult.fail(code, msg);
    }

    @ExceptionHandler(Exception.class)
    public ApiResult<Void> handleException(Exception e) {
        LOG.warn("handle exception", e);
        String msg = e.getMessage();
        return ApiResult.fail(-1, msg);
    }

}

统一返回

通过实现org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice,在写入响应前统一包装返回内容。

package tk.fishfish.rest;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 返回body处理,包装成ApiResult。如果是ResponseEntity,则不包装
 *
 * @author 奔波儿灞
 * @see tk.fishfish.rest.ApiResult
 * @since 1.0
 */
@RestControllerAdvice(annotations = RestController.class)
public class ApiResultResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter,
                                  MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // ResponseEntity,则不包装
        if (body instanceof ResponseEntity) {
            return body;
        }
        // ApiResult,也不包装
        if (body instanceof ApiResult) {
            return body;
        }
        // todo 基本数据类型是否特殊处理
        // 其余统一包装成ApiResult
        return ApiResult.ok(body);
    }

}

项目地址

posted @ 2019-11-05 21:11  bener  阅读(497)  评论(0编辑  收藏  举报