Board logo

标题: RESTful Grails(3) [打印本页]

作者: look_w    时间: 2018-8-8 10:21     标题: RESTful Grails(3)

用 Grails 实现 RESTful Web 服务首先,需要确保您的控制器已经开始响应那四个 HTTP 方法了。回想一下,如果用户不指定一个像 list或 show这样的操作的话,index闭包就是通往控制器的入口点。index默认重定向到 list操作:def index = { redirect(action:list,params:params) }。用清单 8 中的代码替换这个代码:
清单 8. 启动 HTTP 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def index = {      
switch(request.method){
   case "POST":
     render "Create\n"
     break
   case "GET":
     render "Retrieve\n"
     break
   case "PUT":
     render "Update\n"
     break
   case "DELETE":
     render "Delete\n"
     break
}   
}




如清单 9 所示,使用 cURL来验证 switch语句运行正常:
清单 9. 全部四个 HTTP 方法都使用 cURL
1
2
3
4
5
6
7
8
$ curl --request POST http://localhost:9090/trip/airport
Create
$ curl --request GET http://localhost:9090/trip/airport
Retrieve
$ curl --request PUT http://localhost:9090/trip/airport
Update
$ curl --request DELETE http://localhost:9090/trip/airport
Delete




实现 GET由于您已经知道如何返回 XML 了,实现 GET方法就应该是小菜一碟了。但有一点需要注意。对 http://localhost:9090/trip/airport 的 GET请求应该返回一个机场列表。而对 http://localhost:9090/trip/airport/den 的 GET请求应该返回 IATA 代码为 den 的一个机场实例。要达到这个目的,必须建立一个 URL 映射。
在文本编辑器中打开 grails-app/conf/UrlMappings.groovy。默认的 /$controller/$action?/$id?映射看起来应该很熟悉。URL http://localhost:9090/trip/airport/show/1 映射到了 AiportController和 show操作,而 params.id值被设置成 1。操作和 ID 结尾的问号说明 URL 元素是可以选择的。
如清单 10 所示,向将 RESTful 请求映射回 AirportController的 static mappings块添加一行。由于还没有在其他控制器中实现 REST 支持,所以我暂时对控制器进行了硬编码。稍候可能会用 $controller来替代 URL 的 airport部分。
清单 10. 创建一个自定义 URL 映射
1
2
3
4
5
6
7
8
9
10
class UrlMappings {
   static mappings = {
     "/$controller/$action?/$id?"{
        constraints { // apply constraints here
        }
       }         
       "/rest/airport/$iata?"(controller:"airport",action:"index")
    "500"(view:'/error')
  }
}




该映射确保了所有以 /rest 开头的 URI 都被传送到了 index操作(这样就不需要协商内容了)。它还意味着您可以检查 params.iata存在与否,以此来决定是应该返回列表还是一个实例。
按清单 11 所示的方法,修改 index 操作:
清单 11. 从 HTTP GET返回 XML
1
2
3
4
5
6
7
8
9
10
11
def index = {      
switch(request.method){
   case "POST":   //...
   case "GET":
     if(params.iata){render Airport.findByIata(params.iata) as XML}
     else{render Airport.list() as XML}         
     break
   case "PUT":    //...
   case "DELETE": //...
}      
}




在 Web 浏览器中输入 http://localhost:9090/trip/rest/airport和 http://localhost:9090/trip/rest/airport/den,确认自定义 URL 映射已经就位。
通过 HTTP 方法实现的自定义 URL 映射您可以使用不同的方法来建立 RESTful URL 映射。您可以依照 HTTP 请求将请求传送到具体操作。例如,按照如下的方法可以将 GET、PUT、POST和 DELETE映射到已经存在的相应 Grails 操作:
static mappings = {
   "/airport/$id"(controller:"airport"){
       action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"]
   } }

实现 DELETE添加 DELETE支持与添加 GET支持的差别不大。但在这里,我仅需要通过 IATA 代码逐个删除机场。如果用户提交了一个不带有 IATA 代码的 HTTP DELETE请求的话,我将返回一个 400 HTTP 状态码 Bad Request。如果用户提交了一个无法找到的 IATA 代码的话,我将返回一个常见的 404 状态码 Not Found。只有删除成功了,我才会返回标准的 200 OK(参见 参考资料,查看更多有关 HTTP 状态码的信息的链接)。
将清单 12 中的代码添加到 index操作中的 DELETE case中:
清单 12. 对 HTTP DELETE做出响应
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def index = {      
switch(request.method){
   case "POST": //...
   case "GET":  //...
   case "PUT":  //...
   case "DELETE":
     if(params.iata){
       def airport = Airport.findByIata(params.iata)
       if(airport){
         airport.delete()
         render "Successfully Deleted."
       }
       else{
         response.status = 404 //Not Found
         render "${params.iata} not found."
       }
     }
     else{
       response.status = 400 //Bad Request
       render """DELETE request must include the IATA code
                 Example: /rest/airport/iata
       """
     }
     break
}
}




首先,试着删除一个已知确实存在的机场,如清单 13 所示:
清单 13. 删除一个存在的机场
1
2
3
4
5
Deleting a Good Airport</heading>
$ curl --verbose --request DELETE http://localhost:9090/trip/rest/airport/lga
> DELETE /trip/rest/airport/lga HTTP/1.1
< HTTP/1.1 200 OK
Successfully Deleted.




然后,试着删除一个已知不存在的机场,如清单 14 所示:
清单 14. 试着 DELETE一个不存在的机场
1
2
3
4
$ curl --verbose --request DELETE http://localhost:9090/trip/rest/airport/foo
> DELETE /trip/rest/airport/foo HTTP/1.1
< HTTP/1.1 404 Not Found
foo not found.




最后,试着发出一个不带有 IATA 代码的 DELETE请求,如清单 15 所示:
清单 15. 试着一次性 DELETE所有机场
1
2
3
4
5
$ curl --verbose --request DELETE http://localhost:9090/trip/rest/airport
> DELETE /trip/rest/airport HTTP/1.1
< HTTP/1.1 400 Bad Request
DELETE request must include the IATA code
Example: /rest/airport/iata






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0