DevOps入门(三)自动化构建工具Gradle

参考:Gradle实战系列(一)__初体验

一、Gradle

Gradle是一个开源的项目自动化构建工具,建立在Apache Ant 和Apache Maven概念的基础上,并引入了基于Groovy的特定邻域语言(DSL),而不在使用XML形式管理构建脚本。

Groovy是用于Java虚拟机的一种敏捷的动态语言,他是一种成熟的面向对象的编程语言,既可以用于面向对象编程,也可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码,同时又具有闭包和动态语言的其他特性。
与Java相比较,Groovy完全兼容Java语法,分号是可选的,类和方法默认都是public,编译器给属性自动添加getter/setter方法,属性可以直接用点号获取,不再需要通过方法来获取,同时最后一个表达式的值会被作为返回值,==等同于equals(),不会有NullPointerException。
Groovy的高效特性中,自带了assert语句,它是弱类型的编程语言,直接通过def来定义类型;同时它的括号是可选的,字符串有多种写法。

Gradle有以下作用:      
    1、 按照约定声明构建和建设;
    2、 强大的支持多工程的构建;
    3、 强大的依赖管理(基于Apache ivy),提供强大的便利去构建工程;
    4、 权利支持已有的maven或者ivy仓库基础建设;
    5、 支持传递性依赖管理,在哪不需要远程仓库和pom.xml和ivy配置文件的前提下;
    6、 基于groovy脚本构建,其build脚本使用groovy语言编写;
    7、 具有广泛的领域模型支持构建;
    8、 深度API;
    9、  易迁移;

Mac上的Gradle安装如下:

$ brew update && brew install gradle

安装后可以使用如下命令验证安装:

gradle -v

二、Gradle的目录结构

Gradle相关的文件和目录结构如下:

Project-name
|--modules
    |--build.gradle
|--build.gradle
|--gradlew
|--setting.gradle

./builld.gradle 和 ./app/build.grade
gradle项目自动编译的时候要读取的配置文件。比如指定项目的依赖包等。
build.grade有两个,一个是全局的,一个是在模块里面。全局的build.grade主要设置的是声明仓库源gradle的版本号说明等。

buildscript {
    repositories {
        // 声明仓库源,比如我们构建了一个安卓的库,现在想要把库上传到jcenter中供别人一起使用,则可以上传到jcenter中
        // 具体上传步骤见:http://www.jcodecraeer.com/a/anzhuokaifa/Android_Studio/2015/0227/2502.html
        jcenter()
    }
    dependencies {
        // 说明gradle的版本号
        classpath 'com.android.tools.build:gradle:1.3.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

// 所有项目都继承这个配置
allprojects {
    repositories {
        mavenLocal()
        jcenter()
    }
}
在每个应用的根目录下的build.gradle文件中设置了模块的gradle构建配置,如下是一个工程项目的build.gradle文件:

import org.ajoberstar.grgit.* //提供一个Grgit实例,允许与Gradle项目所在的Git仓库交互

defineProperty("major", 2)
defineProperty("minor", 0)
defineProperty("buildNumber", "DEV")
defineProperty("type", "regression")
defineProperty("sourceMap", "true")

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'org.akhikhl.gretty:gretty:1.1.8',
                'gradle.plugin.com.tools.security:dependency-check:0.0.4',
                'org.ajoberstar:gradle-git:1.1.0',
                'gradle.plugin.com.palantir:jacoco-coverage:0.4.0'
    }
}

