【发布时间】:2018-02-28 20:01:05
【问题描述】:
我目前正在开发一个具有多个模型对象的应用程序,这些模型对象彼此之间有很多关系。
例如,我有一个用户对象和一个包含多个用户的组对象。
我们为这些对象公开的端点是:
/users
/users/{uid}
/users/{uid}/groups
/users/{uid}/groups/{gid}
/groups
/groups/{gid}
/groups/{gid}/users
/groups/{gid}/users/{uid}
到目前为止,这很容易。现在假设每个用户和每个组都可以有设置、消息、头像……
现在我们可以公开端点,例如
/users/{uid}/avatar
/groups/{uid}/avatar
/users/{uid}/messages
/users/{uid}/messages/{mid}
/groups/{gid}/messages
/groups/{gid}/messages/{mid}
/users/{uid}/settings
/groups/{gid}/settings
即使只有 6 个关系(user->avatar、group->avatar、user->messages、group->messages、user->setting、group->settings),RequestMappings(端点)的数量在我们考虑各种 CRUD 操作(PUT、DELETE、POST、GET、..)
如果我添加另一个资源,例如可以包含多个组的 groupOfGroups,我将暴露的 RequestMappings 的数量将成倍增加
/gog/{gogid}/groups
/gog/{gogid}/groups/{gid}
/gog/{gogid}/groups/{gid}/users
/gog/{gogid}/groups/{gid}/users/{uid}
/gog/{gogid}/settings
/gog/{gogid}/messages
/gog/{gogid}/avatar
我还将为 CRUD 操作添加 RequestMappings。
为了避免代码重复,我一直在每个主控制器中使用捕获所有请求映射。例如,在 UserController 中,我会有以下 requestMappings
GET /users
GET /users/{id}
POST /users
PUT /users/{id}
DELETE /users/{id}
/**
/** 映射将捕获 /users/{uid}/messages/{mid} 调用。在/**映射对应的方法里面,我会做如下操作
- 令牌化请求 URL 以获取 /users/{uid} 和 restOfTheUrl(在本例中为 /message/{mid} 但可以是 /settings 或 /avatar)
- 检查具有该 uid 的用户是否存在,如果不存在则返回 404
- 添加一个 requestAttribute,其中包含关键用户和值 {uid}
- 转发到 restOfTheUrl
这会将请求转发到 MessageController,在那里我可以使用一些 QueryDSL 构建器来构建 QueryDSL,以仅获取请求属性中的任何消息(在这种情况下,它是具有 {uid} 的用户,但它可以是 ID 为 {gid} 的组或 ID 为 {gogid} 的 groupOfGroups
我想知道这是否是正确的解决方案,或者是否有更好的方法来处理关系而无需转发但也无需重复代码。
至少在我看来,拥有三个端点是没有意义的
/users/{uid}/messages
/users/{uid}/settings
/users/{uid}/avatar
检查用户是否存在,这将对组和 groupOfGroups 执行相同的功能,但唯一的区别是我们正在检查组是否存在或 groupOfGroups 存在。
需要注意的是,像Swagger这样的工具当然不支持这种方式,甚至转发,也不能使用@RestController,只能使用更通用的web mvc注解@Controller。
我想知道这里最好的方法是什么。
【问题讨论】:
标签: spring rest spring-mvc spring-boot spring-rest