Статьи

Grails Good: привязка пользовательских данных с аннотацией @DataBinding

У Grails есть механизм привязки данных, который преобразует параметры запроса в свойства объекта разных типов. Мы можем настроить привязку данных по умолчанию различными способами. Один из них использует аннотацию @DataBinding . Мы используем замыкание в качестве аргумента для аннотации, в которой мы должны вернуть преобразованное значение. Мы получаем два аргумента: первый — это объект, к SimpleMapDataBindingSource применяется привязка данных, а второй — источник со всеми исходными значениями типа SimpleMapDataBindingSource . Источником может быть, например, структура типа карты или параметры объекта запроса.

В следующем примере кода у нас есть класс Product с классом ProductId . Мы пишем пользовательскую привязку данных для преобразования значения String с шаблоном {code}-{identifier} в объект ProductId :

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
package mrhaki.grails.binding
 
import grails.databinding.BindUsing
 
class Product {
 
    // Use custom data binding with @BindUsing annotation.
    @BindUsing({ product, source ->
 
        // Source parameter contains the original values.
        final String productId = source['productId']
 
        // ID format is like {code}-{identifier},
        // eg. TOYS-067e6162.
        final productIdParts = productId.split('-')
 
        // Closure must return the actual for
        // the property.
        new ProductId(
            code: productIdParts[0],
            identifier: productIdParts[1])
 
    })
    ProductId productId
 
    String name
 
}
 
// Class for product identifier.
class ProductId {
    String code
    String identifier
}

Следующая спецификация показывает привязку данных в действии:

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
40
package mrhaki.grails.binding
 
import grails.test.mixin.TestMixin
import grails.test.mixin.support.GrailsUnitTestMixin
import spock.lang.Specification
import grails.databinding.SimpleMapDataBindingSource
 
@TestMixin(GrailsUnitTestMixin)
class ProductSpec extends Specification {
 
    def dataBinder
 
    def setup() {
        // Use Grails data binding
        dataBinder = applicationContext.getBean('grailsWebDataBinder')
    }
 
    void "productId parameter should be converted to a valid ProductId object"() {
        given:
        final Product product = new Product()
 
        and:
        final SimpleMapDataBindingSource source =
            [productId: 'OFFCSPC-103910ab24', name: 'Swingline Stapler']
 
        when:
        dataBinder.bind(product, source)
 
        then:
        with(product) {
            name == 'Swingline Stapler'
 
            with(productId) {
                identifier == '103910ab24'
                code == 'OFFCSPC'
            }
        }
    }
 
}

Если бы у нас был контроллер с параметрами запроса productId=OFFCSPC-103910ab24&name=Swingline%20Stapler привязка данных Grails может создать экземпляр Product и установить свойства с правильными значениями.

Написано с Grails 2.5.0 и 3.0.1.