project(":") {

    repositories {
        mavenCentral()
        maven {
            url "http://[repalce with deliveryurl]"
        }
    }

    apply plugin: 'java'
    apply plugin: 'war'
    apply plugin: 'rpm'
    apply plugin: 'xwar'
    apply plugin: 'checkstyle'
    apply plugin: "jacoco"
    apply plugin: 'com.palantir.jacoco-coverage'
    apply plugin: 'idea'
    apply plugin: 'dependency.check'
    apply plugin: org.akhikhl.gretty.GrettyPlugin

    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    [compileJava, compileTestJava]*.options.collect { options ->
        options.encoding = 'UTF-8'
    }

    dependencies {
        compile("javax.servlet:javax.servlet-api:3.1.0",
                "org.eclipse.jetty:jetty-webapp:9.2.3.v20140905",
                "org.eclipse.jetty:jetty-servlets:9.2.3.v20140905",
                'org.eclipse.jetty:jetty-util:9.2.3.v20140905',
                'org.tuckey:urlrewritefilter:4.0.4',
                "com.github.jknack:handlebars.java:4.0.4",
                "com.github.jknack:handlebars-springmvc:4.0.4",
                'com.github.jknack:handlebars-guava-cache:4.0.4',
                "org.springframework:spring-web:4.2.4.RELEASE",
                "org.springframework:spring-webmvc:4.2.4.RELEASE",
                "org.springframework:spring-aop:4.2.4.RELEASE",
                'org.springframework:spring-context:4.2.4.RELEASE',
                'org.springframework:spring-context-support:4.2.4.RELEASE',
                ...)

        testCompile('junit:junit:4.10',
                'org.hamcrest:hamcrest-all:1.1',
                'org.mockito:mockito-all:1.9.5',
                "org.springframework:spring-test:4.1.2.RELEASE")

        compile('org.owasp.esapi:esapi:2.1.0') {
            force = true
            exclude group: 'commons-beanutils'
        }
    }
    jacoco {
        toolVersion = "0.7.6.201602180812"
        reportsDir = file("$buildDir/jacocoReportDir")
    }

    jacocoTestReport {
        reports {
            xml.enabled false
            csv.enabled false
            html.destination "${buildDir}/jacoco/coverage"
        }
        afterEvaluate {
            classDirectories = files(classDirectories.files.collect {
                fileTree(
                        dir: "${buildDir}/classes/main",
                        excludes: [
                                "com/[ProjectName]/web/HomeController.class",
                                "com/[ProjectName]/web/SearchController.class",
                                "com/[ProjectName]/web/MapViewController.class",
                                ...
                        ])
            })
        }
    }

    jacocoCoverage {
        packageThreshold 0.41, LINE, "com/[ProjectName]/ancillary"
        packageThreshold 0.42, METHOD, "com/[ProjectName]/ancillary"
        packageThreshold 0.57, CLASS, "com/[ProjectName]/ancillary"

        packageThreshold 0.36, LINE, "com/[ProjectName]/content"
        packageThreshold 0.34, METHOD, "com/[ProjectName]/content"
        packageThreshold 0.60, CLASS, "com/[ProjectName]/content"
        ...
    }

    test {
        useJUnit {
            includeCategories 'com.[ProjectName].junit.UnitTests'
        }
    }

    idea {
        module {
            inheritOutputDirs = false
            outputDir = file('out')
            testOutputDir = file('out')
        }
    }

    gretty {
        servletContainer = "jetty9"
        contextPath = ""
        httpPort = 8080
        host = "0.0.0.0"
        scanInterval = 1
        fastReload = true

        integrationTestTask = "prePush"
        onStart {

            if (env == "ci" || env == "test" || env == "dev") {
                systemProperty("spring.profiles.active", "internal")
            }

            systemProperty("app.env", System.getProperty('app.env', 'development'))
            systemProperty("feature-toggle.conf", new File("src/main/conf/${type}.china-site.properties").absolutePath)
            systemProperty("china-site.conf", project.getConfigFile())
            systemProperty("log4j.configuration", "file://" + project.file("src/main/conf/log4j.properties").absolutePath)
        }

        afterEvaluate {
            prepareInplaceWebAppClasses.dependsOn(['startAssetsPipelineServer', 'copyUrlRewriteConfig'])
            jettyBeforeIntegrationTest.dependsOn(['check', 'checkJs', 'integrationTest', "jacocoTestReport", 'processAssets', ":acceptance-tests:startOmnitureServer", "acceptance-tests:clearListingsInSolr"])
            jettyAfterIntegrationTest.dependsOn([":acceptance-tests:stopOmnitureServer", "stopAssetsPipelineServer"])
        }
    }
    task integrationTest(type: Test, description: "Integration Tests.", group: "verification") {

        doFirst {
            systemProperty("china-site.conf", project.getConfigFile())
        }

        useJUnit {
            includeCategories 'com.[ProjectName].junit.IntegrationTests'
        }
    }

    task npmInstall(type: Exec, description: "Install Node Dependencies.", group: "verification") {
        commandLine "npm"
        args "install"
    }

    task stopAssetsPipelineServer(type: Exec, description: "stop assets pipeline server",
            group: "asset-pipeline", dependsOn: ['npmInstall']) {

        commandLine "node_modules/tiny-asset-pipeline/bin/main"
        args "-stop"
        ignoreExitValue true
    }

    task rpm(type: Rpm, dependsOn: 'executableWar') {
        pkg = '[project-name]'
        summary = '[Project Name]'
        version = "${major}.${minor}.${buildNumber}"
        release = "1"
        user = 'user'
        group = 'usgrp'
        splunkIndex = '[project-name]'
        service '/opt/[project-name]/service'
        require 'java-1.8.0-openjdk'

        from('src/main/conf') {
            exclude '**/*.*.properties'
            include '**/*.properties'
            into "/opt/conf/[project-name]"
        }
    }

    processResources.doFirst {
        def versionFile = new File("src/main/resources/version.properties")
        versionFile.text = "app.version = ${major}.${minor}.${buildNumber}"
        versionFile.append(System.getProperty("line.separator"))
        versionFile.append("commit=" + Grgit.open(project.file('.')).head().id)
    }
    
    task checkJs(type: Exec, description: "check JavaScript use jshint and do unit tests.", group: "verification", dependsOn: ['npmInstall']) {
        commandLine "node_modules/grunt-cli/bin/grunt"
    }

    task compressImages(type: Exec, description: "compress images(*.png) use pngquant",
            group: "asset-pipeline", dependsOn: ['npmInstall']) {
        commandLine "node"
        args "node_modules/tiny-asset-pipeline/lib/tools/compressImg.js", "src/main/webapp/assets/images/"
    }

    gradle.taskGraph.whenReady { taskGraph ->
        if (taskGraph.hasTask(prePush) || taskGraph.hasTask(integrationTest)) {
            defineProperty('env', 'test')
        } else {
            defineProperty('env', 'dev')
        }
    }

    task wrapper(type: Wrapper) {
        gradleVersion = "2.0"
    }
}

