公共脚本

公共脚本

Gradle中公共脚本抽取与共享

要解决冗余代码和通用配置的问题,最简单的做法就是抽取出共同部分,作为其它所有项目的parent/common项目。

使用git submodule

将所有系统中公共的类库和通用的配置,放到独立的仓库Common中。因为我们用git来管理代码,而git本身提倡多branch,多仓库,所以采用git submodule方式,其它项目需要添加Common这个submodule

git submodule add yourGitRepo deps/Common

最后的”deps/Common”是自定义的,意思就是在当前的deps目录下用Common名字来当作submoduleclone

如果你clone别的带有submodule的项目时,默认情况下,当前的project并不会把submodule的代码都clone下来,可以执行:

git submodule foreach git pull

以下这段一般大家经常会遇到:当你clone项目时,submodule会以最新的master分支上的commit id作为本次的tag下载,类似一个副本,因为一般大家都是用submodule,而不是修改它。所以当你的submodule需要更新的时候,需要先执行这段代码:

git submodule foreach git checkout master

submodule切换到master分支了,然后就可以用上面的submodule pull来更新了。

Gradle构建

鉴于上文对gradle优点的描述,我们采用gradle来构建。我们的项目最初都是基于maven来构建的,从maven切换到gradle很简单,在项目根目录下,先执行(假设你的机器已经安装了gradle环境,一般负责构建的人首次需要安装,开发人员可以不安装

gradle init wrapper

这样,就会自动生成相关的gradlew,build.gradle,settings.gradle等文件和相关目录,并会自动下载对应版本的gradle binary包(所以以后不需要安装Gradle会自动识别Maven里的配置,并相应的导入进来,有少量部分配置可能需要修改。

注:在已有的gradle项目里,尽量使用生成的gradlew这个wrapper,因为它会自动下载对应版本的Gradle,也就是说团队合作的其他人开发机上是不需要手动安装Gradle的,并且wrapper也让大家的Gradle版本一致,避免问题。

Gradle脚本修改

上面执行完之后,环境已经准备好了,现在要做的就是修改构建脚本:因为已经通过git submodule把公共项目放到独立目录(deps/Common)了,并且它本身也是独立可构建的项目,那么也就是说当前有两个项目了,一个是当前project,一个是Common项目,要做的就是告诉gradle,要多项目构建,编辑settings.gradle,增加项目配置:

include "deps:Common"

以上就是把Common引入到当前项目了。根据项目的不同,然后对应修改build.gradle,就大功告成了。看一个例子:

// 这一段主要是把公共库Common的构建脚本引入,因为一般会有通用的配置在里面
def userGradleScript = file("deps/Common/build.gradle")
if (userGradleScript.exists()) {
    apply from: userGradleScript
}
// 使用war插件,这样就默认引入了java插件
apply plugin: 'war'
// for jetty
apply plugin: 'jetty'
stopKey = 'yourStopKey' // 自定义的stopkey
stopPort = xxxx     // 停止端口
httpPort = xxxx     // 启动http端口

// 项目属性
group = 'yourApp'
version = '1.0.0'
description = """这里描述你的项目"""


// checkstyle config文件地址
checkstyle {
    configFile = file("deps/Common/config/checkstyle/checkstyle.xml")
}
// lib依赖
dependencies {
    // 依赖公共库Common,compile是和maven里的compile scope一样
    compile project(':deps:Common')
    compile 'commons-validator:commons-validator:1.4.0'
    compile('javax.servlet.jsp.jstl:jstl-api:1.2') {
        exclude(module: 'servlet-api')      // 防止版本冲突
    }
    compile 'javax.persistence:persistence-api:1.0.2'
    runtime 'mysql:mysql-connector-java:5.1.26'
    providedCompile 'org.apache.tomcat:tomcat-servlet-api:7.0.30'
    // providedCompile 这个conf在java插件里是报错的,war里是正确的
    providedCompile 'javax.servlet.jsp:jsp-api:2.1'
    ...
}

我们再来简单看下公共项目Common的构建脚本:

// 定义一堆基础插件
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: "jacoco"
apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'findbugs'
apply plugin: 'eclipse'
apply plugin: 'idea'

// 定义项目属性
group = 'Common'
version = '1.0.0'
description = """Giant common library"""

// 定义依赖仓库
repositories {
    mavenCentral()
}
// project的额外属性,这里用于定义profile属性,模拟maven的profile
ext {
    if (project.hasProperty('profile')) {
        profile = project['profile']
    } else {
        profile = "dev"
    }
    println "profile:" + profile
}
// 额外增加source path
sourceSets {
    main {
        resources {
            srcDir "src/main/profiles/${profile}"
        }
    }
}

// project依赖
dependencies {
    compile 'ch.qos.logback:logback-core:1.0.13'
    compile 'ch.qos.logback:logback-classic:1.0.13'
    compile 'ch.qos.logback:logback-access:1.0.13'
    compile 'commons-io:commons-io:2.0.1'
    compile 'commons-lang:commons-lang:2.6'
    compile 'joda-time:joda-time:1.6.2'
    compile 'org.testng:testng:6.8.7'
    compile 'com.googlecode.jmockit:jmockit:1.5'
    ...
}

// task 配置
checkstyle {
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}

findbugs {
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}

pmd {
    ruleSets = ["basic", "braces", "design"]
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}

jacocoTestReport {
    reports {
        xml.enabled true
        html.enabled true
        csv.enabled false
    }
    sourceSets sourceSets.main
}

tasks.withType(Compile) {
    options.encoding = "UTF-8"
}

test {
    useTestNG()
    jacoco {
        excludes = ["org.*"]
    }
}

这样,就可以在公共项目里配置好一堆基础的taskdependencies等等,而使用这个公共项目的其它项目则可以直接使用,无需再额外配置。脚本修改完了,就可以开始构建了(不需要安装gradle,直接使用生成的gradlew就行

./gradlew build

// 基于profile构建
./gradlew -Pprofile=dev build

常用构建命令:clean:清除之前的构建test:执行测试compileJava:编译java check:在test之后做一个check,一般代码检查插件,都是在这个阶段做的build:构建打包

下一页