用 Grails 实现 GETful Web 服务
从 Grails 应用程序中获取 POX 的最快捷的方式就是导入 grails.converters.* 包,然后添加一对新的闭包,如清单 1 所示:
清单1. 简单的 XML 输出
import grails.converters.*
class AirportController{
def xmlList = {
render Airport.list() as XML
}
def xmlShow = {
render Airport.get(params.id) as XML
}
//... the rest of the controller
}
class AirportController{
def xmlList = {
render Airport.list() as XML
}
def xmlShow = {
render Airport.get(params.id) as XML
}
//... the rest of the controller
}
您在 “精通 Grails:使用 Ajax 实现多对多关系 中见过了使用中的 grails.converters” 包。该包向您提供了非常简单的 JavaScript Object Notation(JSON)和 XML 输出支持。图 1 展示了调用 xmlList 操作的结果:
图 1. 来自于 Grails 的默认 XML 输出
虽然默认的 XML 输出很好调试,但您还是想稍微自定义一下格式。还好,render() 方法给您提供了一个 Groovy MarkupBuilder,它允许您动态定义自定义 XML(参见 参考资源,查看更多有关 MarkupBuilder 的消息的链接)。清单 2 创建了一些自定义 XML 输出:
清单 2. 自定义 XML 输出
def customXmlList = {
def list = Airport.list()
render(contentType:"text/xml"){
airports{
for(a in list){
airport(id:a.id, iata:a.iata){
"official-name"(a.name)
city(a.city)
state(a.state)
country(a.country)
location(latitude:a.lat, longitude:a.lng)
}
}
}
}
}
def list = Airport.list()
render(contentType:"text/xml"){
airports{
for(a in list){
airport(id:a.id, iata:a.iata){
"official-name"(a.name)
city(a.city)
state(a.state)
country(a.country)
location(latitude:a.lat, longitude:a.lng)
}
}
}
}
}
图 2 展示了输出结果:
图 2. 使用 Groovy MarkupBuilder 的自定义 XML 输出
注意源代码和 XML 输出之间的对应的紧密程度。您可以随意定义元素名称(airports、airport、city),无需顾及它们是否与类的真实字段名称对应。如果您想提供一个以连字符链接的元素名称的话(诸如 official-name),又或者想要添加名称空间支持的话,只要给元素名称加上引号就可以了。而属性(诸如 id 和 iata)是用 Groovy 散列映射键:值 语法定义的。要填充元素的正文,需要提供一个不带键:的值。