有了Gradle,還會選Maven嗎?

如今許多人還在爲使用Maven 仍是 Gradle 而糾結。若是關注過《Maven權威指南》做者許曉斌老師在InfoQ中發表的文章:《Maven實戰(六)——Gradle,構建工具的將來?》,那麼必定會有同感:Gradle太靈活,可能會形成不可控。文章中的原話是:java

「Gradle的另一個問題就是它太靈活了,雖然它支持約定優於配置,不過從本文你也看到了,破壞約定是多麼容易的事情。人都喜歡自由,愛自定義,以爲本身的需求是多麼的特別,可事實上,從Maven的流行來看,幾乎95%以上的狀況你不須要自行擴展,若是你這麼作了,只會讓構建變得難以理解。從這個角度來看,自由是把雙刃劍,Gradle給了你足夠的自由,約定優於配置只是它的一個選項而已,這初看起來很誘人,卻也可能使其重蹈Ant的覆轍。」git

首先看一下咱們最初使用Gradle構建Spring Cloud項目的build.gradle的寫法:web

buildscript {
    ext {
        springCloudVersion = 'Edgware.SR3'
        springBootVersion = '1.5.9.RELEASE'
        REPOSITORY_HOME = "http://maven.aliyun.com"
    }
    repositories {
        maven { url "${REPOSITORY_HOME}/nexus/content/groups/public" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}
apply plugin: 'maven'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'

if (JavaVersion.current().isJava8Compatible()) {
    allprojects {
        tasks.withType(Javadoc) {
            options.encoding = 'UTF-8'
            options.addStringOption('Xdoclint:none', '-quiet') // 關閉JDK1.8的doclint特性
        }
    }
}
// 導入Spring Cloud 依賴
dependencyManagement {
  imports {
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
  }
}

dependencyManagement {
  resolutionStrategy {
    // 檢查遠程依賴是否存在更新
    cacheChangingModulesFor 0, 'seconds'
    cacheChangingModulesFor 0, 'seconds' // 修改本地緩存策略
  }
}

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

bootRepackage {
  // 默認只打普通jar包
  enabled = false
}

// 打包源代碼,爲了方便查看源碼及調試,把源碼也上傳到nexus倉庫中
task sourcesJar(type: Jar) {
  classifier = 'sources'
  from sourceSets.main.allSource
}

// 打javadoc包,爲了方便查看註釋,須要把javadoc也上傳到nexus倉庫中
task javadocJar(type: Jar, dependsOn: javadoc) {
  classifier = 'javadoc'
  from javadoc.destinationDir
}

artifacts {
  archives jar
  archives sourcesJar
  archives javadocJar
}

uploadArchives {
    repositories {
        mavenDeployer {
            snapshotRepository(url: "${REPOSITORY_HOME}/nexus/content/repositories/snapshots/") {
                authentication(userName: 'xxx', password: 'xxx')
            }
            repository(url: "${REPOSITORY_HOME}/nexus/content/repositories/releases/") {
                authentication(userName: 'xxx', password: 'xxx')
            }
        }
    }
}

version = '0.0.1' // 設置版本
group = 'com.suixingpay.demo' // 設置group id
description = 'demo' // 設置描述

dependencies {
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-web')
    compileOnly('org.springframework.boot:spring-boot-configuration-processor')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.projectlombok:lombok')
    testCompile "org.springframework.boot:spring-boot-starter-test"
}

經過上面代碼咱們能夠看出如下問題:spring

  1. 雖然dependencies部分代碼比maven少了許多,但整體來看,代碼並不簡潔;
  2. 存在硬編碼帶來的風險,好比要修改Maven倉庫的地址,或用戶名及密碼時,須要通知全部人進行變動;
  3. gradle代碼除buildscript代碼塊外,沒有像maven中xml同樣結構性書寫要求,那麼可能形成每一個人的寫法是不同的狀況;
  4. 很難區分每一個插件的配置都有哪些,對於不熟悉插件的人來講是很是痛苦的事情,很是不方便維護;
  5. 當項目多時,會有很是多的重複代碼,增長了很是多的重複開發及維護成本;好比以前沒有要求將源碼及javadoc上傳到maven倉庫中,後來因各類緣由,增長了這項需求,那麼就須要通知全部把全部代碼都修改一遍;

咱們最初的想法是將上面代碼,根據不一樣的插件,使用不一樣的gradle文件來維護,再將它們放到GRADLE_HOME/init.d/目錄下,但仍是更新難的問題。緩存

補充說明init.gradle的加載順序,Gradle會依次對一些目錄進行檢測,按照優先級加載這些目錄下的文件,若是一個目錄下有多個文件被找到,則按照英文字母的順序依次加載。加載優先級以下:服務器

  1. 經過 -I 或者 –init-script 參數在構建開始時指定路徑,如app

    gradle --init-script init.gradle clean
    
     gradle --I init.gradle assembleDebug
  2. 加載USER_HOME/.gradle/init.gradle文件maven

  3. 加載USER_HOME/.gradle/init.d/目錄下的以.gradle結尾的文件spring-boot

  4. 加載GRADLE_HOME/init.d/目錄下的以.gradle結尾的文件工具

後來研究發現gradle 能夠經過 apply from 命令加載外部gradle文件,甚至能夠加載遠程http服務器中的文件。這個發現讓咱們興奮不已,有了它能夠幫助咱們解決上面全部的問題。

首先將上面build.gradle的內容拆分紅多個文件:

  1. 將maven相關的代碼放入maven.gradle文件中;
  2. 因java、spring boot和Spring Cloud是咱們平時用得最多的插件,因此咱們將它們都相關的代碼放到了同一個文件中:spring-cloud.gradle,但Spring boot及Spring Cloud的版本會由於項目的不一樣而使用不一樣的版本,因此須要將它們的單獨提取出來,好比:spring-cloud-dalston-sr4.gradlespring-cloud-edgware.gradle

而後將上面拆分好的文件入到git倉庫中,並修改build.gradle文件:

buildscript { // buildscript 不能抽取出來,只能重複寫。
  ext{
    sxGradleHome = "https://gitee.com/sxfad/gradle-scripts/raw/master/"
  }
  apply from: sxGradleHome + 'maven.gradle'
  apply from: sxGradleHome + 'spring-cloud-edgware.gradle' // 導入使用Spring Cloud及相應的Spring Boot版本號
  repositories {
    maven { url REPOSITORY_URL }
  }
  dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  }
}

// 更詳細的說明請參考 https://gitee.com/sxfad/gradle-scripts/
apply from: sxGradleHome + 'maven.gradle'
apply from: sxGradleHome + 'spring-cloud.gradle'

version = '0.0.1' // 設置版本
group = 'com.suixingpay.demo' // 設置group id
description = 'demo' // 設置描述

dependencies {
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-web')
    compileOnly('org.springframework.boot:spring-boot-configuration-processor')
    compileOnly('org.projectlombok:lombok')
    testCompile('org.projectlombok:lombok')
    testCompile "org.springframework.boot:spring-boot-starter-test"
}

經過上面的方法處理後,給咱們帶來以下好處:

  1. 修改後的build.gradle變得極其簡潔,只須要關心其基本信息及依賴便可;
  2. 對於公司內部使用來講,讓gradle的使用更加規範和標準,也使用變得更加簡單;
  3. 由於核心gradle文件放到了遠程服務器中,很是方便更新和維護;而且使用git管理後,還帶有「版本管理」功能(方便查看文件修改歷史,及回退等);

看到這以後,你必定不會再爲選擇Maven仍是Gradle糾結,甚至已經愛上了Gradle。

更詳細的說明請參考 https://gitee.com/sxfad/gradle-scripts/

相關文章
相關標籤/搜索