技术开发 频道

精通 Grails: 用 JSON 和 Ajax 实现异步 Grails

  创建用于发出远程 JSON 请求的控制器方法

  在本文的前面,您已经创建了一个 HotelController。将清单 15 中的 near 闭包添加到其中。(您在 “Grails 服务和 Google 地图” 中已经看到了类似的代码)。

  清单 15. HotelController

class HotelController {
  def scaffold
= Hotel
  def near
= {
    def addr
= "http://local.yahooapis.com/LocalSearchService/V3/localSearch?"
    def qs
= []
    qs
<< "appid=YahooDemo"
    qs
<< "query=hotel"
    qs
<< "sort=distance"
    qs
<< "output=json"
    qs
<< "latitude=${params.lat}"
    qs
<< "longitude=${params.lng}"
    def url
= new URL(addr + qs.join("&"))
    render(contentType:
"application/json", text:"${url.text}")
  }
}

  所有查询字符串参数都是硬编码的,但最后两个除外:latitude 和 longitude。倒数第二行实例化一个新的 java.net.URL。最后一行调用服务(url.text),并呈现结果。由于没有使用 JSON 转换器,因此必须显式地将 MIME-type 设置为 application/json。除非特意设置,否则 render 会返回 text/plain。

  在浏览器中输入下面的内容(不要换行):

http://localhost:9090/trip/hotel/near?lat=
  
39.858409881591797&lng=-104.666999816894531

  将结果与前面直接调用 http://local.yahooapis.com 的结果相比,两者应该是相同的。

  使用控制器可以让远程 JSON 请求带来两个好处:可以规避同源 Ajax 限制(参见 为什么不能直接从浏览器远程调用 Web 服务? 侧边栏),但是更重要的是,它提供某种封装。控制器将变得与 Data Access Object(DAO)类似。

  就像您不希望将 URL 硬编码到远程 Web 服务中一样,您也不希望在视图中出现原始的 SQL。现在,通过调用一个本地控制器,可以保证下游的客户机不受实现更改的影响。表名或字段名的更改会破坏嵌入式的 SQL 语句,URL 的更改则会破坏嵌入式的 Ajax 调用。而通过调用 AirportMapping.iata(),则就可以随意更改本地表和远程 GeoNames 服务中的数据源,并保证客户端界面不受影响。长远来看,为了提升性能,甚至可以将对远程服务的调用缓存到一个本地数据库,为每个请求构建本地缓存。

  现在,这个服务已经可以工作,您可以从 Web 页面调用它。

0
相关文章