String getConfigFile() {

    def configFile = new File("src/main/conf/${env}.china-site.properties")
    if (!configFile.exists()) {
        configFile.createNewFile()
    }

    return configFile.absolutePath
}


void defineProperty(prop, defaultValue) {
    if (!hasProperty(prop)) {
        project.ext.set(prop, defaultValue)
    }
}
配置分为很多部分,下面会详细介绍。

./gradle.properties
grade的运行环境配置,比如使用多少内存之类的。
./gradlew 和 ./gradlew.bat
自动完成 gradle 环境的脚本,在linux和mac下直接运行gradlew会自动完成gradle环境的搭建(这两个文件由gradle-wrapper创建)。
./local.properties
配置SDK或者NDK的环境路径,各个机器上这个变量可能都是不一样的,所以不应该进入版本库
./setting.gradle
整个项目的管理,比如这个项目包含哪些模块等。

rootProject.name = 'china-site'

include(':acceptance-tests')
project(':acceptance-tests').projectDir = new File(settingsDir, 'acceptance-tests')
./[Project-name].iml
iml是Intellij Idea的入口文件,可以使用Idea打开其工程。

三、Groovy

Groovy是一门jvm语言,它最终是要编译成class文件然后在jvm上执行,所以Java语言的特性Groovy都支持,我们完全可以混写Java和Groovy。既然如此,那Groovy的优势是什么呢?简单来说,Groovy提供了更加灵活简单的语法,大量的语法糖以及闭包特性可以让你用更少的代码来实现和Java同样的功能。比如解析xml文件,Groovy就非常方便,只需要几行代码就能搞定,而如果用Java则需要几十行代码。

3.1 Groovy的变量和方法声明

在Groovy中,通过 def 关键字来声明变量和方法,比如:

def a = 1;
def b = "hello world";
def int c = 1;

def hello() {
   println ("hello world");
   return 1;
}
在Groovy中,很多东西都是可以省略的,比如
  1. 语句后面的分号是可以省略的
  2. 变量的类型和方法的返回值也是可以省略的
  3. 方法调用时,括号也是可以省略的
  4. 甚至语句中的return都是可以省略的
所以上面的代码也可以写成如下形式:

def a = 1
def b = "hello world"
def int c = 1

def hello() {
   println "hello world" // 方法调用省略括号
   1;                    // 方法返回值省略return
}

def hello(String msg) {
   println (msg)
}

// 方法省略参数类型
int hello(msg) {
   println (msg)
   return 1
}

3.2 Groovy的数据类型

Groovy中,数据类型有:

  1. Java中的基本数据类型
  2. Java中的对象
  3. Closure(闭包)
  4. 加强的List、Map等集合类型
  5. 加强的File、Stream等IO类型
