Board logo

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

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

实现 POST接下来您的目标是要插入一个新的 Airport。创建一个如清单 16 所示的名为 simpleAirport.xml 的文件:
清单 16. simpleAirport.xml
1
2
3
4
5
6
7
8
9
<airport>
<iata>oma</iata>
<name>Eppley Airfield</name>
<city>Omaha</city>
<state>NE</state>
<country>US</country>
<lat>41.3019419</lat>
<lng>-95.8939015</lng>
</airport>




如果资源的 XML 表示是扁平结构(没有深层嵌套元素),而且每一个元素名称都与类中的一个字段名称相对应的话,Grails 就能够直接从 XML 中构造出新类来。XML 文档的根元素是通过 params寻址的,如清单 17 所示:
清单 17. 响应 HTTP POST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def index = {      
switch(request.method){
   case "POST":
     def airport = new Airport(params.airport)
     if(airport.save()){
       response.status = 201 // Created
       render airport as XML
     }
     else{
       response.status = 500 //Internal Server Error
       render "Could not create new Airport due to errors:\n ${airport.errors}"
     }
     break
   case "GET":    //...
   case "PUT":    //...
   case "DELETE": //...
}      
}




XML 一定要使用扁平结构,这是因为 params.airport其实是一个散列(Grails 是在后台将 XML 转换成散列的)。这意味着您在对 Airport使用命名参数构造函数 —def airport = new Airport(iata:"oma", city:"Omaha", state:"NE")。
要测试新代码,就要使用 cURL来 POSTsimpleAirport.xml 文件,如清单 18 所示:
清单 18. 使用 cURL来发出一个 HTTP POST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ curl --verbose --request POST --header "Content-Type: text/xml" --data
     @simpleAirport.xml http://localhost:9090/trip/rest/airport
> POST /trip/rest/airport HTTP/1.1
> Content-Type: text/xml
> Content-Length: 176
>
< HTTP/1.1 201 Created
< Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?><airport id="14">
<arrivals>
   <null/>
</arrivals>
<city>Omaha</city>
<country>US</country>
<departures>
   <null/>
</departures>
<iata>oma</iata>
<lat>41.3019419</lat>
<lng>-95.8939015</lng>
<name>Eppley Airfield</name>
<state>NE</state>
</airport>




如果 XML 比较复杂的话,则需要解析它。例如,还记得您先前定义的自定义 XML 格式么?创建一个名为 newAirport.xml 的文件,如清单 19 所示:
清单 19. newAirport.xml
1
2
3
4
5
6
7
<airport iata="oma">
<official-name>Eppley Airfield</official-name>
<city>Omaha</city>
<state>NE</state>
<country>US</country>
<location latitude="41.3019419" longitude="-95.8939015"/>
</airport>




现在,在 index操作中,用清单 20 中的代码替代 def airport = new Airport(params.airport)行:
清单 20. 解析复杂的 XML
1
2
3
4
5
6
7
8
def airport = new Airport()
airport.iata = request.XML.@iata
airport.name = request.XML."official-name"
airport.city = request.XML.city
airport.state = request.XML.state
airport.country = request.XML.country
airport.lat = request.XML.location.@latitude
airport.lng = request.XML.location.@longitude




request.XML对象是一个持有原始 XML 的 groovy.util.XmlSlurper。它是根元素,因此您可以通过名称(request.XML.city)来寻找子元素。如果名称是用连字符连接的,或者使用了名称空间,就加上引号(request.XML."official-name")。元素的属性要使用 @符号(request.XML.location.@latitude)来访问(参见 ,查看有关 XmlSlurper的更多信息的链接)。
最后,使用 cURL来测试它:curl --request POST --header "Content-Type: text/xml" --data @newAirport.xml http://localhost:9090/trip/rest/airport。
实现 PUT您需要支持的最后一个 HTTP 方法就是 PUT。了解了 POST之后,会知道代码基本是一样的。惟一不同的就是它无法直接从 XML 构造类,您需要向 GORM 寻求现有的类。然后,airport.properties = params.airport行会用新的 XML 数据来替代现有的字段数据,如清单 21 所示:
清单 21. 响应 HTTP PUT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def index = {      
switch(request.method){
   case "POST":  //...
   case "GET":   //...
   case "PUT":   
     def airport = Airport.findByIata(params.airport.iata)
     airport.properties = params.airport
     if(airport.save()){
       response.status = 200 // OK
       render airport as XML
     }
     else{
       response.status = 500 //Internal Server Error
       render "Could not create new Airport due to errors:\n ${airport.errors}"
     }
     break
   case "DELETE": //...
}      
}




创建一个名为 editAirport.xml 的文件,如清单 22 所示:
清单 22. editAirport.xml
1
2
3
4
5
6
7
8
9
<airport>
<iata>oma</iata>
<name>xxxEppley Airfield</name>
<city>Omaha</city>
<state>NE</state>
<country>US</country>
<lat>41.3019419</lat>
<lng>-95.8939015</lng>
</airport>




最后,使用 cURL: curl --verbose --request PUT --header "Content-Type: text/xml" --data @editAirport.xml http://localhost:9090/trip/rest/airport来测试它。
结束语我在很短的时间内讲解了很多相关知识。现在,您应该了解到 SOA 和 ROA 之间的不同之处了。您同样也应该意识到,并不是所有的 RESTful Web 服务都如出一辙。有些 Web 服务是 GETful 的 —使用 HTTP GET请求来调用类 RPC 方法。而其他的则是纯粹面向资源的,其中 URI 是访问资源的关键,而标准 HTTP GET、POST、PUT和 DELETE方法构成了完整的 CRUD 功能。无论您是喜欢 GETful 方法还是 RESTful 方法,Grails 都为输出和轻易地获取 XML 提供了强有力的支持。
在下一期的 中,我将把重点转向测试。Grails 配有优良的开箱即用的测试工具。而那些没有提供的功能则可以在以后以插件的形式添加进去。既然已经在 Grails 开发中投入了这么多的时间了,那么就一定要确保它在无错误的情况下开始运行并可以在应用程序的整个生命周期中都可以保持这种无错误的状态。在达到这个目标之前,继续关注精通 Grails 系列文章吧。




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