【问题标题】:Implement a REST API in a Grails app在 Grails 应用程序中实现 REST API
【发布时间】:2012-04-13 12:43:45
【问题描述】:

我想知道让 Grails 应用程序提供可被 Web 服务使用的 RESTful API(主要是一些 CRUD 操作)的最佳方法是什么,例如当您想为基于浏览器的应用程序或其他任何东西构建相应的 iOS 应用程序时。

我想在我的 Grails 应用程序中构建一个单独的部分,接收来自 www.mywebapp.com/api/someAction 的调用,以便我可以重用服务层。那么我将如何进行 URL 映射呢?只有一个大的ApiController 听起来不是很时髦。

或者有什么我不知道的更好的方法吗?这种方法必须支持OAuth之类的东西来验证调用Web服务的用户。

【问题讨论】:

  • 查看这个问答:[RESTful grails application: DRYing up UrlMapping][1] [1]: stackoverflow.com/questions/955603/…
  • 谢谢,但是我只能有一个控制器来处理它?或者我可以映射/rest/foo/$action/$id 例如到RestFooController?这可能吗?
  • 是的,你可以这样映射它。

标签: web-services api rest grails grails-2.0


【解决方案1】:

Grails 可以绝对提供 REST API,但这样做的难度取决于您希望 API 的 mature(也就是 RESTful)的程度。

基本 REST

获得基本的 RESTfullness 水平,您可以使用完整的 HTTP 动词并利用 HTTP 响应代码来操作资源的 json 或 xml 表示,这非常容易。要做到这一点,有 3 个主要部分:

  1. URL mapping

    以下是我如何在最近的项目中编写 URL 映射以允许更多 RESTful URL 的示例:

    // RESTful list mapping
    name restEntityList: "/$controller"(parseRequest: true) {
        action = [GET: "list", POST: "save"]
    }
    
    // RESTful entity mapping
    name restEntity: "/$controller/$id"(parseRequest: true) {
        action = [GET: "show", PUT: "update", POST: "update", DELETE: "delete"]
        constraints {
            id matches: /\d+/
        }
    }
    
  2. Content negotiation

    Grails 可以处理内容协商的 3 种不同方式使框架非常灵活,允许您支持更广泛的客户端,这些客户端可能无法设置诸如 Accept HTTP 标头之类的内容。

    您可以使用内容协商以不同的方式响应不同的请求,使用 withFormat 块根据客户端指示他们想要的内容。这种强大的能力也可以用来对你的 API 进行版本控制,就像 Github does 一样。

  3. Response status

    HTTP 已经内置了一个很好的响应机制,它允许您利用架构中的先天能力,例如可缓存性和独立操作。虽然某些 Web 浏览器不能非常优雅地处理某些响应代码,但使用您的 API 的客户端应用程序可以使用它们来大大简化其内部代码。

干休息

使您的应用程序 RESTful 并同时保持 DRY 的最佳方法之一是尽可能利用控制器脚手架,因为 CRUD 对于所有域对象基本上都是相同的。 This article 让默认控制器更加 RESTful,this article 简化默认控制器都是从脚手架获得更多功能的重要资源。

高级 REST

一旦你达到了这一点,你就有了一个用于你的 grails 应用程序的非常实用的 REST API。您可以执行所有基本的 CRUD 操作,并且资源相当容易使用。

然而,真正的 RESTful 超媒体 API 阶梯的下一个层次要实现得多。解决这个问题是 Grails 的路线图,但目前它相当痛苦。这些部分是:

  1. 超媒体资源
  2. 内容类型
  3. 版本控制

谢天谢地,a plugin 让定义自定义编组器变得非常容易,这使我们能够相当轻松地解决剩下的三个 REST 难题。

最后,还有保护整个事物的方面。一般来说,Spring Security 会为您提供良好的保护,以确保用户访问您的 api。由于大多数 API 访问来自应用程序,并且用户不可见,因此基本或摘要式身份验证通常是最简单的方法。 一个基于 Spring Security 的OAuth plugin。我没有亲自使用它,所以我不能保证它的稳定性,但它对我来说看起来很不错。

总的来说,Grails 足够灵活和强大,可以非常非常好地执行 REST,但尚未完成使其开箱即用地执行 REST 的工作。

【讨论】:

  • 哇,我想,这涵盖了一切。非常感谢!
  • 我很乐意提供帮助。 Grails 是一个很棒的框架,而在我看来,REST 只是对 Web 上的事物有意义的唯一架构。如果您有更具体的问题或希望提供帮助并回馈社区,请随时访问 Freenode 上的#grails IRC 频道。
  • 对于刚开始调整的用户,Grails v2.3 将获得重大的 REST 提升,敬请关注更多详情!
  • Github 链接失效
【解决方案2】:

grails 文档在设置 RESTfull api 方面做得很好

http://grails.org/doc/latest/guide/webServices.html#13.1

【讨论】:

    【解决方案3】:

    无论如何你都可以映射它,使用任何 url 结构。 Grails UrlMapping 非常灵活,它只是映射到/$controller/$action 的默认行为,但您可以使用自己的映射,您可以手动事件映射每个 url,等等。

    请参阅 UrlMapping 文档 - http://grails.org/doc/latest/guide/theWebLayer.html#urlmappings

    【讨论】:

      【解决方案4】:
      • 网址映射:

        "/api/element/$version/$master" { 控制器 = “元素” 动作 = [GET:"show"] }

      这会将 http get 映射到控制器元素的 show 方法。

      • 即显示方法:

      DRY:api 可能与应用程序的逻辑相同。区别在于内容协商。

      ...
      
      def show = {
          def elements = elementService.findByMasterVersion(params.master, params.version)
          withFormat {
              xml {
                  render(status:200,text:elements as XML, contentType:"text/xml",encoding:"UTF-8")
              }
              json { ... }
              html { ... }
          }
      }
      
      • Oauth 实施起来非常复杂,而且在很多情况下似乎有点矫枉过正。

      【讨论】:

        猜你喜欢
        • 2020-11-08
        • 1970-01-01
        • 1970-01-01
        • 2010-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-09
        • 1970-01-01
        相关资源
        最近更新 更多