类型可以显示声明,也可以用 def 来声明,用 def 声明的类型Groovy将会进行类型推断。基本数据类型和对象这里不再多说,和Java中的一致,只不过在Gradle中,对象默认的修饰符为public。下面主要说下String、闭包、集合和IO等。
1. String
String的特色在于字符串的拼接,比如:

def a = 1
def b = "hello"
def c = "a=${a}, b=${b}"
println c

outputs:
a=1, b=hello
2. 闭包
Groovy中有一种特殊的类型,叫做Closure,翻译过来就是闭包,这是一种类似于C语言中函数指针的东西。闭包用起来非常方便,在Groovy中,闭包作为一种特殊的数据类型而存在,闭包可以作为方法的参数和返回值,也可以作为一个变量而存在。
{ parameters ->
   code
}
闭包可以有返回值和参数,当然也可以没有。下面是几个具体的例子:

def closure = { int a, String b ->
   println "a=${a}, b=${b}, I am a closure!"
}

// 这里省略了闭包的参数类型
def test = { a, b ->
   println "a=${a}, b=${b}, I am a closure!"
}

def ryg = { a, b ->
   a + b
}

closure(100, "renyugang")
test.call(100, 200)
def c = ryg(100,200)
println c
闭包可以当做函数一样使用,在上面的例子中,将会得到如下输出:
a=100, b=renyugang, I am a closure!
a=100, b=200, I am a closure!
300
3. List和Map

Groovy加强了Java中的集合类,比如List、Map、Set等。此处由于主要针对Gradle因此不多涉及。


4. IO

在Groovy中,文件访问要比Java简单的多,不管是普通文件还是xml文件。Object下提供了eachLine方法:

public Object eachLine(int firstLine, Closure closure)

因此可以写出代码如下

def file = new File("a.txt")
println "read file using two parameters"
file.eachLine { line, lineNo ->
   println "${lineNo} ${line}"
}

四、Gradle的编译和生命周期

在解析 Gradle 的编译过程之前我们需要理解在 Gradle 中非常重要的两个对象。Project和Task。每个项目的编译至少有一个 Project,一个 build.gradle就代表一个project,每个project里面包含了多个task,task 里面又包含很多action,action是一个代码块,里面包含了需要被执行的代码。
在编译过程中, Gradle 会根据 build 相关文件(一般是build.gradle),聚合所有的project和task,执行task 中的 action。因为 build.gradle文件中的task非常多,先执行哪个后执行那个需要一种逻辑来保证。这种逻辑就是依赖逻辑,几乎所有的Task 都需要依赖其他 task 来执行,没有被依赖的task 会首先被执行。所以到最后所有的 Task 会构成一个 有向无环图(DAG Directed Acyclic Graph)的数据结构。
编译过程分为三个阶段:

  1. 初始化阶段:创建 Project 对象,如果有多个build.gradle,也会创建多个project.
  2. 配置阶段:在这个阶段,会执行所有的编译脚本,同时还会创建project的所有的task,为后一个阶段做准备。
  3. 执行阶段:在这个阶段,gradle 会根据传入的参数决定如何执行这些task,真正action的执行代码就在这里.

五、Gradle初始化和参数配置

Gradle在项目中一般使用build.gradle和settings.gradle文件配置,创建build.gradle文件的过程如下:

1. gradle init

gradle init命令用于创建初始的build.gradle和setting.gradle文件,执行命令如下:

$ gradle-sample gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed
创建文件目录如下:


此时build.gradle和setting.gradle均为空,gradlew和gradlew.bat为Linux/Mac和Windows系统添加Gradle功能(使用方法为./gradlew [script])。

2. 配置外部引入库

在build.gradle中使用import命令可以引入外部依赖库,实例如下:

import org.gradle.api.tasks.Exec
import org.ajoberstar.grgit.*  /*提供一个Grgit实例,允许与Gradle项目所在的Git仓库交互*/
3. 配置依赖项目

在build.gradle中使用apply命令可以引入依赖项,示例如下:

    apply plugin: 'java'
    apply plugin: 'war'
    apply plugin: 'rpm'
    apply plugin: 'xwar'

    apply plugin: 'checkstyle'
    apply plugin: "jacoco"
    apply plugin: 'com.palantir.jacoco-coverage'
    apply plugin: 'idea'
    apply plugin: 'dependency.check'

gradle可用的plugins可以搜索:Search Gradle plugins

4. 设置maven仓库和外部依赖

在buildscript中的repositories中配置maven项目

