RESTful grails 应用程序:干燥 UrlMapping
假设我们有一个公开多个资源的 grails Web 应用程序。
- Tags
- urls
- users
该应用程序有一个经典的 Web 界面,用户可以与之交互并进行一些管理。 我们希望通过 RESTful API 将应用程序中的资源公开给客户端,并且我们不希望应用程序的这一部分弄乱我们已有的控制器和代码。 因此,我们提出了以下建议:
如果 Web 界面提供 host/app_path/url/[list|show|create]
,我们希望 REST API 位于 /host/app_path/rest /url
。
所以我们最终得到了以下 UrlMappings 文件:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
}
/* adding new urls and listing them */
"/rest/url"{
controller = "urlRest"
action = [POST: "save", PUT: "save", GET: "list", DELETE:"error"]
}
/* accessing a single url */
"/rest/url/$id"{
controller = "urlRest"
action = [POST: "update", PUT: "update", GET: "show", DELETE: "delete"]
}
/* non-crud stuff on urls */
"/rest/url/$action?/$id?"{
controller = "urlRest"
}
"/"(view:"/index")
"500"(view:'/error')
}
}
问题是,这并不是这里最干燥的东西。 当我们添加更多资源(例如标签)时,情况会变得更糟。 它们将转换为另外三个非常相似的代码块...
非 CRUD 函数将类似于使用特定标准进行搜索之类的东西...
我们尝试使用循环生成映射闭包,但没有成功。 我们是否完全走错了路?
Let's say we have a grails web application exposing several resources.
- tags
- urls
- users
The application has a classical web-interface which the users interact with and some administration.
We want to expose the resources from the application to clients via a RESTful API and we don't want that part of the app to clutter up the controllers and code we already have.
So we came up with the following:
If the web interface offers host/app_path/url/[list|show|create]
we want the REST API to be at /host/app_path/rest/url
.
So we ended up with the following UrlMappings file:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
}
/* adding new urls and listing them */
"/rest/url"{
controller = "urlRest"
action = [POST: "save", PUT: "save", GET: "list", DELETE:"error"]
}
/* accessing a single url */
"/rest/url/$id"{
controller = "urlRest"
action = [POST: "update", PUT: "update", GET: "show", DELETE: "delete"]
}
/* non-crud stuff on urls */
"/rest/url/$action?/$id?"{
controller = "urlRest"
}
"/"(view:"/index")
"500"(view:'/error')
}
}
The problem is, that this isn't exactly the most DRY thing here. It gets worse as we add more resources such as tags. They would translate to yet another three blocks of very similar code...
The non-crud functions will be things like searching with specific criterions and such...
We tried generating the mapping closures with a loop, but without success. Are we completely on the wrong track here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我建议使用以下映射:
下面是将为 urlRestController 创建的 HTTP 方法到操作映射:
我明白为什么您可能想要映射 /rest/url POST 来保存和 /rest/url/id PUT 来更新,但是这违背了这些动词的含义。 PUT 应该是添加新 url 的唯一方法,而 POST 应该是更新 url 的唯一方法。 如果您的约束是保持当前的控制器代码不变,那么按照您布置的方式进行操作可能是最好的方法。 然而,我的猜测是,您的控制器可能已经被编码为可以很好地处理默认映射(如果没有 id,则更新/删除会给出错误,如果没有 id,则显示重定向到列表,等等)。
I would recommend the following mapping:
Below is the HTTP method to action mapping that this would create for the urlRestController:
I see why you might want to map /rest/url POST to save and /rest/url/id PUT to update, but that goes against the meaning of those verbs. A PUT should be the only way to add a new url and POST the only way to update a url. Doing it the way you have laid out would work and might be the best way if your constraint is to keep your current controller code untouched. However, my guess is that you controller might already be coded to handle the default mappings just fine (update/delete give error if no id, show redirects to list if no id, etc.).