在 Grails 应用中使用 SpringBoot @ConfigurationProperties
Grails 3 应用是 Spring Boot 应用。了解如何通过 @ConfigurationProperties 将属性值绑定到结构化对象。
作者:Sergio del Amo
Grails 版本 3.3.8
1 培训
Grails 培训 - 由创建和积极维护 Grails 框架的人员开发和交付!。
2 入门
在本指南中,我们将创建一个通过下载包含书籍列表的 Excel 文件来演示 Grails 文件传输功能的应用。
2.1 您需要的信息
要完成本指南,您需要以下内容
-
一些时间
-
一个出色的文本编辑器或 IDE
-
JDK 1.8 或更高版本以及相应配置的
JAVA_HOME
2.2 解决方案
我们建议您按照下一部分中的说明逐步创建应用。但是,您可以直接转到完成的示例。
-
下载并解压源代码
或
-
克隆 Git 存储库:
git clone https://github.com/grails-guides/grails-configuration-properties.git
然后,进入下载/克隆的项目的根项目中的 complete
文件夹。
3 编写应用
grails create-app example.grails.complete --features=events,geb2,hibernate5
我们在使用包括 Geb 2 和 Gradle WebDriver Binaries 插件 的 geb2 功能。Geb 2 需要 JDK 1.8 或更高版本。 |
3.1 配置属性
在本部分中,我们将探讨如何通过 @ConfigurationProperties
将属性值绑定到结构化对象。
首先,我们需要用 @ComponentScan
注释 Application.groovy
。
package example.grails
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
import groovy.transform.CompileStatic
import org.springframework.context.annotation.ComponentScan
@CompileStatic
@ComponentScan (1)
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
}
}
1 | @ComponentScan 告诉 Spring 在指定包中查找其他组件、配置和服务。Spring 能够自动扫描、检测和注册预定义项目包中的 bean 或组件。如果没有指定包,则当前类包将作为根包。 |
创建一个名为 AddressConfiguration.groovy
的文件。
package example.grails
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration
import org.springframework.stereotype.Component
@Configuration (1)
@ConfigurationProperties(prefix = "address") (2)
class AddressConfiguration {
String street
String city
String country
}
1 | 我们添加了 @Configuration 注解,以便 Spring 能够找到此 bean 并将其设为注入候选对象。 |
2 | @ConfigurationProperties 注解采用配置前缀。 |
在属性文件中定义的任何具有前缀 address
并且与某个属性同名的属性都会自动分配给这个对象。
向 application.yml
添加一些属性。
address:
street: 221B Baker Street
city: London
country: United Kingdom
3.2 Tag Lib
创建一个 标签库 来呈现地址
package example.grails
class AddressTagLib {
static namespace = "app" (1)
AddressConfiguration addressConfiguration (2)
def address = { attrs, body ->
out << """\
<div class='adr'>
<div class='street-address'>${addressConfiguration.street}</div>
<span class='locality'>${addressConfiguration.city}</span>,
<div class='country-name'>${addressConfiguration.country}</div>
</div>""" (3)
}
}
1 | 默认情况下,标签会添加到默认的 Grails 名称空间中,并且在 GSP 页面中以 g: 前缀使用。但是,您可以通过向 TagLib 类添加静态属性来指定其他名称空间。 |
2 | 可以像对其他任何 bean 一样将 AddressConfiguration 注入到 TagLib 中。 |
3 | 创建一个有效的 adr 微格式 HTML 代码段。 |
3.3 单元测试
为 TagLib 创建一个单元测试
package example.grails
import grails.testing.web.taglib.TagLibUnitTest
import spock.lang.Specification
class AddressTagLibSpec extends Specification implements TagLibUnitTest<AddressTagLib> { (1)
Closure doWithSpring() {{ -> (2)
addressConfiguration(AddressConfiguration)
}}
void "test address tag"() {
when:
String returnString = tagLib.address().toString() (3)
then:
returnString == "<div class='adr'>\n <div class='street-address'>221B Baker Street</div>\n <span class='locality'>London</span>,\n <div class='country-name'>United Kingdom</div>\n</div>"
}
}
1 | 标签库和 GSP 页面可以使用 grails.testing.web.taglib.TagLibUnitTest 特性来进行测试。 |
2 | 要提供或替换上下午中的 bean,您可以在测试中覆盖 doWithSpring 方法。 |
3 | 向测试添加 TagLibUnitTest 特性会导致自动为测试的 TagLib 类创建一个新的 tagLib 字段。tagLib 属性可用于测试将标签调用为函数调用。 |
3.4 验收测试
编辑 grails-app/views/index.gsp
,即访问主页 /
和添加以下代码段时呈现的 GSP
...
<div id="content" role="main">
....
...
<app:address/>
</div>
...
现在可以使用 Geb 创建一个验收测试,以验证地址已呈现到主页上
package example.grails
import geb.spock.GebSpec
import grails.testing.mixin.integration.Integration
import spock.lang.IgnoreIf
@Integration
class AddressSpec extends GebSpec {
@IgnoreIf({ !sys['geb.env'] })
def "verify address is displayed in homepage"() {
when:
browser.go("/")
then:
browser.driver.pageSource.contains('221B Baker Street')
}
}
4 测试应用
运行测试
./grailsw
grails> test-app
grails> open test-report
或
./gradlew check
open build/reports/tests/index.html