简述Gradle在大型Java项目上的应用---环境的配置(二)

2. 环境的配置

为了方便地将应用部署到开发、测试以及产品等不同环境上, Gradle提供了几种不同的方式为不同的环境打包,使得不同的环境可以使用不同的配置文件。此外,它还提供了简单的方法,使得我们能够便捷地初始化数据库 。

2.1 Properties配置

要为不同的环境提供不一样的配置信息,Maven选择使用profile,而Gradle则提供了两种方法为构建脚本提供Properties配置:

第一种方式是使用传统的properties文件, 然后在使用Gradle时,通过传入不同的参数加载不同的properties文件。例如,我们可以在项目中提供development.properties、test.properties和production.properties。在项目运行时,使用-Pprofile=development来指定加载开发环境的配置。构建脚本中加载properties文件的代码如下:

ext {
    profile = project['profile']
}
def loadProperties(){
    def props = new Properties()
    new File("${rootProject.projectDir}/config/${profile}.properties")
            .withInputStream {
                stream -> props.load(stream)
            }
    props
}

在运行脚本的时候,传入的-Pprofile=development可以指定使用哪个运行环境的配置文件。代码中使用了project['profile']从命令行里读取-P传入的参数,Gradle会去父项目根目录下的config文件夹中需找对应的properties文件。

另外一种方式就是使用Groovy的语法,定义可读性更高的配置文件。比如可以在项目中定义config.groovy的配置文件,内容如下:

environments {
    development {
        jdbc {
            url = 'development'
            user = 'xxxx'
            password = 'xxxx'
        }
    }
 
    test {
        jdbc {
            url = 'test'
            user = 'xxxx'
            password = 'xxxx'
        }
    }
 
    production {
        jdbc {
            url = 'production'
            user = 'xxxx'
            password = 'xxxx'
        }
    }
}

这里定义了三个环境下的不同数据库配置,在构建脚本中使用如下的代码来加载:

ext {
    profile = project['profile']
}
 
def loadGroovy(){
    def configFile = file('config.groovy')
    new ConfigSlurper(profile).parse(configFile.toURL()).toProperties()
}

这里在ConfigSlurper的构造函数里传入从命令行里取到的-P的参数。调用loadGroovy方法就可以加载项目根目录下的config.groovy文件,并作为一个Map返回,这样就可以通过jdbc.url来获取url的值。

从可读性以及代码整洁(配置文件也需要代码整洁)而言,我推荐使用第二种方式来配置,因为这种方法具有清晰的结构。如上面的例子,就可以把数据库相关的信息都放在jdbc这个大的节点下,而不用像properties文件这样的扁平结构。但是对于一些已经使用properties文件来为不同环境提供配置信息的遗留项目里,使用properties文件也没有问题。

2.2 替换

通过不同的方式加载不同环境的配置后,就需要把它们替换到有占位符的配置文件中去。在配置文件中使用@key@来标注要被替换的位置,比如在config文件夹中有jdbc.properties文件,其内容如下:

jdbc.url=@jdbc.url@
jdbc.user=@jdbc.user@
jdbc.password=@jdbc.password@

在Gradle构建过程中,有一个processResources的Task,可以修改该Task的配置,让其在构建过程中替换资源文件中的占位符:

processResources {
    from(sourceSets.main.resources.srcDirs) {
        filter(org.apache.tools.ant.filters.ReplaceTokens,
                		tokens: loadGroovyConfig()
)
    }
}

上面这种做法用来处理子项目src/main/resources文件夹下的资源文件,所以需要将这段代码放在子项目的独立配置文件里。

在一些复杂的项目中,经常会把配置文件放置到一个目录进行统一管理。比如在我所在的项目,就专门提供了一个config子目录,里面存放了所有的配置信息。在处理这些资源文件时, Gradle默认提供的processResources就不够用了,我们需要在Gradle脚本中定义一个Task去替换这些包含占位符的配置文件,然后让package或者deploy的Task依赖这个Task。该Task的代码如下:

task replace(type: Sync) {
            def configHome = "${project.rootDir}/config"
 
    from(configHome) {
        include '**/*.properties'
        include '**/*.xml'
        filter org.apache.tools.ant.filters.ReplaceTokens, 
tokens: loadGroovyConfig()
    }
    into "${buildDir}/resources/main"
}

这里定义了一个Sync类型的Task,会将父项目的根目录下的config文件夹的所有properties和xml文件使用从loadGroovyConfig()方法中加载出来的配置替换,并将替换之后的文件放到build文件夹下的resource/main目录中。再让打包的Task依赖这个Task,就会把替换之后的配置文件打到包中。

2.3 更复杂的情况

上面介绍了在项目中如何使用Gradle处理 properties和xml文件中具有相同配置,但其中的一些值并不相同的情况 。然而,在有些项目中不同的环境配置之间变化的不仅是值,很有可能整个配置文件都不相同;那么,使用上面替换的处理方式就无法满足要求了。

在我所在的项目中,我们需要依赖一个外部的Web Service。在开发环境上,我们使用了Stub来模拟和Web Service之间的交互,为开发环境提供测试数据,这些数据都放置在一个Spring的配置文件中;而在测试和产品环境上,又要使用对应的测试和产品环境的Web Service。这时,开发、测试与产品环境的配置完全不同。对于这种复杂的情况,Gradle可以在构建过程中为不同的环境指定不同的资源文件夹,在不同的资源文件夹中包含不同的配置文件。

例如,在我们项目的config目录下包含了application文件夹,定义了不同环境所需的不同配置文件,其目录结构如下图所示:

 

在构建脚本中,根据从命令行读入的-P参数,使用不同的资源文件夹,其代码如下:

sourceSets {
    main {
        resources {
            srcDir "config/application/spring/${profile}", 
                        "config/application/properties/${profile}"
        }
    }
}

这样在打包的过程中,就可以使用-P传入的参数的资源文件夹下面的properties和xml文件作为项目的配置文件。

2.4 初始化数据库

在项目开发过程中,为了方便为不同环境构建相同的数据库及数据,我们通常需创建数据库的表以及插入一些初始化数据。Gradle目前没有提供相关的Task或者Plugin,但是我们可以自己创建Task去运行SQL来初始化各个环境上的数据库。

前面也提到Gradle是Groovy定义的DSL,所以我们可以在Gradle中使用Groovy的代码来执行SQL脚本文件。在Gradle脚本中,使用Groovy加载数据库的Driver之后,就可以使用Groovy提供的Sql类去执行SQL来初始化数据库了。代码如下:

groovy.sql.Sql oracleSql = 
	Sql.newInstance(props.getProperty('database.connection.url'),
                props.getProperty('database.userid'),
                props.getProperty('database.password'),
                props.getProperty('database.connection.driver'))
 
try {
        new File(script).text.split(";").each {
            logger.info it
            oracleSql.execute(it)
        }
    } catch (Exception e) { }

这段代码会初始化执行SQL的groovy.sql.Sql对象,然后按照分号(;)分割SQL脚本文件里的每一条SQL并执行。对于一些必须运行成功的SQL文件,可以在catch块里通过抛出异常来中止数据库的初始化。需要注意的是需要将数据库的Driver加载到ClassPath里才可以正确地执行。

因为在Gradle中包含了Ant,所以我们除了使用Groovy提供的API来执行SQL之外,还可以使用Ant的sql任务来执行SQL脚本文件。但若非特殊情况,我并不推荐使用Ant任务,这部分内容与本文无关,这里不再细述 。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值