首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为子资源设计rest端点URL

问如何为子资源设计rest端点URL
EN

Stack Overflow用户
提问于 2022-01-21 17:03:42
回答 2查看 113关注 0票数 0

假设我们有两个实体。User实体可以有许多报价,而Offer必须有一个User。

代码语言:javascript
复制
class User {
    ...
    @OneToMany(mappedBy = "user", orphanRemoval = true)
    private Set<Offer> offers;
}

class Offer {
    ...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "fk_user")
    private User user;
}

此时有两个控制器。UserController和OrderController。UserController在/api/v1/users/下映射,OrderController映射在/api/v1/orders/下。

  • 获取用户提供列表的端点应该是什么样子的?
  • 应该在同一个控制器里吗?我确实有by functionality项目结构。
  • 如何为特定的Offer修改或删除User?如果我们让/api/v1/users/{username}/offers/{offerId}删除或更新报价,我们是否也应该有允许编辑或删除报价的/api/v1/offers/{offerId}端点?也许对管理员来说,拥有它值得吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-21 17:59:39

我在创建端点时使用的一般经验规则是:

  • URL必须干净易懂。
  • 它们应该尽可能短,同时还要提供信息。
  • 尝试将其构建成允许您在合理数量内重用它的方式。
  • 考虑一下用户体验(无论是浏览器还是移动应用程序等等)。

不过,我不确定是否有一条成文的规则,确切地说应该如何构建一个URL。在您的具体情况下,只有在您公开和使用优惠的唯一位置时,我才会使用/users/{username}/offers/{offerId},因为您是根据功能将代码分隔开的。

如果您有更多关于要约的逻辑和/或具有这种逻辑的bean,我将为/offers下的报价创建一个单独的控制器。关于你最后一个问题。这在很大程度上取决于你在努力实现什么。如果您需要能够更新/删除/创建服务,那么拥有这样的功能是有意义的。即使它仅由管理员使用。可以限制对端点的访问。如何做到这一点取决于您授权用户的方式以及您拥有的有关用户的信息。大多数人都使用角色。

如果您决定拥有完整的CRUD功能,我建议使用单一路径并结合请求方法。

就我个人而言,我要创造以下几点:

代码语言:javascript
复制
@RestController
@RequestMapping(value = "/users")
class UserController {
@GetMapping("{userId}/offers")
    public Set<Offer> getAllOffers(@PathVariable("userId") String userId){
    ...
  }
@GetMapping("{userId}/offers")
    public Offer getOffer(@PathVariable("userId") String userId, @RequestParam(required = true) String offerId){
    ...
  }
@PutMapping("{userId}/offers")
    public Offer createOffer(@PathVariable("userId") String userId, @RequestBody Offer offer){
    ...
  }
@PostMapping("{userId}/offers")
    public Offer updateOffer(@PathVariable("userId") String userId, @RequestBody Offer offer){
    ...
  }
@DeleteMapping("{userId}/offers")
    public void deleteOffer(@PathVariable("userId") String userId, @RequestParam(required = true) String offerId){
    ...
  }
}

在这种情况下,我认为创建和更新的POST/PUT将更干净,因为信息不会重复。准确地说是身份证。

票数 2
EN

Stack Overflow用户

发布于 2022-01-21 17:25:56

我同意它应该位于相同的“UserController”中,这是有意义的,因为提供服务属于用户,因此有一个端点,如:

代码语言:javascript
复制
@GetMapping("{user}/offers")
    public Set<OfferDTO> getOffers(@PathVariable("user") String user) {
    return offerService.getOffers(user);
}

例如,如果您想在列表中显示元数据,您可以定义特殊的DTO,以便从报价中获取元数据,并且可以将它们作为列表显示给用户。

您可以设置一个类似的端点,用于更新服务(可以是POST端点)和删除端点(用于删除)。不过,您可能想一想,如果用户在删除某个报价时,它会发生什么情况,比如在后台线程中执行异步任务,并更新UI以通知用户该提议已被删除。

Spring有一些非常好的安全注释(检查这和这),您可以为管理员端点编写自己的注释:

代码语言:javascript
复制
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasAuthority('" + ROLE_ADMIN + "')")
public @interface IsAdmin {}

然后按如下方式注释您的方法:

代码语言:javascript
复制
@DeleteMapping("/{user}/{offer}/delete")
  @IsReceiverAdmin
  public void delete(@PathVariable("user") String user, @PathVariable("offer") String offer){
    return offerService.delete(user, offer);
  }

当然,服务层的实现是非常重要的,但是它可以像调用存储库和在那里执行操作一样简单:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70804976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档