如何在具有自动保存功能的网站上设计 api 端点?

Posted

技术标签:

【中文标题】如何在具有自动保存功能的网站上设计 api 端点?【英文标题】:How to design api endpoints on a website with auto save? 【发布时间】:2021-08-17 12:04:13 【问题描述】:

我有一个网站,每个公司都可以在其中修改一些设置:UpperBanner、LowerBanner、Introduction 或 TextSize。这些字段中的每一个都具有自动保存功能。我应该为每个字段创建端点吗?

这是我数据库中的一个表:

这是我的网站设计(每个字段都有自动保存):

我考虑以下端点。方向好吗?

GET /PageSettings - to return a row in a database for a company
HEAD /PageSettings - to check if exists a row in a database for a company
POST /PageSettings - to create a row in a database with only Id and CompanyId

HEAD /PageSettings/UpperBanner/FileId - to check if exists UpperBanner in a database for a company
POST /PageSettings/UpperBanner - to add UpperBanner in a database for a company
PUT /PageSettings/UpperBanner/FileId - to change UpperBanner in a database for a company

HEAD /PageSettings/LowerBanner/FileId - to check if exists LowerBanner in a database for a company
POST /PageSettings/LowerBanner - to add LowerBanner in a database for a company
PUT /PageSettings/LowerBanner/FileId - to change LowerBanner in a database for a company

HEAD /PageSettings/Introduction - to check if exists Introduction in a database for a company
POST /PageSettings/Introduction - to add Introduction in a database for a company
PUT /PageSettings/Introduction - to change Introduction in a database for a company

HEAD /PageSettings/TextSize - to check if exists TextSize in a database for a company
POST /PageSettings/TextSize - to add TextSize in a database for a company
PUT /PageSettings/TextSize - to change TextSize in a database for a company

【问题讨论】:

或许可以考虑使用http方式PATH? 我有文件,所以不知道 PATH 是否简单。 【参考方案1】:

最好创建一个单独的 CRUD 端点,其 PUT/PATCH 操作仅更新发送的信息。在这种情况下,您必须区分何时发送或尚未发送可能为 null 的字段。

如果您消除了包含 null 元素的可能性,则合并是微不足道的:

@Controller
... MyControllerClass 

    @Put / @Patch
    public Response upsert(Entity upsertEntity) 
        ...
        Entity currentEntity = repository
            .get(upsertEntity.getId())
            .merge(upsertEntity);
        ...
        repository.save(currentEntity);

Entity.merge 操作如下:

class Entity 
    ...
    public Entity merge(Entity other) 
        if(other.getField1() != null) setField1(other.getField1());
        if(other.getField2() != null) setField1(other.getField2());
        ...
        // merge hierarchy
        if(other.getFieldX() != null)
            getFieldX().merge(other.getFieldX());
        ...
        return this;

如果可以将字段删除到null 状态,则此方法不起作用,并且您不能为您的 API 使用相同的持久性实体(例如 Spring Boot Forms,在许多情况下您需要一个包装器)。

因此,如果客户端想要更新 N 个字段,只需一次操作即可完成。如果当用户进行更改时您等待 X 秒,您可以检测并累积多个更改以一起发送。

如果您需要重置字段(设置为 null),请为单个操作创建特定类型:

class UpsertRequestData 
    private boolean resetField1; // or `field1IsPresent`
    private Field1Type field1;
    private boolean resetField2;
    private Field2Type field2;
    ...

【讨论】:

不幸的是每个字段都可以为空:( 然后正如我所说,为每个字段包装数据,而不是创建一个完整的端点。

以上是关于如何在具有自动保存功能的网站上设计 api 端点?的主要内容,如果未能解决你的问题,请参考以下文章

怎么用百度地图api自动获取当前位置(谷歌的也行)

如何使用设计自动化 API 从上传的 AutoCAD 文件中提取元数据?

API管理和最佳实践

保护 Firebase Cloud Function HTTP 端点

如果其中一个工作簿具有自动保存功能,如何分离 Excel 实例?

Restful API设计