Spring Boot随手记-统一封装response的格式

4,436

1. 概述

在项目中,将response返回信息的格式进行统一封装,不仅有利于与前端统一处理接口的返回,而且具备良好的可读性。通常情况下项目中采用JSON(JavaScript Object Notation)序列化数据再进行传输,统一格式的response也就包含三部分信息:

  1. 状态码:定义了成功、失败的标志,还可以包含一些内部定义的状态码,如对应用户名不存在时应该返回的状态码。注意此状态码与HTTP状态码无关。
  2. 提示信息:以一段字符串补充说明状态码的具体信息。如果允许,前端还可以直接将该字段信息反馈给用户。
  3. 携带信息:这部分是response中的关键,包含了用户正在希望请求的信息。特别的是,如果请求失败时,该部分通常为null或被隐藏。

2. 统一返回状态码及对应提示信息

使用一个枚举类型定义状态码及其对应的提示信息,方便扩展。

/**
 * API 统一返回状态码
 */
public enum ResultCode {
    /* 成功状态码 */
    SUCCESS(0, "Request is successful"),
    FAIL(1, "Request is failed"),
    TOKEN_INVALID(40001, "Token is null or invalid"),
    ACCESS_DENIED(40003, "Access denied"),
    FAIL4DELETE(50001, "Delete failed"),
    FAIL4UPDATE(50002, "Update failed");

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

    public Integer code(){
        return this.code;
    }

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

3. 统一封装response

使用一个RestResponse类封装reponse信息,其包含三个成员变量:codemessagedata,以及在不同情况下调用的构造方法。

package me.ifight.model.common;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel(description = "返回结果")
public class RestResponse {
    @ApiModelProperty("状态码 0:成功")
    private int code;
    @ApiModelProperty("消息")
    private String message;
    @ApiModelProperty("返回数据")
    private Object data;

    public RestResponse(){

    }

    public static RestResponse succuess(){
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultCode.SUCCESS);

        return restResponse;
    }

    public static RestResponse succuess(Object data){
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultCode.SUCCESS);
        restResponse.setData(data);

        return restResponse;
    }

    public static RestResponse fail() {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(ResultCode.FAIL);

        return restResponse;
    }


    public static RestResponse fail(ResultCode resultCode) {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(resultCode);

        return restResponse;
    }

    public static RestResponse fail(String message) {
        RestResponse restResponse = new RestResponse();
        restResponse.setCode(ResultCode.FAIL.code());
        restResponse.setMessage(message);

        return restResponse;
    }

    public static RestResponse fail(Integer code, String message) {
        RestResponse restResponse = new RestResponse();
        restResponse.setCode(code);
        restResponse.setMessage(message);

        return restResponse;
    }

    public static RestResponse fail(ResultCode resultCode, Object data) {
        RestResponse restResponse = new RestResponse();
        restResponse.setResultCode(resultCode);
        restResponse.setData(data);

        return restResponse;
    }

    private void setResultCode(ResultCode resultCode){
        this.code = resultCode.code();
        this.message = resultCode.message();
    }

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

    public Object getData(){
        return data;
    }

    public int getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

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

4. 应用场景

下面是一个简单的查询用户信息的接口:

    @GetMapping("/queryUserById")
    @ApiOperation("根据ID查找用户信息")
    @ApiImplicitParam(name = "id", value = "用户主键id", required = true, dataType = "int")
    public RestResponse queryUserById(int id){
        logger.info("#queryUserId, id:" + id);

        UserVO userVO = userService.queryUserById(id);

        if(userVO != null){
            return RestResponse.succuess(userVO);
        }else{
            return RestResponse.fail("Not Found the ID");
        }
    }

如果查询成功将会返回如下信息:

{
	"code":0,
	"message":"Request is successful",
	"data":{
		"username":"admin",
		"age":"20"
	}
}

查询失败

{
	"code":1,
	"message":"Request is failed",
	"data":null
}

有不合理之处,请留言指正,谢谢

更新1

业务定义的状态码最好不要与HTTP状态码相同,因此修改了ResultCode枚举类的错误码 -- 2019-01-17