Иногда мы хотим поддерживать в нашем RESTful API другой уровень детализации при выводе для одного и того же ресурса. Например, вывод по умолчанию с основными полями и более подробный вывод со всеми полями для ресурса. Затем клиент нашего API может выбрать, нужен ли вывод по умолчанию или подробный вывод. Один из способов реализовать это в Grails — использовать конвертер с именем конфигурации.
Преобразователи Grails, такие как JSON
и XML
, поддерживают именованные конфигурации. Сначала нам нужно зарегистрировать именованную конфигурацию в конвертере. Затем мы можем вызвать метод использования конвертера с именем конфигурации и закрытием с операторами для генерации вывода. Код в замыкании выполняется в контексте именованной конфигурации.
Средства визуализации по умолчанию в Grails, например DefaultJsonRenderer
, имеют свойство с namedConfiguration
. Средство визуализации будет использовать именованную конфигурацию, если свойство установлено для вывода выходных данных в контексте настроенной именованной конфигурации. Давайте настроим соответствующие средства визуализации и зарегистрируем именованные конфигурации для поддержки именованной конфигурации в средствах визуализации по умолчанию.
В нашем примере у нас есть User
ресурс с некоторыми свойствами. Мы хотим поддерживать короткие и подробные выходные данные, где различные свойства включены в результирующий формат.
Сначала у нас есть наш ресурс:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// 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
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// 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
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// 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' )] } } |
Мы определили несколько новых типов mime в grails-app/conf/spring/resources.groovy
, но мы также должны добавить их в наш файл grails-app/conf/Config.groovy
:
1
2
3
4
5
6
7
8
|
// 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
параметра запроса format
чтобы найти правильный тип MIME, а затем правильный рендерер. Grails также может проверить заголовок запроса Accept
или расширение URI, но для нашего RESTful API мы хотим использовать параметр запроса format
.
Если мы вызываем наш ресурс в разных форматах, мы видим следующие результаты:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
$ curl -X GET http: //localhost:8080/rest-sample/users/1 { "class" : "com.mrhaki.grails.User" , "id" : 1 , "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" , "fullname" : "Hubert Klein Ikkink" } |
Код, написанный с помощью Grails 2.4.2.
Ссылка: | Grails Good: использование именованных конфигураций конвертера с рендерами по умолчанию от нашего партнера JCG Хьюберта Иккинка в блоге JDriven . |