buildscript {
    repositories {
        jcenter()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }

    dependencies {
        classpath 'com.reagroup.china:gradle-rpm-plugin:1.18',
                'com.reagroup.china:gradle-xwar-plugin:1.01',
                'org.akhikhl.gretty:gretty:1.1.8',
                'gradle.plugin.com.tools.security:dependency-check:0.0.4',
                'org.ajoberstar:gradle-git:1.1.0',
                'gradle.plugin.com.palantir:jacoco-coverage:0.4.0'
    }
}

也可以使用类似如下dependencies配置:

dependencies {
        compile("javax.servlet:javax.servlet-api:3.1.0",
                "org.eclipse.jetty:jetty-webapp:9.2.3.v20140905",
                "org.eclipse.jetty:jetty-servlets:9.2.3.v20140905",
                'org.eclipse.jetty:jetty-util:9.2.3.v20140905',

                'org.tuckey:urlrewritefilter:4.0.4',

                "com.github.jknack:handlebars.java:4.0.4",
                "com.github.jknack:handlebars-springmvc:4.0.4",
                'com.github.jknack:handlebars-guava-cache:4.0.4',
                "org.springframework:spring-web:4.2.4.RELEASE",
                "org.springframework:spring-webmvc:4.2.4.RELEASE",
                "org.springframework:spring-aop:4.2.4.RELEASE",
                'org.springframework:spring-context:4.2.4.RELEASE',
                'org.springframework:spring-context-support:4.2.4.RELEASE')
}


repositories中还可以配置本地仓库和maven默认的中心仓库:

mavenLocal
mavenCentral
此外如果url指定的仓库需要配置密码,也可使用
    maven {
        url "<you_company_resp_url>"
        credentials {
            username 'your_username'
            password 'your_password'
        }
    }
Gradle还可以使用本地静态仓库,代码如下:

repositories{
    flatDir{
      dirs './static_repo'
    }
}

此时在dependencies中的应用方式为:

dependencies{
  compile(name:'libraryname', ext:'./static_repo')
}


5. 配置变量

Gradle使用defineProperty函数指定变量:

defineProperty("major", 2)
defineProperty("minor", 0)
defineProperty("buildNumber", "DEV")
defineProperty("s3StaticAssets", "myfun.com.assets")
defineProperty("awsRegion", "cn-north-1")
defineProperty("s3Bucket", "myfun.stg.com.dist")
defineProperty("type", "regression")
defineProperty("sourceMap", "true")
此处定义的变量可以在后续的task中使用。
6. 配置JDK版本

sourceCompatibility = 1.8
targetCompatibility = 1.8
基本配置如上,除了如上的基本配置之外,gradle中还包括一些高级配置,以下将举例说明。

五、Gradle配置Git

Grgit是Andrew Oberstar实现的JGit封装器,为基于Groovy的工具与Git仓库交互提供了更简洁流畅的API。

  • org.ajoberstar.grgit - 提供一个Grgit实例,允许与Gradle项目所在的Git仓库交互
  • org.ajoberstar.github-pages - 向Github仓库的gh-pages分支发布文件
  • org.ajoberstar.release-base - 提供用于从项目状态和所在Git仓库推断当前项目版本和创建新版本的通用结构
  • org.ajoberstar.release-opinion - 用于org.ajoberstar.release-base的默认选项,遵从语义版本控制(Semantic Versioning)
下面是一个Gradle任务示例,用于从Git仓库克隆项目。

task cloneGitRepo(type: GitClone) {
  def destination = file("destination_folder")
  uri = "your_git_repo_uri"
  destinationPath = destination
  bare = false
  enabled = !destination.exists() //to clone only once
}

六、Gradle配置test

JUnit和TestNG允许复杂的测试方法分组。对于分组,JUnit有测试类和方法。JUnit 4.8引入了类别的概念。测试任务允许指定要包括或排除的JUnit类别。可以使用build.gradle文件中的以下代码段对测试方法进行分组。如下代码所示:

test {
   useJUnit {
      includeCategories 'org.gradle.junit.CategoryA'
      excludeCategories 'org.gradle.junit.CategoryB'
   }
}
Test类有一个include和exclude方法。这些方法可以用于指定哪些测试应该运行。
只运行包含的测试 -
test {
   include '**my.package.name/*'
}
以下代码中所示的build.gradle示例文件显示了不同的配置选项。

apply plugin: 'java' // adds 'test' task

