compile 'groupId:artifactId:version'复制代码

依赖其他子项目

compile project(':dependency-project')复制代码

依赖本地 jar 包

compile files('spring-core.jar', 'spring-aop.jar')
compile fileTree(dir: 'src/main/webapp/WEB-INF/lib', include: '*.jar')复制代码

dir 可以是绝对路径,也可以是相对于工程目录的项目路径

gradle assemble // 编译,打包
gradle build    // 编译,执行测试,打包复制代码

打包时制定包名,例如默认打包出来是 Exam.war ,而我们需要的是 Exam.zip

war.archiveName 'Exam.zip'复制代码
gradle compileJava复制代码

指定编译的输出目录

buildDir = new File(rootProject.projectDir, '../build/' + project.name)复制代码

指定 Maven 仓库

allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
        maven{ url 'http://maven.edu-edu.com.cn/content/groups/public/' }
        // 带认证的库
        maven {
            url 'http://maven.edu-edu.com.cn/content/groups/public/'
            credentials {
                username 'admin'
                password '*****'
}复制代码

上传 jar 包到 Maven 仓库

  • 命令: gradle uploadArchives
  • Release 版本地址: maven.edu-edu.com.cn/nexus/conte…
  • Snapshop 版本地址: maven.edu-edu.com.cn/nexus/conte…
  • 上传的地址和下载的地址是有区别的
  • uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: "http://maven.edu-edu.com.cn/nexus/content/repositories/releases/") {
                    authentication(userName: "admin", password: "*****")
                // 以下三项可选
                pom.groupId    = "$project.group"
                pom.artifactId = "$artifactId" // 默认为项目的目录名
                pom.version    = "$project.version"
    }复制代码

    排除冲突的 jar 包

    例如 dubbo 2.5 依赖 Spring 2,现在基本都用 Spring 4,所以需要把 dubbo 依赖的 Spring 2 的依赖去掉,使用 exclude:

    compile('com.alibaba:dubbo:2.5.3') {
        exclude group: 'org.springframework', module: 'spring'
    }复制代码

    打包时过滤掉不需要的 jar 包

    war {    
        // 打包时只包含以下几个 jar 包
        classpath = classpath.filter { file ->
            file.name.startsWith('lms-client') ||
            file.name.startsWith('dict-client') ||
            file.name.startsWith('e-platform-client')
    }复制代码

    打包时替换 META-INF/context.xml 中的占位符

    war {
        // gradle build 打包时替换 META-INF 下的文件
        from("$webAppDir/META-INF") {
            eachFile {
                it.filter(ReplaceTokens, tokens: loadConfiguration())
            into('META-INF')
    }复制代码

    运行时替换 META-INF/context.xml 中的占位符

    任务 prepareInplaceWebApp 执行完后执行自定义任务,例如替换 context.xml 中的占位符

    project.afterEvaluate {
        // prepareInplaceWebApp 的时候替换 META-INF 下的文件,例如生成 context.xml
        tasks.getByPath('prepareInplaceWebApp').doLast {
            copy {
                from("$webAppDir/META-INF") {
                    eachFile {
                        it.filter(ReplaceTokens, tokens: loadConfiguration())
                into("$buildDir/inplaceWebapp/META-INF")
    }复制代码

    获取命令中的参数

    推荐使用 -D 的方式

    命令: gradle -Denv=development clean assemble
    获取: def environment = System.getProperty('env', 'development')
    命令: gradle -Penv=develop clean assemble
    获取: def environment = hasProperty('env') ? env : 'development'复制代码

    资源文件内容动态替换

    def loadConfiguration() {
        // 获取 gradle 参数中 -Penv 的值: gradle -Penv=development clean assemble
        def environment = hasProperty('env') ? env : 'development'
        def configFile = file('config.groovy') // 配置文件
        return new ConfigSlurper(environment).parse(configFile.toURI().toURL()).toProperties()
    processResources {
        // src/main/resources 下的文件中 @key@ 的内容使用 config.groovy 里对应的进行替换
        from(sourceSets.main.resources.srcDirs) {
            filter(ReplaceTokens, tokens: loadConfiguration())
    }复制代码
    // config.groovy 的内容
    environments {
        development {
                host = '127.0.0.1'
                username = 'root'
                password = 'root'
                database = 'db_exam'
        production {
                host = '192.168.10.123'
                username = 'root'
                password = 'sluper'
                database = 'db_exam'
    }复制代码

    使用嵌入式服务器 Tomcat

    apply plugin: 'org.akhikhl.gretty'
    buildscript {
        repositories {
            jcenter()
        dependencies {
            classpath 'org.akhikhl.gretty:gretty:1.4.0'
    gretty {
        port = 8080
        contextPath = ''
        servletContainer = 'tomcat7'
    }复制代码
    // gretty 的更多配置
    gretty {
        httpPort    = 8080
        debugPort   = httpPort + 1
        servicePort = httpPort + 2
        statusPort  = httpPort + 3
        httpsPort   = httpPort + 4
        httpsEnabled = true
        contextPath  = ''
        jvmArgs = ['-Xmx1024M', '-XX:PermSize=128M', '-XX:MaxPermSize=256M']
        servletContainer = 'jetty7'
        scanInterval = 0
        inplaceMode  = 'hard'
        debugSuspend = false
        enableNaming = true // 启用 JNDI
        managedClassReload = true
    }复制代码

    Tomcat 的 GET 请求的默认编码是 ISO8859-1,如果 GET 需要使用 UTF-8 的话,需要在 server.xml 中设置 URIEncoding 为 UTF-8:

    <Connector port="8080" protocol="HTTP/1.1"
             connectionTimeout="20000"
             redirectPort="8443"
             URIEncoding="UTF-8"/>复制代码

    在 Gretty 中没有提供设置 URIEncoding 的选项,但是可以设置 serverConfigFile 引用 Tomcat 的 server.xml 来达到目的,例如:

    gretty {
        httpPort = 8080
        contextPath = ''
        servletContainer = 'tomcat7'
        serverConfigFile = "server.xml"
        inplaceMode = 'hard'
        debugSuspend = false
        managedClassReload      = true
        recompileOnSourceChange = false
    }复制代码

    Gretty 热部署优化

    Gretty 热部署的相关配置,下面几项都默认设置为 true (reload 表示重新加载整个 web 应用):

  • recompileOnSourceChange // Java 文件变化后自动编译
  • reloadOnClassChange // Class 文件变化后 reload
  • reloadOnConfigChange // 配置文件如 web.xml 变化后 reload
  • reloadOnLibChange // lib 目录下的 jar 变化后 reload
  • 例如 Java 文件修改保存后会自动编译,导致 Class 文件变化,然后 gretty 会重新加载整个 Web 应用,例如应用启动时要执行计划任务,检查数据库的结构等,这样的热部署效率太低。

    如果 Class 文件变化后,能不能只加载 Class 文件,而不是重新加载整个 Web 应用呢?设置 managedClassReload=true 即可 (使用的是 SpringLoaded 来进行热加载,并自动设置 reloadOnClassChange=false):

    gretty {
        port = 80
        contextPath = '/'
        servletContainer = 'tomcat7'
        managedClassReload      = true
        recompileOnSourceChange = false // 禁止自动编译过度频繁的进行热部署
    }复制代码

    多模块工程

  • parent 是父模块
  • mix1 mix2 是子模块
  • └── parent
        ├── mix1
        │   ├── build.gradle
        │   └── src
        │       └── main
        │           ├── java
        │           └── resources
        ├── mix2
        │   ├── build.gradle
        │   └── src
        │       └── main
        │           ├── java
        │           └── resources
        ├── build.gradle
        └── settings.gradle复制代码
    // parent/settings.gradle
    include 'mix1'
    include 'mix2'复制代码
    // parent/build.gradle
    // 所有模块生效
    allprojects {
        ext {
            // gradle build or gradle -Dprofile=product build
            profile = System.getProperty("profile", "dev")
        println '++ Building: ' + project.name
    // 所有子项目的通用配置
    subprojects {
        apply plugin: 'java'
        tasks.withType(JavaCompile) {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
        [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'
        repositories {
            mavenLocal()
            mavenCentral()
    // 某一个指定模块生效
    project('mix1') {
        println 'Building module mix1'
    // 多个匹配的子模块生效
    configure(subprojects.findAll {
            it.name.equals('mix1') ||
            it.name.equals('mix2')
    }) {
        apply plugin: 'java'
    }复制代码

    进入 parent 目录:

  • 执行 gradle build 构建所有的模块
  • 执行 gradle :mix1:build 构建子模块 mix1
  • println "${rootProject.projectDir}/config"
    println ${rootProject.projectDir} + "/config"复制代码

    settings.gradle

    除了构建脚本文件,Gradle 还定义了一个约定名称的设置文件(默认为settings.gradle),该文件在初始化阶段被执行,对于多项目构建必须保证在根目录下有 settings.gradle 文件,对于单项目构建设置文件是可选的

    强制 Gradle 使用 UTF-8

    打开 gradle/bin 目录下的 gradle.bat 文件,修改 12 行附近的代码为
    set DEFAULT_JVM_OPTS="-Dfile.encoding=UTF-8"复制代码
    gradle.properties 里添加
    systemProp.file.encoding=UTF-8复制代码

    创建工程目录结构

    Gradle 默认没有提供创建各种项目目录结构的任务,但是可以使用 gradle-templates 来创建工程的目录结构。

    apply plugin: 'java'
    apply plugin: 'templates'
    repositories {
        mavenCentral()
    buildscript {
        repositories {
            maven {
                url 'http://dl.bintray.com/cjstehno/public'
        dependencies {
            classpath 'gradle-templates:gradle-templates:1.5'
    }复制代码

    运行 gradle tasks 可以看到有很多创建不同项目结构的任务

  • 使用 gradle initJavaProject 创建 Java 应用程序的目录结构
  • 使用 gradle initWebappProject 创建 Web 项目的目录结构
  • 使用 Spring 的应用程序打包

    Gradle 默认的打包任务 jar 不能带上依赖的类,在有依赖 Spring 的项目中,最好是使用 shadowJar 来打包,其会合并 spring 冲突的配置文件,例如 fatJar 则不会。

    如果是可执行的 jar 包,配置 mainClassName 为 jar 包启动运行的类,否则可以忽略掉。

    apply plugin: 'java'
    apply plugin: 'application'
    apply plugin: 'com.github.johnrengelman.shadow'
    buildscript {
        repositories { jcenter() }
        dependencies { classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' }
    mainClassName = 'Foo'
    jar {
        manifest { attributes 'Main-Class': mainClassName }
    // 打包命令: gradle clean shadowJar
    shadowJar {
        mergeServiceFiles('META-INF/spring.*')
    }复制代码

    打包时只要指定的 jar 包,解压

    war {
        // 打包时只包含以下几个 jar 包
        classpath = classpath.filter { file ->
            file.name.startsWith('javaee-mvc-framework') ||
            file.name.startsWith('e-platform-client') ||
            file.name.equals('main')
        archiveName 'qa.zip' // 默认为 qa.war
        def zipFile = file("$buildDir/libs/qa.zip")
        doLast {
            copy {
                from zipFile
                into "$rootProject.projectDir/output/$school/"
            def outputDir = file("$rootProject.projectDir/output/qa")
            delete outputDir
            copy{
                from zipTree(zipFile)
                into outputDir
    }复制代码
  • Gradle 替代 Maven
  • Gretty Hot deployment
  • Gradle脚本基础全攻略
  • since1986 Dubbo
    • 1678
    私信
    2,028