springboot restful统一响应请求格式

###restful接口统一返回值
使用JsonResult返回请求接口,使用泛型填充返回数据结构。code代表返回值,既可以设置为Integer,也可以设置为String,取决于项目需要。
通常,系统复杂可以使用String类型,标识出错的模块名称以及错误类型。系统简单直接使用Integer标识错误码即可。此处,封装两个函数,success和error。

//JsonResult作为返回值
public class JsonResult<T> {
    private Integer code;
    private String message;
    private T data;

    public JsonResult(T data) {
        this.code = RtnCodeMsg.SUCCESS.getCode();
        this.message = RtnCodeMsg.SUCCESS.getMessage();
        this.data = data;
    }

    public JsonResult(RtnCodeMsg rtnCodeMsg) {
        this.code = rtnCodeMsg.getCode();
        this.message = rtnCodeMsg.getMessage();
    }

    public Integer getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

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

    public static <T> JsonResult<T> success(T data) {
        return new JsonResult<T>(data);
    }

    public static <T> JsonResult<T> error(RtnCodeMsg msg) {
        return new JsonResult<T>(msg);
    }
}

//返回值封装,定义常用错误码
public class RtnCodeMsg {
    private Integer code;
    private String message;

    public RtnCodeMsg(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public RtnCodeMsg(BusinessRuntimeException businessRuntimeException) {
        this.code = businessRuntimeException.getCode();
        this.message = businessRuntimeException.getMessage();
    }

    public Integer getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public RtnCodeMsg fillArgs(Object...args) {
        Integer code = this.code;
        String message = String.format(this.message, args);
        return new RtnCodeMsg(code, message);
    }

    //通用错误码
    public static RtnCodeMsg SUCCESS = new RtnCodeMsg(200, "请求成功");
    public static RtnCodeMsg BAD_REQUEST = new RtnCodeMsg(400, "%s");
    public static RtnCodeMsg NO_PERMITS = new RtnCodeMsg(401, "%s");
    public static RtnCodeMsg INTERNAL_ERROR = new RtnCodeMsg(500, "%s");

    //OSS错误码40XXX
    public static RtnCodeMsg NOT_EXIST = new RtnCodeMsg(404, "%s");
}

//业务代码中,使用封装后的异常
public class BusinessRuntimeException extends RuntimeException {
    private Integer code;

    public BusinessRuntimeException() {
        super();
    }

    public BusinessRuntimeException(RtnCodeMsg rtnCodeMsg) {
        super(rtnCodeMsg.getMessage());
        code = rtnCodeMsg.getCode();
    }

    public Integer getCode() {
        return code;
    }

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

    @Override
    public String getMessage() {
        return super.getMessage();
    }
}

###restful接口数据封装
请求完成,无论成功与否,可以采用以下方式封装结果。请求返回controlller时,引入ResponseBodyAdvice,进行相应的处理。
同样此处增加全局异常的捕获,对异常结果也进行封装。其中ResponseBodyAdvice用于结果处理。beforeBodyWrite 函数中,如果o是JsonResult,直接返回即可,
否则,则表示处理成功,对结果进行封装即可

@ControllerAdvice(basePackages = "com.hero.test.controller")
@ResponseBody
public class JsonResultResponseBodyAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (o instanceof JsonResult) {
            return o;
        }

        JsonResult jsonResult = JsonResult.success(o);
        if (o instanceof String) {
            return JSON.toJSONString(jsonResult);
        } else {
            return jsonResult;
        }
    }

    @ExceptionHandler(value = Exception.class)
    public JsonResult exceptionHandler(HttpServletRequest request, Exception ex) {

        if (ex instanceof BindException) {
            BindException bindException = (BindException) ex;
            List<ObjectError> errors = bindException.getAllErrors();
            ObjectError error = errors.get(0);
            String errorMsg = error.getDefaultMessage();
            return JsonResult.error(RtnCodeMsg.BAD_REQUEST.fillArgs(errorMsg));
        }

        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) ex;
            String errorMsg = methodArgumentNotValidException.getBindingResult().getAllErrors().get(0).getDefaultMessage();
            return JsonResult.error(RtnCodeMsg.BAD_REQUEST.fillArgs(errorMsg));
        }

        if (ex instanceof BusinessRuntimeException) {
            BusinessRuntimeException businessRuntimeException = (BusinessRuntimeException) ex;
            return JsonResult.error(new RtnCodeMsg(businessRuntimeException));
        }

        return JsonResult.error(INTERNAL_ERROR.fillArgs(ex.getMessage()));
    }
}

注意点:
(1)对于返回String类型结果的,要特殊处理,否则系统会报错,提示Cast失败,在源码分析时再做讨论.
(2)对于ControllerAdvice,可以指定对哪些包进行结果的封装,通常指定自身代码所在包。如果不指定,
例如使用Swagger,会导致Swagger查询失败,因为我们对其返回的结果也进行了封装,不符合原有预期。

猜你喜欢

转载自blog.csdn.net/zhaoyaxiong_ctu/article/details/112007472