为什么我不能获得HAL支持在grails 2.3.8中工作?

RMo*_*sey 2 rest grails hateoas

我按照文档中的说明进行操作:

http://grails.org/doc/2.3.8/guide/webServices.html#hypermedia

为什么grails不会产生HAL格式的输出,如文档中所示?

我有一个域对象,我用@Resource注释映射:

@Resource(uri='/documentCatalogs', formats = ['json', 'xml'], readOnly = true)
class DocumentCatalog {
    String entityType
    String actionCode
    ...
}
Run Code Online (Sandbox Code Playgroud)

...在我的conf/spring/resources.groovy中,我配置了HAL JSON渲染器bean:

import com.cscinfo.platform.api.formslibrary.DocumentCatalog
import grails.rest.render.hal.HalJsonCollectionRenderer
import grails.rest.render.hal.HalJsonRenderer

// Place your Spring DSL code here
beans = {
    halDocumentCatalogRenderer(HalJsonRenderer, DocumentCatalog)
    halDocumentCatalogCollectionRenderer(HalJsonCollectionRenderer, DocumentCatalog)
}
Run Code Online (Sandbox Code Playgroud)

使用调试器,我确认调用了HalJsonRenderer上的initialize()方法,并使用正确的targetType构造它.

我使用邮递员发送休息电话:

http://localhost:8080/formslibrary/documentCatalogs/3
Accept application/hal+json
Run Code Online (Sandbox Code Playgroud)

我得到一个常规JSON的响应,并且不包含任何链接:

{
    "class": "com.cscinfo.platform.api.formslibrary.DocumentCatalog",
    "id": 3,
    "actionCode": "WITH",
    "entityType": "LLP",
...
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?是否有一些插件或配置设置我必须启用此行为?是否有某些额外的映射属性没有记录?

RMo*_*sey 7

弄清楚了!修复有多个方面......

我不得不在@Resource注释中添加"hal"作为列出的格式之一:

@Resource(uri='/documentCatalogs', formats = ['json', 'xml', 'hal'])
Run Code Online (Sandbox Code Playgroud)

调试器中的一些搜索显示Grails将Accept根据从客户端发送的UserAgent字符串轻率地忽略标头.(在我的情况下,因为我使用的是Postman,它是Google Chrome UA字符串.)

Accept标题问题的一种解决方法是在URL的末尾添加".hal":

http://localhost:8080/formslibrary/documentCatalogs/3.hal
Run Code Online (Sandbox Code Playgroud)

这不是一个非常好的解决方案IMO,因为渲染器生成的HAL URL默认情况下不以".hal"结尾.

更好的解决方案是通过更新配置来修复Grails对accept头的处理.在Config.groovy中,您会看到一行说:

grails.mime.disable.accept.header.userAgents = ['Gecko', 'WebKit', 'Presto', 'Trident']
Run Code Online (Sandbox Code Playgroud)

将其更改为:

grails.mime.disable.accept.header.userAgents = ['None']
Run Code Online (Sandbox Code Playgroud)

Accept无论用户代理如何,这都会强制Grails遵守标头.

希望这可以帮助那些遇到同样问题的人.

PS在ResponseMimeTypesApi#getMimeTypesFormatAware(...)方法中放置断点确实很有帮助.