API接口开发(一):接口开发返回结果解决方案

简介: 采用前后端分离的方式进行项目开发,那么前后端交互比较好的方式是采用HTTP+JSON。如何接口返回结果更加简洁,更加优雅,也更加合理,并且让前端开发人员看得明白,后端开发者也并不会因此而增加工作量呢?

摘要

采用前后端分离的方式进行项目开发,那么前后端交互比较好的方式是采用HTTP+JSON。如何接口返回结果更加简洁,更加优雅,也更加合理,并且让前端开发人员看得明白,后端开发者也并不会因此而增加工作量呢?

正文开始

Hello,各位,好久不见了。一直在筹划个人网站2020版本改版的事情,所以,本篇文章,也是2019年最后一篇了,当然,也得花一些心思,争取把我想要说的话,都一一说出来,说明白,说透彻。

采用前后端分离的方式进行项目开发,那么前后端交互比较好的方式是采用HTTP+JSON。如何接口返回结果更加简洁,更加优雅,也更加合理,并且让前端开发人员看得明白,后端开发者也并不会因此而增加工作量呢?

为此,我写了一套关于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)

成功,携带描述信息

success(String message, T data)

成功,携带描述信息和数据

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

成功,携带描述信息、数据、总数、每页条数、总页数、当前页

error(String message)

错误,携带详细的描述信息

快速入门

我们为你提供了三个实体类,以满足不同场景,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

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[xfsy_2015@163.com]
 * @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[xfsy_2015@163.com]
 * @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[xfsy_2015@163.com]
 * @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] 测试示例代码

目录
相关文章
|
10月前
|
缓存 监控 前端开发
顺企网 API 开发实战:搜索 / 详情接口从 0 到 1 落地(附 Elasticsearch 优化 + 错误速查)
企业API开发常陷参数、缓存、错误处理三大坑?本指南拆解顺企网双接口全流程,涵盖搜索优化、签名验证、限流应对,附可复用代码与错误速查表,助你2小时高效搞定开发,提升响应速度与稳定性。
|
10月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
10月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
11月前
|
JSON 前端开发 API
如何调用体育数据足篮接口API
本文介绍如何调用体育数据API:首先选择可靠服务商并注册获取密钥,接着阅读文档了解基础URL、端点、参数及请求头,然后使用Python等语言发送请求、解析JSON数据,最后将数据应用于Web、App或分析场景,同时注意密钥安全、速率限制与错误处理。
1169 152
|
10月前
|
API 开发者 数据采集
高效获取淘宝商品详情:API 开发实现链接解析的完整技术方案
2025反向海淘新机遇:依托代购系统,聚焦小众垂直品类,结合Pandabay数据选品,降本增效。系统实现智能翻译、支付风控、物流优化,助力中式养生茶等品类利润翻倍,新手也能快速入局全球市场。
高效获取淘宝商品详情:API 开发实现链接解析的完整技术方案
|
10月前
|
缓存 数据可视化 定位技术
快递鸟快递API技术指南:获取物流轨迹信息与轨迹地图的解决方案
在当今电商竞争激烈的环境中,物流体验已成为提升用户满意度的关键因素。研究表明,超过 75% 的消费者会因物流信息不透明而放弃下单。
2163 1
|
10月前
|
存储 缓存 算法
淘宝买家秀 API 深度开发:多模态内容解析与合规推荐技术拆解
本文详解淘宝买家秀接口(taobao.reviews.get)的合规调用、数据标准化与智能推荐全链路方案。涵盖权限申请、多模态数据清洗、情感分析、混合推荐模型及缓存优化,助力开发者提升审核效率60%、商品转化率增长28%,实现UGC数据高效变现。
|
10月前
|
人工智能 自然语言处理 测试技术
Apipost智能搜索:只需用业务语言描述需求,就能精准定位目标接口,API 搜索的下一代形态!
在大型项目中,API 数量庞大、命名不一,导致“找接口”耗时费力。传统工具依赖关键词搜索,难以应对语义模糊或命名不规范的场景。Apipost AI 智能搜索功能,支持自然语言查询,如“和用户登录有关的接口”,系统可理解语义并精准匹配目标接口。无论是新人上手、模糊查找还是批量定位,都能大幅提升检索效率,降低协作成本。从关键词到语义理解,智能搜索让开发者少花时间找接口,多专注核心开发,真正实现高效协作。
|
10月前
|
存储 缓存 算法
亚马逊 SP-API 深度开发:关键字搜索接口的购物意图挖掘与合规竞品分析
本文深度解析亚马逊SP-API关键字搜索接口的合规调用与商业应用,涵盖意图识别、竞品分析、性能优化全链路。通过COSMO算法解析用户购物意图,结合合规技术方案提升关键词转化率,助力卖家实现数据驱动决策,安全高效优化运营。
|
10月前
|
缓存 人工智能 API
API接口调用中的网络异常及解决方案
淘宝API是淘宝开放平台提供的接口集合,支持商品、交易、用户、营销等数据交互。开发者需注册获取App Key,通过签名认证调用API,结合沙箱测试、OAuth授权与安全策略,实现订单管理、数据监控等应用,提升电商自动化与数据分析能力。

热门文章

最新文章