Grails的好处:将转换器命名的配置与默认渲染器一起使用

有时,我们想在我们的RESTful API中在同一资源的输出中支持不同级别的详细信息。 例如,默认输出包含基本字段,而更详细的输出包含资源的所有字段。 然后,我们API的客户端可以选择是否需要默认或详细输出。 在Grails中实现此目的的方法之一是使用转换器命名的configuration。

Grails转换器(如JSONXML )支持命名配置。 首先,我们需要向转换器注册一个命名配置。 然后,我们可以use配置名称和带有语句的闭包来调用转换器的use方法以生成输出。 闭包中的代码在命名配置的上下文中执行。

Grails中的默认渲染器(例如DefaultJsonRenderer )具有名为namedConfiguration的属性。 如果将属性设置为在已配置的命名配置的上下文中呈现输出,则渲染器将使用命名的配置。 让我们配置适当的渲染器并注册命名配置,以支持默认渲染器中的命名配置。

在我们的示例中,我们有一个带有某些属性的User资源。 我们希望支持简短详细信息输出,其中在结果格式中包含不同的属性。

首先,我们有资源:

// File: grails-app/domain/com/mrhaki/grails/User.groovy
package com.mrhaki.grails

import grails.rest.*

// Set URI for resource to /users.
// The first format in formats is the default
// format. So we could use short if we wanted
// the short compact format as default for this 
// resources.
@Resource(uri = '/users', formats = ['json', 'short', 'details'])
class User {

    String username
    String lastname
    String firstname
    String email

    static constraints = {
        email email: true
        lastname nullable: true
        firstname nullable: true
    }

}

接下来,我们在Bootstrap为此资源注册两个命名配置:

// File: grails-app/conf/Bootstrap.groovy
class Bootstrap {

    def init = { servletContext ->
        ...
        JSON.createNamedConfig('details') {
            it.registerObjectMarshaller(User) { User user ->
                final String fullname = [user.firstname, user.lastname].join(' ')
                final userMap = [
                        id      : user.id,
                        username: user.username,
                        email   : user.email,
                ]
                if (fullname) {
                    userMap.fullname = fullname
                }
                userMap
            }
            // Add for other resources a marshaller within
            // named configuration.
        }

        JSON.createNamedConfig('short') {
            it.registerObjectMarshaller(User) { User user ->
                final userMap = [
                        id      : user.id,
                        username: user.username
                ]
                userMap
            }
            // Add for other resources a marshaller within
            // named configuration.
        }    
        ...
    }
...
}

现在,我们必须注册自定义渲染器User资源,如Spring组件resources

// File: grails-app/conf/spring/resources.groovy
import com.mrhaki.grails.User
import grails.rest.render.json.JsonRenderer
import org.codehaus.groovy.grails.web.mime.MimeType

beans = {
    // Register JSON renderer for User resource with detailed output.
    userDetailsRenderer(JsonRenderer, User) {
        // Grails will compare the name of the MimeType
        // to determine which renderer to use. So we 
        // use our own custom name here. 
        // The second argument, 'details', specifies the
        // supported extension. We can now use
        // the request parameter format=details to use
        // this renderer for the User resource.
        mimeTypes = [new MimeType('application/vnd.com.mrhaki.grails.details+json', 'details')]
        
        // Here we specify the named configuration
        // that must be used by an instance
        // of this renderer. See Bootstrap.groovy
        // for available registered named configuration.
        namedConfiguration = 'details'
    }

    // Register second JSON renderer for User resource with compact output.
    userShortRenderer(JsonRenderer, User) {
        mimeTypes = [new MimeType('application/vnd.com.mrhaki.grails.short+json', 'short')]

        // Named configuration is different for short
        // renderer compared to details renderer.
        namedConfiguration = 'short'
    }

    // Default JSON renderer as fallback.
    userRenderer(JsonRenderer, User) {
        mimeTypes = [new MimeType('application/json', 'json')]
    }

}

我们在grails-app/conf/spring/resources.groovy定义了一些新的mime类型,但我们还必须将它们添加到grails-app/conf/Config.groovy文件中:

// File: grails-app/conf/spring/resources.groovy
...
grails.mime.types = [
    ...
    short   : ['application/vnd.com.mrhaki.grails.short+json', 'application/json'],
    details : ['application/vnd.com.mrhaki.grails.details+json', 'application/json'],
]
...

现在我们的应用程序已准备就绪并已配置。 如果我们请求资源,我们主要依靠Grails内容协商来获取正确的渲染器以生成我们的输出。 Grails内容协商可以使用请求参数format的值来找到正确的mime类型,然后找到正确的渲染器。 Grails也可以检查Accept请求标头或URI扩展,但是对于我们的RESTful API,我们想使用format请求参数。

如果我们以不同的格式调用资源,则会看到以下结果:

$ curl -X GET http://localhost:8080/rest-sample/users/1
{
    "class": "com.mrhaki.grails.User",
    "id": 1,
    "email": "hubert@mrhaki.com",
    "firstname": "Hubert",
    "lastname": "Klein Ikkink",
    "username": "mrhaki"
}
$ curl -X GET http://localhost:8080/rest-sample/users/1?format=short
{
    "id": 1,
    "username": "mrhaki"
}
$ curl -X GET http://localhost:8080/rest-sample/users/1?format=details
{
    "id": 1,
    "username": "mrhaki",
    "email": "hubert@mrhaki.com",
    "fullname": "Hubert Klein Ikkink"
}

用Grails 2.4.2编写的代码。

翻译自: https://www.javacodegeeks.com/2014/07/grails-goodness-using-converter-named-configurations-with-default-renderers.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值