天天看點

API接口開發(一):接口開發傳回結果解決方案

摘要

采用前後端分離的方式進行項目開發,那麼前後端互動比較好的方式是采用HTTP+JSON。如何接口傳回結果更加簡潔,更加優雅,也更加合理,并且讓前端開發人員看得明白,後端開發者也并不會是以而增加工作量呢?

正文開始

Hello,各位,好久不見了。一直在籌劃個人網站2020版本改版的事情,是以,本篇文章,也是2019年最後一篇了,當然,也得花一些心思,争取把我想要說的話,都一一說出來,說明白,說透徹。

為此,我寫了一套關于API接口開發傳回結果解決方案,

api-result

,已将其開源,并上傳到

中央倉庫

,歡迎各位批評和指正。

API講解

實體類

提供了滿足各場景使用的實體類,如下:

ResultModel

這個類是基礎實體類,有如下屬性:

success:傳回結果辨別,是一個布爾值,true / false(成功 / 失敗)

message:描述資訊,錯誤時,可以在這裡填寫錯誤的詳細資訊

data:資料,是一個泛型,可以是數組或者對象等等,成功并且需要傳回資料時,才有該參數

ApiResultModel

結構關系如下:

ResultModel
 └── ApiResultModel           

在這個類裡面增加了

code

屬性,也是一個泛型,你可以自定義你的傳回碼類型,可以是整數,或者字元串。

PageResultModel
ResultModel
 └── PageResultModel           

這個類主要主要分頁傳回結果,是以,增加了以下屬性:

total:資料總條數,Long型

size:每頁條數,整數

pages:總頁數,Long型

current:目前頁,Long型

Helper工具類

幫助我們操作實體類,具體有哪些helper呢?如下:

ResultHelper

ResultHelper是與ResultModel對應的

success(String message)

成功,攜帶描述資訊

success(String message, T data)

成功,攜帶描述資訊和資料

error(String message)

錯誤,攜帶詳細的描述資訊

ApiResultHelper

ApiResultHelper是與ApiResultModel對應的

success(S code, String message)

成功,攜帶傳回碼和描述資訊

success(S code, String message, T data)

成功,攜帶傳回碼、描述資訊和資料

error(S code, String message)

錯誤,攜帶錯誤碼和較長的描述資訊

PageResultHelper

PageResultHelper是與PageResultModel對應的

success(String message, T data, long total, int size, long pages, long current)

成功,攜帶描述資訊、資料、總數、每頁條數、總頁數、目前頁

快速入門

我們為你提供了三個實體類,以滿足不同場景,ResultModel适用于通常傳回結果,ApiResultModel适用于接口開發傳回結果,PageResultModel适用于分頁傳回結果。也分别為這三個實體類提供了各自的Helper,是以,你可以直接使用這些Helper進行傳回。當然,我推薦的使用方式是,先為各Helper編寫工具類,再通過工具類進行傳回,這樣可能更加合理定制自己的傳回工具類。

利用Helper進行傳回

首先我們來看一個簡單的示例代碼:

/**
 * 添加方法示例
 * @return {@link ResultModel}
 */
@ApiOperation(value = "添加方法示例")
@PostMapping
public ResultModel<?> add() {
  return ResultHelper.success("添加成功");
}           

傳回結果:

{
  "success": true,
  "message": "添加成功"
}           

注:這隻是一個接口傳回示例,而不是說添加接口應該這樣寫。

編寫傳回結果工具類

比如,我們可以寫一個ResultUtils工具類來操作ResultHelper。如下示例:

/**
 * 成功示例
 * @return {@link ResultModel}
 */
public static ResultModel <?> success() {
    return ResultHelper.success("Success");
}           

使用傳回結果工具類

我門就可以調用ResultUtils類裡面的方法,如下示例:

/**
* 成功示例
* @return {@link ResultModel}
*/
@ApiOperation(value = "成功示例")
@DeleteMapping
public ResultModel<?> success() {
   return ResultUtils.success();
}           

印象結果:

{
 "success": true,
 "message": "Success"
}           

使用示例

示例圖

測試接口預覽

Models

傳回成功結果示例

/**
 * 删除方法示例
 * @return {@link ResultModel}
 */
@ApiOperation(value = "删除方法示例")
@DeleteMapping
public ResultModel<?> delete() {
    return ResultUtils.success();
}           

響應結果:

{
  "success": true,
  "message": "Success"
}           