test {
   // enable TestNG support (default is JUnit)
   useTestNG()

   // set a system property for the test JVM(s)
   systemProperty 'some.prop', 'value'

   // explicitly include or exclude tests
   include 'org/foo/**'
   exclude 'org/boo/**'

   // show standard out and standard error of the test JVM(s) on the console
   testLogging.showStandardStreams = true

   // set heap size for the test JVM(s)
   minHeapSize = "64m"
   maxHeapSize = "512m"

   // set JVM arguments for the test JVM(s)
   jvmArgs '-XX:MaxPermSize=256m'

   // listen to events in the test execution lifecycle
   beforeTest { 
      descriptor → logger.lifecycle("Running test: " + descriptor)
   }

   // listen to standard out and standard error of the test JVM(s)
   onOutput { 
      descriptor, event → logger.lifecycle
         ("Test: " + descriptor + " produced standard out/err: " 
         + event.message )
   }
}
使用方法如下:

gradle <someTestTask> --debug-jvm

七、Gradle配置wrapper

想使用gradle wrapper,首先要在你的项目中创建。具体来说就是在build.gradle里面加入类似于下面的task:

task wrapper(type: Wrapper) {
        gradleVersion = "2.0"
}
然后使用

gradle createWrapper  
即可生成如下目录结构:
Project-name/  
  gradlew  
  gradlew.bat  
  gradle/wrapper/  
    gradle-wrapper.jar  
    gradle-wrapper.properties  

需要使用gradle wrapper的时候,我们就直接在项目根目录下直接执行./gradlew(gradle wrapper的简写), 使用gradlew的方式和gradle一模一样, 例如通过./gradlew tasks来查看所有的任务。事实上,执行gradlew命令的时候,gradlew会委托gradle命令来做相应的事情,所以gradlew只是一个壳而已。

八、Gradle配置Task

任务(Task)是用于将任务定义到构建脚本中的关键字。看看下面的例子,它是一个叫作 hello 的任务,将打印一个字符串:hello world。将以下脚本复制并保存到 build.gradle 文件中。 此构建脚本定义一个名称为 “hello” 的任务,用于打印hello world字符串。

task hello {
   doLast {
      println 'hello world'
   }
}
可以通过为 doLast 语句指定快捷方式(表示符号 <<)来简化此 hello 任务。如果添加这个快捷方式到上面的 hello 任务中,参考如下脚本。

task hello << {
   println 'hello world'
}
任务依赖关系
task hello << {
    println 'Hello world!'
}
task intro(dependsOn: hello) << {
    println "I'm Gradle"
}

九、Gradle配置Jetty

gretty支持热部署、HTTPS、转发、调试、自动化运行环境等诸多特性,让开发和部署变得更加简单。

gretty {
        servletContainer = "jetty9"
        contextPath = ""
        httpPort = 8080
        host = "0.0.0.0"
        scanInterval = 1
        fastReload = true

        integrationTestTask = "prePush"
        onStart {

            if (env == "ci" || env == "test" || env == "dev") {
                systemProperty("spring.profiles.active", "internal")
            }

            systemProperty("app.env", System.getProperty('app.env', 'development'))
            systemProperty("feature-toggle.conf", new File("src/main/conf/${type}.china-site.properties").absolutePath)
            systemProperty("china-site.conf", project.getConfigFile())
            systemProperty("log4j.configuration", "file://" + project.file("src/main/conf/log4j.properties").absolutePath)
        }

        afterEvaluate {
            prepareInplaceWebAppClasses.dependsOn(['startAssetsPipelineServer', 'copyUrlRewriteConfig'])
            jettyBeforeIntegrationTest.dependsOn(['check', 'checkJs', 'integrationTest', "jacocoTestReport", 'processAssets', ":acceptance-tests:startOmnitureServer", "acceptance-tests:clearListingsInSolr"])
            jettyAfterIntegrationTest.dependsOn([":acceptance-tests:stopOmnitureServer", "stopAssetsPipelineServer"])
        }
    }
常用属性
  1. scanInterval:监视周期,单位为秒,设置为0等于完全关闭热部署
  2. scanDir:需要监视的文件夹
  3. recompileOnSourceChange:监视源码变动,自动编译
  4. reloadOnClassChange:编译的类发生改变,自动加载
  5. reloadOnConfigChange:WEB-INF或META-INF发生改变
  6. reloadOnLibChange:依赖发生改变
  7. fastReload属性,默认为true,监听webapp/中的内容,文件发生改变,无需重启。

展开阅读全文

没有更多推荐了,返回首页