【问题标题】:Spring REST API Response for Junction Tables联结表的 Spring REST API 响应
【发布时间】:2017-05-19 18:42:25
【问题描述】:

我有一个 MySQL 数据库和一个在 Tomcat 上运行的 SpringBoot 应用程序。这是我的一个个人项目,也是我设计 REST 服务的第一次体验。我一直在尝试创建我的 POJO 来匹配数据库,但是这个特定的对象引起了一些疑问。

以下是主数据库表:

  • 播放器(ID、描述)
  • 广告系列(ID、描述)
  • 资源(id、描述、resource_type_id)
  • resource_type(id、描述)
  • 组件(ID、描述)

...以及以下联结表:

  • player_resource(id, player_id, resource_id):一个玩家可能有很多资源,一个资源可能属于很多玩家。
  • campaign_resource (id, campaign_id, resource_id):一个活动可能有很多资源,一个资源可能属于很多活动。
  • resource_component(id, resource_id, component_id):一个资源可能有很多组件,一个组件可能属于很多资源

我有点不知道应该如何设计我的 JSON 响应以及专门为 Resource 对象设计的相应 POJO。

到目前为止,我的想法是拥有三个独立的 URI:

  1. .../api/resources/{uuid}:返回具体的资源。
  2. .../api/campaigns/{uuid}/resources:返回提供的广告系列中可用的资源。顺便说一句,玩家存在于战役的范围内,所以这个特定的 API 最终决定了玩家在他们存在的过程中可以获得什么。
  3. .../api/players/{uuid}/resources:返回玩家当前在其库存中拥有的资源。

我为 Resource 创建了一个 POJO:

public class Resource {

    private String resourceId;
    private String shortDescription;
    private String longDescription;
    private ResourceType resourceType;
    private List<Component> components;

    // getters and setters

}

我为 CampaignResource 和 PlayerResource 创建了两个额外的 POJO:

public class CampaignResource {

    private String campaignResourceId;
    private Resource resource;

    // getters and setters

}

public class PlayerResource {

    private String playerResourceId;
    private Resource resource;

    // getters and setters

}

我希望 URI #1 和 #2 返回相同的布局,但我对 URI #3 存在冗余问题。 URI #2 可能会返回 10 个资源,这很好且符合预期,但 URI #3 可能会返回数百个,具体取决于玩家携带的物品。

调用 URI #3 时我真正需要的唯一信息是 player_resource_id、resource_id 和 resource_type_id 字段。我不需要知道资源由哪些组件组成,因为使用 URI #1 或 URI #1 以更易于管理的方式返回该信息。

我害怕创建单独的“基础”资源 POJO,因为我觉得有义务遵循某种形式的规范建模。我可以使用 JsonView 之类的东西并根据它是 URI #1、#2 还是 #3 来分离 Resource RowMappers 吗?我可以实现某种形式的分页,但它仍然有很多冗余数据。一位资深的 REST 开发人员会如何处理这个问题?

【问题讨论】:

    标签: java json spring rest


    【解决方案1】:

    为什么需要为每个 REST API 创建包含资源的单独类。只需返回#1 的一个资源和#2 和#3 的资源列表。

    【讨论】:

    • 这对我的 .../api/players/{uuid}/resources 调用不起作用,因为我需要返回包含 player_resource 表连接键的 playerResourceId 字段。一个玩家可以拥有许多相同的资源,因此如果没有 playerResourceId,我无法识别 Resource 的唯一实例。
    • 您的休息调用合同规定为由其 UUID 标识的给定玩家返回资源。调用者不应该关心 playerResourceId。通过公开 playerResourceId,您将数据库设计泄露给外部调用者。如果稍后您决定不使用连接表让您的播放器进行资源关联,而是规范化并将资源 UUID 放入播放器表中,您将返回什么 playerResourceId?
    • 仍然需要一个键来识别资源的特定实例。例如,如果我有一个资源“木头”而我的播放器有两个“木头”资源 - 我需要使用一些东西来区分这两者。有没有比使用 UUID 更好的方法?
    • 您的资源有“resourceId”字段。它不是唯一的标识符吗?如果没有,也许你需要让它独一无二。
    • 它唯一地标识了一种资源 - 而不是资源的特定实例。我可能会更好地将“player_resource”表描述为“inventory”表,将“player_resource_id”更改为“inventory_id”,这样会更有意义。我觉得这更符合语义,但也许对于面向客户的方面来说,这样是有意义的?
    【解决方案2】:

    我认为如果您想了解 RESTful API 的 this post 会很有帮助。具体关于您要问的内容,请查看主题限制 API 返回的字段

    使用字段查询参数,该参数采用逗号分隔的要包含的字段列表。

    例如:

    GET /tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at

    Here您可以了解 Google、Facebook 和 LinkdIn 的做法。

    []s

    【讨论】:

    • 我不确定添加字段过滤器是否有意义。我不想将campaignResourceId 或playerResourceId 添加到基础Resource 类,因为这些字段并不总是存在。允许消费者请求它们会导致错误。
    猜你喜欢
    • 2020-11-09
    • 2020-02-24
    • 2014-08-24
    • 2017-12-20
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    相关资源
    最近更新 更多