傳回失敗結果示例

如果操作出錯了,我們怎麼傳回呢?我們來看一下:

/**
 * 修改方法示例
 * @return {@link ResultModel}
 */
@ApiOperation(value = "修改方法示例")
@PutMapping
public ResultModel<?> update() {
    return ResultUtils.error("修改失敗");
}           
{
  "success": false,
  "message": "修改失敗"
}           

傳回查詢結果示例

值得一提的話,就是查詢方法了,我們看一下吧

/**
 * 查詢方法示例
 * @return {@link ResultModel}
 */
@ApiOperation(value = "查詢方法示例")
@GetMapping
public ResultModel<?> get() {
    List<Map<String, String>> list = new ArrayList<>();
    Map<String, String> map1 = new HashMap<>();

    map1.put("name", "張飛");
    map1.put("desc", "燕人張飛");
    list.add(map1);

    Map<String, String> map2 = new HashMap<>();
    map2.put("name", "趙雲");
    map2.put("desc", "常山趙子龍");
    list.add(map2);

    Map<String, String> map3 = new HashMap<>();
    map3.put("name", "關羽");
    map3.put("desc", "溫酒斬華雄");
    list.add(map3);

    return ResultUtils.success(list);
}           

看一下響應結果吧,是否如你所願:

{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "張飛",
      "desc": "燕人張飛"
    },
    {
      "name": "趙雲",
      "desc": "常山趙子龍"
    },
    {
      "name": "關羽",
      "desc": "溫酒斬華雄"
    }
  ]
}           

接口傳回資料示例

/**
* 接口傳回資料示例
* @return {@link ApiResultModel}
*/
@ApiOperation(value = "接口傳回資料示例")
@GetMapping("/api-data")
public ApiResultModel<Integer, ?> apiData() {
   return ApiResultUtils.success(getData());
}           
{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "張飛",
      "desc": "燕人張飛"
    },
    {
      "name": "趙雲",
      "desc": "常山趙子龍"
    },
    {
      "name": "關羽",
      "desc": "溫酒斬華雄"
    }
  ],
  "code": 0
}           

接口傳回失敗結果示例

/**
 * API接口錯誤傳回示例
 * @return {@link ApiResultModel}
 */
@ApiOperation(value = "API接口錯誤傳回示例")
@GetMapping("/api-error")
public ApiResultModel<Integer, ?> apiError() {
    return ApiResultUtils.error(1101, "API接口錯誤傳回示例");
}           
{
  "success": false,
  "message": "API接口錯誤傳回示例",
  "code": 1101
}           

分頁傳回資料示例

/**
 * 分頁傳回資料示例
 * @return {@link ApiResultModel}
 */
@ApiOperation(value = "分頁傳回資料示例")
@GetMapping("/page")
public PageResultModel<?> page() {
    return PageResultUtils.success(getData(), 100, 10, 10, 1);
}           
{
  "success": true,
  "message": "Success",
  "data": [
    {
      "name": "張飛",
      "desc": "燕人張飛"
    },
    {
      "name": "趙雲",
      "desc": "常山趙子龍"
    },
    {
      "name": "關羽",
      "desc": "溫酒斬華雄"
    }
  ],
  "total": 100,
  "size": 10,
  "pages": 10,
  "current": 1
}           

工具類示例

傳回結果工具類

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.ResultHelper;
import com.fengwenyi.api_result.model.ResultModel;

/**
 * 傳回結果封裝工具類
 * @author Erwin Feng[[email protected]]
 * @since 2019/11/30 13:54
 */
public class ResultUtils {

    /**
     *  成功
     * @return {@link ResultModel}
     */
    public static ResultModel <?> success() {
        return ResultHelper.success("Success");
    }

    /**
     *  成功,攜帶資料
     * @param data 資料
     * @param <T>  資料的類型
     * @return {@link ResultModel}
     */
    public static <T> ResultModel <T> success(T data) {
        return ResultHelper.success("Success", data);
    }

    /**
     *  錯誤,攜帶詳細的錯誤描述資訊
     * @param message 詳細的錯誤描述資訊
     * @return {@link ResultModel}
     */
    public static ResultModel <?> error(String message) {
        return ResultHelper.error(message);
    }

}           

API接口傳回結果工具類

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.ApiResultHelper;
import com.fengwenyi.api_result.model.ApiResultModel;

/**
 * API接口傳回結果工具類
 * @author Erwin Feng[[email protected]]
 * @since 2019/12/1 20:10
 */
