Java 当我们有可选行为时,什么是正确的restful API设计?

Java 当我们有可选行为时,什么是正确的restful API设计?,java,rest,api,Java,Rest,Api,我有一个将一个班级的学生分成小组的用例。 类有一个classId,团队有一个teamId 我有以下选择: 创建两个端点: @GET @Path("/schoolMetadata/byClass/{classId}") @Produces(MediaType.APPLICATION_JSON) public Response getMetadataByClassId( 及 第二个实现是使用查询参数 @GET @Path("/schoolMetadata/by/") @Produces(Medi

我有一个将一个班级的学生分成小组的用例。 类有一个classId,团队有一个teamId

我有以下选择:

  • 创建两个端点:

    @GET
    @Path("/schoolMetadata/byClass/{classId}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getMetadataByClassId(
    
  • 第二个实现是使用查询参数

    @GET
    @Path("/schoolMetadata/by/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getMetadataById(
        @QueryParam("classId") final Id classId
        @QueryParam("teamId") final Id groupId) {
        if (classid != null) {
        }  else {
        }
    }
    

  • 两种方法中哪一种更好?

    我想第一种方法更好,因为它符合单一责任原则(SOLID)

    单一责任原则(SRP)断言一个类或模块应该只做一件事。现在,这是一种主观的观点,因此这个原则通过启发式得到了加强,即类或模块应该只有一个改变的理由


    1方法有两个方法(模块),每个方法只做一件事

    RESTful URL背后的思想是,它们应该表示单数或复数名词的“资源”。代表类似事物的“集合”的资源应该是复数的。您已经指出,可以为类id或团队id获取学校元数据。听起来像类和团队的可能被视为“资源”,而不管它们是否都在内部建模为“学校元数据”。如果没有任何其他信息,我可能会建议如下:

    • classes/{classId}
    • teams/{teamId}
    如果您使用的是JAXR,那么很自然会得到类似以下内容的URL:

    • 学校元数据/资源/类/{classId}
    • 学校元数据/资源/团队/{teamid}
    您可能还希望实现:

    • 学校元数据/资源/类生成“类”列表。这里可以使用查询参数来简化搜索选项
    • 学校元数据/资源/团队生成“团队”列表
    事实上,REST认为URL是不透明的。没有“RESTful URL”这样的东西。请不要把可破解的URL最佳实践与REST约束混为一谈。Eric,你读过了吗。我认为他不同意你的意见,事实上我同意。请指出论文中建议RESTURL应该包含对客户端有语义意义的信息的地方?我还想让你参考马口:我已经提供了一个链接,指向讨论这个问题的部分。它清楚地指出,“REST中信息的关键抽象是一种资源。任何可以命名的信息都可以是资源:文档或图像、临时服务(如“今日洛杉矶天气”)、其他资源的集合、非虚拟对象(如人)等等。换句话说,任何可能成为作者超文本引用目标的概念都必须符合资源的定义。资源是一组实体的概念映射…“您引用的部分没有提供URL应该是什么样子的指导。论文中的其他地方也没有。按照Fielding的定义,REST意味着您使用的是HATEOAS和以下链接,而不是黑客URL。可破解的URL为开发人员提供了便利。它们可能是好的设计,也可能不是好的设计,但它们不是休息。
    @GET
    @Path("/schoolMetadata/by/")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getMetadataById(
        @QueryParam("classId") final Id classId
        @QueryParam("teamId") final Id groupId) {
        if (classid != null) {
        }  else {
        }
    }