Разработка интерфейса API (1): решение возврата результата разработки интерфейса

API

Резюме

Если интерфейс и сервер разделены для разработки проекта, лучший способ взаимодействия с интерфейсом и сервером — использовать HTTP + JSON. Как интерфейс выдачи результатов сделать лаконичнее, элегантнее и разумнее, и дать понять фронтенд-разработчикам, а бэкенд-разработчикам не увеличить из-за этого нагрузку?

текст начинается

Всем привет, давно не виделись. Я планировал доработку версии своего личного сайта 2020 года, поэтому эта статья также является последней в 2019. Конечно, мне нужно потратить некоторое время, пытаясь сказать все, что я хочу сказать, и сделать это ясно. .

Если интерфейс и сервер разделены для разработки проекта, лучший способ взаимодействия с интерфейсом и сервером — использовать HTTP + JSON. Как интерфейс выдачи результатов сделать лаконичнее, элегантнее и разумнее, и дать понять фронтенд-разработчикам, а бэкенд-разработчикам не увеличить из-за этого нагрузку?

С этой целью я написал набор решений для разработки интерфейса API для возврата результатов,api-result, который был открыт и загружен нацентральный склад, любая критика и исправления приветствуются.

объяснение API

класс сущности

Предоставляет классы сущностей, отвечающие потребностям различных сценариев, а именно:

ResultModel

Этот класс является базовым классом сущностей со следующими свойствами:

успех: возвращает идентификатор результата, который является логическим значением, true/false (успех/неудача)

сообщение: информация описания, если есть ошибка, вы можете заполнить подробности ошибки здесь

data: данные, которые являются универсальным типом, который может быть массивом или объектом и т. д. Этот параметр доступен только в том случае, если он выполнен успешно и данные должны быть возвращены.

ApiResultModel

Структурная взаимосвязь выглядит следующим образом:

 ResultModel
 └── ApiResultModel

В этом классе добавленоcodeСвойство также является универсальным типом, вы можете настроить тип вашего типа возврата, который может быть целым числом или строкой.

PageResultModel

Структурная взаимосвязь выглядит следующим образом:

 ResultModel
 └── PageResultModel

Этот класс в основном возвращает результаты путем разбиения на страницы, поэтому добавлены следующие свойства:

total: общее количество данных, длинный тип

размер: количество записей на странице, целое число

страницы: общее количество страниц, длинный тип

current: текущая страница, длинный тип

Класс вспомогательных инструментов

Помогите нам работать с классами сущностей, какие есть конкретные помощники? следующим образом:

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 подходит для возврата результатов при разбиении по страницам. Он также предоставляет свои собственные помощники для этих трех классов сущностей, так что вы можете использовать эти помощники для прямого возврата. Конечно, я рекомендую сначала написать класс инструмента для каждого помощника, а затем вернуть его через класс инструмента, так что может быть более разумно настроить свой собственный класс инструмента возврата.

Используйте Помощник, чтобы вернуться

Сначала давайте посмотрим на простой пример кода:

/**
 * 添加方法示例
 * @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;
    }
}

Пример парсинга возвращаемого результата пейджинга

Это немного отличается от приведенного выше, потому что добавляются некоторые поля, поэтому мы можем вернуть его с помощью бинов.

/**
 * 解析分页返回结果示例
 * @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-результата | github

[2] исходный код API-результата | Code Cloud

[3] центральный репозиторий результатов API

[4] Тестовый образец кода