【问题标题】:How to use scaffolding and RESTfulness together in Grails 2.3如何在 Grails 2.3 中同时使用脚手架和 RESTful
【发布时间】:2013-10-28 05:27:35
【问题描述】:

Grails 官方文档说

2.0.x 版本的脚手架插件包含不同的脚手架 与 Grails 中引入的新 REST API 一致的模板 2.3及以上。 (取自这里http://grails.org/doc/latest/guide/scaffolding.html

但我不能(或者我不理解这个概念)将 RESTful 与脚手架一起工作。

让我们从头开始:

grails create-app myapp
cd myapp/
grails create-domain-class Book
grails create-scaffold-controller myapp.Book

在域类中添加一个字段

class Book {
    String text

    static constraints = {
    }
}

并使用grails run-app 运行应用程序。 在http://localhost:8080/myapp/ 上冲浪表明脚手架效果很好:

  • http://localhost:8080/myapp/book/index页面显示图书列表
  • http://localhost:8080/myapp/book/show/1 页面显示 id = 1 的图书的详细信息
  • http://localhost:8080/myapp/book/create page 创建一本书
  • 等等,好旧的脚手架。

让我们看看 REST 怎么样。 官方文档说我应该为 REST 使用像 http://localhost:8080/myapp/books/... 这样的 URL,但是任何访问应用程序的尝试,比如 curl -i -H "Accept: application/json" localhost:8080/myapp/books/1 都会返回 404 和一堆 HTML。

好的,让我们仔细阅读文档:

在 Grails 中创建 RESTful API 的最简单方法是公开一个 域类作为 REST 资源。这可以通过添加 grails.rest.Resource 转换为任何领域类

没问题,现在 Book 类的标题是

import grails.rest.*

@Resource(uri='/books') class Book {

现在在http://localhost:8080/myapp/上冲浪显示脚手架坏了:

  • http://localhost:8080/myapp/book/index页面显示图书列表
  • http://localhost:8080/myapp/book/create 页面显示 xml 输出 <?xml version="1.0" encoding="UTF-8"?><book><text /></book>
  • 等等,糟糕的新 xml 输出。

我在 URLMappings.groovy 中使用过 @Resource"/books"(resources:"book") 但没有找到任何可行的解决方案可能的脚手架和 RESTfulness 背靠背工作。事实上,我设法让它们分开工作。

更新

我找到了实现预期目标的方法。我找到的方法是:

  1. @Resource(uri = "/books")标记Book类。
  2. 删除脚手架控制器BookController
  3. 为书创建带有脚手架的专用控制器:class HumanBookController {static scaffold = Book}

现在,带有http://localhost:8080/myapp/humanBook/index 之类的 URL 的基架 GUI 页面可以很好地工作。使用http://localhost:8080/myapp/books/1 之类的 URL 可以很好地处理 json 请求。但是让 2 个控制器为普通的 web 和 json 做同样的事情并不优雅。

【问题讨论】:

  • 尝试将 "/books"(resources:"book") 添加到您的域中的 urlmapping.groovy 中,而不是 @Resource 看看是否有帮助,您可以使用 url-mappings-report 查看哪些服务被公开。
  • Alidad,我试过了 - 但它不起作用(返回 404 表示有效请求)。我猜,只有@Resource 在运行时生成所需的控制器。此外,文档说 UrlMapping 中的 RESTy URL 映射应与 @Resource 结合使用 - 它只是定义具有一些附加(如嵌套资源)功能的映射的另一个地方。
  • 我目前(使用 2.4.0)有同样的问题,就像映射都是错误的。 :(
  • 该解决方案不适用于 2.4.4。如果我从控制器中删除静态脚手架 = true,则 REST URL 仍然给出 404。基本上,@Resource 似乎什么都不做。
  • 根据 evanwong 下面的帖子,这在 2.4.4 中对我有用,但在域类中没有 @Resource 但在 UrlMappings.groovy 中:“/books”(资源:“Book” )。我有 REST 和脚手架屏幕根据需要一起工作。还要非常感谢 Alidad 提供有关 grails url-mappings-report 命令的提示。

标签: rest grails scaffolding


【解决方案1】:

你可以这样做:

import grails.rest.RestfulController

class BookController extends RestfulController {

    static responseFormats = ['html', 'json']

    BookController() {
        super(Book)
    }
}

然后在 UrlMappings.groovy 中:

 "/books"(resources:"book")
 "/$controller/$action?/$id?(.${format})?"{
    constraints {
        // apply constraints here
    }
  }

无需在域中添加@Resource。 您现在可以让 /books/1.json 或 /books/1.html 指向正确的位置。您可能仍需要执行grails generate-view Book 才能生成视图。但是虽然您需要为 html 生成视图,但您只保留单个控制器和路径。

【讨论】:

  • evanwong,看起来您的解决方案确实有效。我在我的 Grails 2.3.1 上检查了它:1. 是的,我必须为这本书生成视图,2. 我对使用 responseFormats 有一些担忧,因为我认为它会破坏漂亮的 url(需要 ". html" 用于人类 url),但似乎常规 url(没有 ".html")工作得很好。我同意你的观点,拥有 1 个控制器和生成的脚手架视图(你的解决方案)比拥有 2 个控制器(我的)要好,但这仍然不是 Grails 文档所承诺的。
【解决方案2】:

我遇到了和你一样的问题。 这可能是一个微不足道的解决方案,并非适用于所有情况,但请尝试更新您的 Grails 版本。 至于我:Grails 2.3.4 -> Grails 2.3.6 有效。 希望对大家有所帮助。

【讨论】:

  • 我正在使用 grails 2.4.4 并且有同样的问题。
【解决方案3】:

我目前正在使用 Grails 2.4.0,解决方案是这样做的:

  • 控制器: BookController { 静态脚手架 = true }
  • 域: Book { .... } // 没有@Resource

结果是你可以:

  • /book.json 获取 JSON 化列表
  • /book/index 获取 HTML 标准脚手架
  • /book/为新项目创建 html 脚手架
  • /book/show/1 html脚手架编辑项目1
  • /book/show/1.json 项目 ID 的 JSON:1

我很邪恶,我知道。我找到了this,它让我继续前进。

【讨论】:

    【解决方案4】:

    使用 Grails 2.4.4,我能够使用以下步骤使脚手架与单个控制器一起工作:

    1. 在 UrlMappings.groovy 中添加了指向资源映射的 URL,例如"/books"(resources:"book")
    2. static scaffold = true 插入到生成的控制器中

    我确实没有验证以下是否有所不同,但我还在 Config.groovy 中设置了grails.mime.disable.accept.header.userAgents = []grails.mime.use.accept.header = true(后者大概是新的默认值)。

    脚手架的 REST 和 UI 界面都可以通过以下测试正常工作:

    • GET /app//1(传递 Accept 标头)
    • GET /app//1.json(无 Accept 标头)
    • POST /app/(使用 json 或表单编码的有效负载)
    • 删除 /app//1
    • PUT /app//1(带有 json 有效负载。表单有效负载更新了对象,但发回了 302 重定向)

    编辑

    1. 删除了资源注释步骤并阐明了 URL 映射设置
    2. 在 URL 映射中分配的 URI与控制器的默认 URI 相同。例如,“书”而不是“书”。添加此映射后,控制器的 URI 将默认为 UrlMapping 中的 URI,但原始 URI 将继续工作。

    【讨论】:

      【解决方案5】:

      生成的控制器是一个 Restful 控制器,因为它实现了可感知以下请求的操作:

      curl -i -X GET yourDomain:8080/yourApp/books.json
      

      它以 json 格式返回书籍列表。 (10 本书,假设您创建了测试数据,是吗?)

      您可以附加一个参数,如:

      curl -i -X GET yourDomain:8080/yourApp/books.xml?40
      

      默认情况下,您将获得html 格式。您需要附加.json.xml 以获取正确的数据。

      您也可以使用Accept 标头

      curl -i -X GET -H "Accept: application/xml" yourDomain/books/1
      

      以 xml 格式返回 id=1 的书的详细信息。终于

      curl -i -X POST -H "Content-Type: application/json" -d "{name: 'Book'}" yourDomain/books
      

      创建一本新书并

      curl -i -X PUT -H "Content-Type: application/json" -d "{name: 'Book'}" yourDomain/books/1
      

      更新 id=1 的书名

      所有资源都需要通过 url 公开。 url不是为你生成的,你应该写在UrlMappings文件上:

      "/v1/books"(resources: "book")
      

      第一个字符串 "/v1/books" 是 uri,第二个字符串 "book" 是遵循 grails 约定的控制器名称。 (前面的v1 字符串是因为我总是将版本号放在我的 API URI 中)

       | GET    | /v1/books            | Action: index  |
       | GET    | /v1/books/create     | Action: create |
       | POST   | /v1/books            | Action: save   |
       | GET    | /v1/books/${id}      | Action: show   |
       | GET    | /v1/books/${id}/edit | Action: edit   |
       | PUT    | /v1/books/${id}      | Action: update |
       | DELETE | /v1/books/${id}      | Action: delete |
      

      【讨论】:

      • 您指的是“生成的”控制器。这可以用一个“脚手架”控制器来完成吗?
      • AA.,非常抱歉回复延迟。我刚刚测试了您提出的建议,但它在我这边不起作用:curl -i -X GET localhost:8080/myapp/books.json 导致HTTP/1.1 404 Not Found 带有一堆 HTML。 curl -i -X GET -H "Accept: application/xml" localhost:8080/books/1 带来简单的 404 响应。
      • 根据 2.3.4 文档,所需要的只是将带有 uri 映射的 @Resource 添加到域类。这应该生成控制器并执行所有 URL 映射。到目前为止,我无法使用该方法使其工作。 grails.org/doc/latest/guide/webServices.html
      • 我也有同样的问题。 @Resource 根本不起作用(为任何记录的调用获取 404,即上述 URL 示例都不起作用)
      【解决方案6】:

      只需要@Resource 注释和域类上的uri。如果你想要特定的格式(默认格式是第一个),还包括格式:

      @Resource(uri='/books', formats=['json', 'xml'])
      

      应该是这样的。如果 ypu 仍然无法找到您的动态 @Resource 端点,请尝试运行:

      grails url-mappings-report
      

      这将为您提供所有 url 的一个很好的摘要,包括由 @Resource 域的脚手架控制器支持的那些。我发现在尝试“猜测” URL 时,我往往会犯一些愚蠢的错误——使用报告输出可确保您和 grails 达成一致。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-11
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 2015-01-19
        相关资源
        最近更新 更多