本月探討如何讓 Grails 應用程式成為原始資料(XML)來源,供其他 Web 應用程式呼叫。雖常稱為「建立 Web 服務」,但傳統 Web 服務常聯想到 SOAP 與 SOA。本文將實作基於 REST(Representational State Transfer)的介面,回傳 Plain Old XML(POX),並澄清 SOA 與 ROA(Resource-Oriented Architecture)的差異。
開發人員口中的「RESTful」通常指「簡單 HTTP GET 回傳 XML」。Yahoo! 等大廠提供此類服務(如 https://api.search.yahoo.com/...webSearch?query=beatles),實為 RPC 風格,Yahoo! 官方 FAQ 亦承認僅為「類 REST」。真正的 REST 由 Roy Fielding 博士論文定義:資源導向,URI 識別資源,統一介面使用標準 HTTP 動詞(GET、POST、PUT、DELETE)操作資源完整 CRUD 生命週期,而非自訂方法名稱(如 webSearch、getForecast)。本文將兩者區分為 GETful(簡單 GET 取得 XML)與 RESTful(資源導向、標準 HTTP 動詞)。
最快方式:匯入 grails.converters.*,在控制器加入 render Airport.list() as XML。預設 XML 結構適合除錯,若需客製化,可用 render(contentType:"text/xml") { ... } 搭配 Groovy MarkupBuilder 動態產生任意結構(元素名稱、屬性、巢狀結構皆可自訂)。
HTTP Accept 標頭讓客戶端聲明偏好格式。使用 curl --header Accept:text/xml ... 可測試。Grails 將 Accept 對應至 Config.groovy 的 grails.mime.types 對應表(xml: ['text/xml','application/xml'] 等),並在 request.format 提供解析結果。在控制器動作使用 withFormat { html { ... } xml { ... } } 即可依據 Accept 回傳 HTML 或 XML。亦可透過副檔名(.xml)或查詢參數(?format=xml)強制指定格式。
在 UrlMappings.groovy 定義 "/rest/airport/$iata?"(controller:"airport", action:"index"),將所有 /rest/airport 請求導向 index 動作,並透過 request.method 判斷 HTTP 動詞:
params.iata 存在回傳單一機場 XML,否則回傳列表。new Airport(params.airport);複雜 XML 需用 request.XML(XmlSlurper)解析屬性與巢狀元素。成功回傳 201 Created 及新資源 XML。airport.properties = params.airport 更新屬性,成功回傳 200。使用 curl 逐一驗證四大動詞,確認狀態碼與回應正確。
Grails 提供強大的 XML 輸出、內容協商、URL 映射與請求解析能力,無論您偏好 GETful 簡單風格或嚴格 RESTful 資源導向,皆能輕鬆實作。下一期將聚焦測試工具,確保應用程式在生命週期中持續無誤運行。