public class ApiResultUtils {

    /**
     * 成功,攜帶傳回碼和描述資訊
     * @return {@link ApiResultModel}
     */
    public static ApiResultModel<Integer, ?> success() {
        return ApiResultHelper.success(0, "Success");
    }

    /**
     * 成功,攜帶傳回碼、描述資訊和資料
     * @param data 資料
     * @param <T>  資料的類型
     * @return {@link ApiResultModel}
     */
    public static <T> ApiResultModel<Integer, T> success(T data) {
        return ApiResultHelper.success(0, "Success", data);
    }

    /**
     * 出錯,攜帶錯誤嗎和較長的描述資訊
     * @param code 傳回碼
     * @param message 相信描述資訊
     * @return {@link ApiResultModel}
     */
    public static ApiResultModel<Integer, ?> error(int code, String message) {
        return ApiResultHelper.error(code, message);
    }
}           

分頁傳回結果工具類

package com.fengwenyi.api_example.util;

import com.fengwenyi.api_result.helper.PageResultHelper;
import com.fengwenyi.api_result.model.PageResultModel;

/**
 * 分頁傳回結果工具類
 * @author Erwin Feng[[email protected]]
 * @since 2019/12/1 20:32
 */
public class PageResultUtils {

    /**
     * 成功,攜帶分頁相關資料以及資訊
     * @param data     資料
     * @param total    資料總條數
     * @param size     每頁條數
     * @param pages    總頁數
     * @param current  目前頁
     * @param <T>      資料類型
     * @return {@link PageResultModel}
     */
    public static <T> PageResultModel<T> success(T data, long total, int size, long pages, long current) {
        return PageResultHelper.success("Success", data, total, size, pages, current);
    }

}           

解析傳回結果示例

這裡補充一下,關于如何解析傳回的json字元串,談談我的看法吧。傳回的是一個json格式的字元串,這裡我用fastjson來寫解析示例。我們通常會将請求資料封裝為一個通用方法或者工具類,隻需要傳回資料,當然,如果失敗,或者出現異常,都在這裡處理。

常用傳回結果解析示例

/**
 * 解析常用傳回結果示例
 * @return 資料
 */
public Object parseResult() {
    String result = "";
    ResultModel<?> resultModel = JSON.parseObject(result, ResultModel.class);
    Boolean success = resultModel.getSuccess();
    if (success != null && success) {
        return resultModel.getData();
    } else {
        // 異常資訊
        String message = resultModel.getMessage();
        // 異常處理
        throw new DataParseException(message);
    }
}           

接口傳回結果解析示例

/**
 * 解析接口傳回結果示例
 * @return 資料
 */
public Object parseApiResult() {
    String apiResult = "";
    ApiResultModel<?, ?> apiResultModel = JSON.parseObject(apiResult, ApiResultModel.class);
    Boolean success = apiResultModel.getSuccess();
    if (success != null && success) {
        return apiResultModel.getData();
    } else {
        Object code = apiResultModel.getCode();
        String message = apiResultModel.getMessage();
        // 根據接口錯誤碼分别進行處理
        // ...
        return null;
    }
}           

分頁傳回結果解析示例

這裡與上面略有不同,因為,增加了一些字段,是以,我們可以借助bean來傳回。

/**
 * 解析分頁傳回結果示例
 * @return {@link PageResultDataBean}
 */
public PageResultDataBean parsePageResult() {
    String pageResult = "";
    PageResultModel<List<?>> pageResultModel = JSON.parseObject(pageResult, PageResultModel.class);
    Boolean success = pageResultModel.getSuccess();
    if (success != null && success) {
        List<?> data = pageResultModel.getData();
        Long total = pageResultModel.getTotal();
        Integer size = pageResultModel.getSize();
        Long pages = pageResultModel.getPages();
        Long current = pageResultModel.getCurrent();
        return new PageResultDataBean()
                .setTotal(total)
                .setSize(size)
                .setPages(pages)
                .setCurrent(current)
                .setData(data);
    } else {
        // 異常資訊
        String message = pageResultModel.getMessage();
        // 異常處理
        throw new DataParseException(message);
    }
}           

以上,這一切都是否如你所願呢?歡迎評論留言告訴我。

連結

[1]

api-result源碼 | github

[2]

api-result源碼 | 碼雲

[3]

api-result中央倉庫

[4]

測試示例代碼