2015年11月28日

Gradle(14)–– Dependency Management

目標
在本章我們會著重在如何管理專案相依、解決相互衝突、解析策略並教你如何發佈artifacts
在不同的元件版本下。

歷史相依管理在建構工具是一個很重要的指標,在傳統的ANT建構工具,他無法幫你處理相依
問題,你必須自己將每一個jar名稱和它的位置寫在build.xml。但是在企業應用,有些軟體
會相依其他函式庫,使用ANT的方式,需要花費很多成本去維護相依的問題。後來,Maven
解決這個缺點,ANT整合Ivy也是解決這個問題。在Gradle有自己的相依管理方式,同時它也
支援Ivy和Maven的套件。Gradle主要定義相依關係

  • 相依環境
當我們開發完成的軟體套件,必須要做版本部署並儲存中央版本庫(central repository),讓所有
團隊可以分享使用這些軟體套件。版本命名參考http://semver.org/

  • Gradle相依管理
gradle相依管理定義在dependencies裡面,需要遵循它的規則和定義方式即可。
宣告相依定義:
dependencies
{
    <configuration name> <dependencies>
}

區塊內定義方式:
1. 個別定義
    compile group: 'log4j', name: 'log4j', version: '1.2.16'
2.陣列定義:
   compile 'log4j:log4j:1.2.16','junit:junit:4.10'
3. Closure定義:
   compile ('log4j:log4j:1.2.16') ) {
            // extra configurations
   }

apply plugin: 'java'repositories {
       
mavenCentral()}
dependencies {
        compile group: 'log4j', name: 'log4j', version: '1.2.16'
}

  • 版本庫(Repositories)
建立版本庫是告訴dependencies要去哪裡下載套件,他會檢查群組、名稱和版本
,符合才下載到gradle版本庫中。

1. 內建版本庫
(1) Maven Central repository :  mavenCentral()
(2) Maven JCenter repository:  jcenter()
(3) Maven local Repository :    mavenLocal()
(4) Ivy repository:    
   ivy {
       url "
http://<ivyrepositorylocation>"
       layout "ivy" // valid values are maven, gradle, ivy
   }

(5) Organization repository: 你可以為你的公司定義私人的程式庫。
repositories {
   maven {
      url "
http://private.repository/path"
      credentials {
        username 'guest'
        password '123123'
     }
   }
   ivy { // For Ivy repositories
   url "
http://private.repository/path"
   }
}

(6) Local directory repository : 有時候開發軟體載入相依性,會用到本地系統檔案目錄,可以定義flatDir方法。
repositories {
   flatDir {
       dirs '/localfile/dir1', '/localfile/dir2'
   }
}

  • 相依深入解析
剛剛介紹相依探討,本節介紹如何解析如何
(1) 遞移相依 :
當套件相依另一個套件時,另一個套件有相依其它套件,一層層的相依關係,可以稱為遞移相依,例如
commons-httpclient –> commons-logging –> 其它套件->…。Gradle會處理這些複雜的相依關係,預設
將這些相依下載到最後一層。

(2)排除相依設定

(2.1) 完全排除(Exclude)
有些情況,你不希望gradle處理相依問題,我們可以使用將transitive為off,
範例一、 只下載commons-httpclient套件apply plugin:'java'
repositories {
          mavenCentral()
}

dependencies {
     compile group:'commons-httpclient', name:'commons-httpclient',
     version:'3.1',
transitive: false}

(2.2) 選擇排除(selective)
如果你不想要全部都不檢查相依,只是部分檢查可以使用exclude定義
dependencies{
    compile('commons-httpclient:commons-httpclient:3.1') {
    exclude group:'commons-codec' // exclude by group
     //exclude group:'commons-codec',module:'commons-codec'
    }
}


(3)動態訂義相依版本

(3.1)版本
Gradle抓取版本超過1.0以上的,如果是用'latest.integration只會捉最新的版本。
compile group:'commons-codec',name:'commons-codec', version: '1.+'
compile group:'commons-codec',name:'commons-codec', version:'latest.integration’

(3.2)副檔名
當我們用ext只會下載所定義的副檔名,範例只會下載 .war的檔案下來。
dependencies {
     runtime group: 'org.mywar', name: 'sampleWeb', version: '1.0',
    
ext: 'war'}

(3.3)特定檔案名稱
當我們利用classifier來定義特定下載檔案名稱,例如版本庫有兩個jar檔為assys-1.0-test.jar和assys-1.0-publish.jar
兩種。使用classifier只會下載publish的jar檔下來。
dependencies {
    runtime group: 'org.assys, name: ‘assys’, version: '1.0',  classifier: 'publish', ext:'war'
}

  • 報表
我們可以顯示本專案各任務的所有相依關係,例如: compile、testCompile等等

build.gradle
apply plugin: 'java'
version=1.0
repositories {
    mavenCentral()
}
dependencies {
     testCompile 'junit:junit:4+'
    compile group: 'log4j', name: 'log4j', version: '1.2.16'
    compile 'commons-httpclient:commons-httpclient:3.1'
    compile 'dom4j:dom4j:1.6.1'
}
C:\Users\bryan\workspace\ex1>gradle -b build.gradle dependencies
:dependencies
------------------------------------------------------------
Root project
------------------------------------------------------------
archives - Configuration for archive artifacts.
No dependencies
compile - Compile classpath for source set 'main'.
Download https://repo1.maven.org/maven2/commons-httpclient/commons-httpclient/3.
1/commons-httpclient-3.1.pom
Download https://repo1.maven.org/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1.pom
Download https://repo1.maven.org/maven2/commons-logging/commons-logging/1.0.4/co
mmons-logging-1.0.4.pom
Download https://repo1.maven.org/maven2/commons-codec/commons-codec/1.2/commons-
codec-1.2.pom
Download https://repo1.maven.org/maven2/xml-apis/xml-apis/1.0.b2/xml-apis-1.0.b2
.pom
+--- log4j:log4j:1.2.16
+--- commons-httpclient:commons-httpclient:3.1
|    +--- commons-logging:commons-logging:1.0.4
|    \--- commons-codec:commons-codec:1.2
\--- dom4j:dom4j:1.6.1
     \--- xml-apis:xml-apis:1.0.b2
default - Configuration for default artifacts.
+--- log4j:log4j:1.2.16
+--- commons-httpclient:commons-httpclient:3.1
|    +--- commons-logging:commons-logging:1.0.4
|    \--- commons-codec:commons-codec:1.2
\--- dom4j:dom4j:1.6.1
     \--- xml-apis:xml-apis:1.0.b2
runtime - Runtime classpath for source set 'main'.
+--- log4j:log4j:1.2.16
+--- commons-httpclient:commons-httpclient:3.1
|    +--- commons-logging:commons-logging:1.0.4
|    \--- commons-codec:commons-codec:1.2
\--- dom4j:dom4j:1.6.1
     \--- xml-apis:xml-apis:1.0.b2
testCompile - Compile classpath for source set 'test'.
+--- log4j:log4j:1.2.16
+--- commons-httpclient:commons-httpclient:3.1
|    +--- commons-logging:commons-logging:1.0.4
|    \--- commons-codec:commons-codec:1.2
+--- dom4j:dom4j:1.6.1
|    \--- xml-apis:xml-apis:1.0.b2
\--- junit:junit:4+ -> 4.12
     \--- org.hamcrest:hamcrest-core:1.3
testRuntime - Runtime classpath for source set 'test'.
+--- log4j:log4j:1.2.16
+--- commons-httpclient:commons-httpclient:3.1
|    +--- commons-logging:commons-logging:1.0.4
|    \--- commons-codec:commons-codec:1.2
+--- dom4j:dom4j:1.6.1
|    \--- xml-apis:xml-apis:1.0.b2
\--- junit:junit:4+ -> 4.12
     \--- org.hamcrest:hamcrest-core:1.3
BUILD SUCCESSFUL
Total time: 20.567 secs

2015年11月27日

Gradle(13)–– Plugin Management

前面有介紹如何建立web專案或是Java專案等等,本章詳細說明Gralde

  • 多Gradle腳本運用

當你需要載入其他gradle腳本時,使用apply from 還載入

語法: apply from: <Path of otherfile.gradle>

範例一、 多Gradle腳本載入

C\:>calcuate.gradle   //計算

apply plugin: 'java'
task task1 {
    println "task1"
}


C\:>project.gradle

apply from:  "calcuate.gradle"

task  mainTask {
    println "It is a main task!"
}

結果

task1
It is a main task!



二位元插件
二進位插件必須實做Plugin的介面功能後,你可以載入它到你的建構腳本。Gradle已經內件函式庫
可以使用。如果你想要使用其他third-party pluings,需要確定可用的classpath路徑,請使用buildscript{}
來設定。

語法 : apply plugin: '<pluginid>'
範例一、 apply plugin : “java”

  • Gradles內建plugins

(1) 建構和測試常用plugins
     Java , Groovy , Scala,  War
(2) 分析plugins
    Checkstyle ,FindBugs ,Sonar ,Sonar Runner ,PMD
(3) IDE plugins
     Eclipse, IDEA ..etc

參考: https://docs.gradle.org/current/userguide/userguide.

  • Third plugins

https://plugins.gradle.org/

  • Java plugin

Java plugin是Gradle的核心一部份,它可以保證我們建構Java專案可以正確編譯、測試和打包。
載入方式為apply plugin: 'java'。

接下來討論建構的任務,我們可以在命令列執行下列的指令:
$ gradle tasks --all

可以看出顯示任務不同有建構任務、測式任務、文件任務等等,使用Java plugin需要符合內建的規範
例如: compileJava和processResources會執行src/main/java 的src/main/resources內的檔案,所以將
完成的java檔和環境設定檔需要分別放在src/main/java 的src/main/resources裡面。接下來我們會說明
gradle的Java plugin指令的功用

範例一、當編譯在src/main底下的java檔案,我們可以使用任務 classes,編譯後的.classes會放在
/build/classes底下,可以下面看到gradle所執行任務的流程。

$ gradle classes

:compileJava
:processResources UP-TO-DATE
:classes

範例二、testClasses用來編譯測試檔與測試環境,編譯後的.classes會放在/build/classes/test底下,
可以下面看到gradle所執行任務的流程。

$ gradle testClasses

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE

範例三、任務test除了編譯檔案外,他會幫我們產生測試報表,放在/build/reports裡面

$ gradle test

C:\Users\bryan\workspace\ex1>gradle test
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE                                                  //執行junit並產生報表

範例四、使用assemble任務或是jar任務會打包.class和resource的資料到jar檔中並放在build/libs
檔案命名為<project-name>.jar ,如果有加入版本會以<name>-<version>.jar.

$ gradle assemble

Total time: 11.204 secs
C:\Users\bryan\workspace\ex1>gradle assemble
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar
:assemble

範例五、 Gradle也有提供一連串完成的任務叫做build,它會從編譯、打包、測試到完整執行,就不需要
分別的執行,其中clean任務會先清除在build/裡面的資料,再進行build任務

$ gradle clean
$ gradle build

C:\Users\bryan\workspace\ex1>gradle clean
:clean

Total time: 5.866 secs
C:\Users\bryan\workspace\ex1>gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:assemble UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build UP-TO-DATE

BUILD SUCCESSFUL

範例六、可以在build.gradle列印出這些變數,顯示出目前目前專案libs路徑、程式的路徑等等。詳細可以查https://docs.gradle.org/current/userguide/java_plugin.html.

task displayJavaPluginConvention << {
    println "Lib Directory: $libsDir"
    println "Lib Directory Name: $libsDirName"
    println "Reports Directory: $reportsDir"
    println "Test Result Directory: $testResultsDir"
    println "Source Code in two sourcesets: $sourceSets"
    println "Production Code: ${sourceSets.main.java.srcDirs}"
    println "Test Code: ${sourceSets.test.java.srcDirs}"
    println "Production code output: ${sourceSets.main.output.classesDir}  ${sourceSets.main.output.resourcesDir}"
    println "Test code output: ${sourceSets.test.output.classesDir}  ${sourceSets.test.output.resourcesDir}"

}

  • 專案環境設定

在上面我們學到如何是用預設環境(default properties or conventions)去建立java專案且可以成功編譯,在本節
會學習到如何根據我們的需求客置設定環境

範例一、我們有一個專案需要將編譯的路徑做一些調整如下:
系統預設: src/main/java  => src/sale
系統預設:  src/test/java   => src/saleTest
系統預設:

buildDir = 'buildfolder'
libsDirName = 'libfolder'
sourceSets {
main {
     java {
         srcDir 'src/sale/java'
      }
      resources {
      srcDir 'src/saleTest/resources'
     }
  }
test{
    java {
        srcDir 'src/testcode/java'
         }
        resources {
        srcDir 'src/testcode/resources'
     }
  }
}

testResultsDirName = "$buildDir/new-test-result"
sourceSets.main.output.classesDir="${buildDir}/classes/sale/java"
sourceSets.main.output.resourcesDir="${buildDir}/classes/sale/resources"
sourceSets.test.output.classesDir="${buildDir}/classes/saleTest/java"
sourceSets.test.output.resourcesDir="${buildDir}/classes/saleTest/resources"

2015年11月22日

Gradle(12)–– Groovy

本章會介紹Gradle的核心語法為Groovy,讓使用者更容易了解gradle工具使用,Groovy運行在JVM上面,
所以很容易與Java做整合利用。

  • 資料類型
Data type Wrapper type values
byte Byte 0
short Short 0
int Integer 0
long Logn 0L
float Float 0.0f
double Double 0.0d
char Character \u0000
boolean Boolean false
String Not Applicable null

資料型態跟Java相同,現在介紹如何宣告變數,

範例一、 宣告變數
def a1 = ‘ It is a sunday.’
def a2 = “It is a sunday.”
def a3 = “example1. ${a1}”
def a4 =/ This is                //斷航符號 /
              a
             book /

  • 動態型別(Dynamic typing)宣告

Groovy支援動態型別與靜態型別兩種,靜態型別通常會再編譯時檢查、記憶體最佳化等等工作。
動態型別表示你不知道宣告的函式的型態或回傳的資料類型是什麼,但是這種方式開發人員比較
有彈性宣告方式。當我宣告時,不會預設型別給宣告之變數,會決定變數型別是在執行的時候才
會決定要丟甚麼型別給他。

範例二、動態型別宣告
//(1) 宣告變數
def  var1
var1 = “It’s a book”
println var1.class       // java.lang.String
var1 = 10
println var1.class      // class java.lang.Integer

//(2) 宣告函式
def addition(a,b) 
addition(1,2)
addition(‘Jack’,‘Janet’)

 

  • 控制結構
    常用的控制語法有if、else、for、switch等等,在groovy也有相同的用法

(1) if-lelse
二元運算:

if( a<input){
    println input
}else{
    println a
}


三元運算
(a<input) ? input : a

(2) switch

switch(input)
{
    case Integer : println("Integer Matched"); break;
    case BigDecimal : println("BigDecimal Matched");break;
    case String : println("String Matched");break;
    default : println("Nothing Matched"); break;
}


(3) for

def fruit = ['apple','banana','strawberry']
for(String s : fruit){
    println s
}


(4) while

int count = 0
while(count < 5) {
     println count++
}

  • 集合

(1) Set
集合是一群沒有排序且不重複物件,set集合可以有Null的資料,常用方法有add, addAll, remove, or removeAll

def set1 = [1,2,3,4,5,6] as Set
def set2 = new HashSet(['a','b','c','d'])

set1.add(7)
set1.add([8,9])
print set1                  //[1, 2, 3, 4, 5, 6, 7, [8, 9],]

set2.remove('d')
println set2              // [a, b, c]

Set union = set1 + set2
println union            // [1, 2, 3, 4, 5, 6, 7, [8, 9], a, b, c]

(2)List

List是一組有順序並且可以有重覆資料的物件集合,

def list1 = ['a','d','c']
def list2 = [5,1,7,2,9,1] as list

println list1[1]              // d
println list1.get(1)         // d
println list2.sort()         //[1, 1, 2, 5, 7, 9]
println list1.reverse()    // [c, d, a]

(3) Map
Map是一種主鍵-值的集合,為java.util.HashMap.

Map ageMap = [Jack:20, MaraYa:30,Katy:16,Li:19,Herry:18] as Map
ageMap.each{key, value ->
   print "Name is "+key
    print "Age is "+ value
   print "\n"
}

ageMap.each{entry –>
    print "Name is "+entry.key
    print "Age is "+ entry.value
    print "\n"
}

//結果
// Name is JackAge is 20
// Name is MaraYaAge is 30
// Name is KatyAge is 16
// Name is LiAge is 19
// Name is HerryAge is 18

(4) Range
這是Groovy特有的集合物件,用來做連續數列的集合。

def range1 = 1..10
Range range2 = 'c'..'e'
range1.each { print it }    //12345678910
range1.any { it > 5 }
range1.every { it > 0 }

List list3 = range1.step(2)
print list1                   // [a, d, c]

 

  • Closure

Closurer可以當作函式來使用,但是不需要回傳值或是輸入值會自動回傳,

範例一、 加法closure

def add = { it + it}
add("Hi!")                      // Hi!Hi!
add()                            // null + null => NullPointerException

closure會將外部變數的值,自動配置成內部的值,變數名稱要相同

範例二、 外部變數參考

def name="bryant"
def sayHello = { println name + " hello "}
sayHello()                            // bryant hello


Gradle(11)–– Eclipse for Gradle


本章會介紹使用Eclipse,如何安裝Gradle套件與應用

  • 安裝篇

步驟1 : Help -> Eclipse MaketPlace...

image

步驟2: 在Find打上gralde 按下 Go按鈕,如果未安裝請你按下Install ,已經安裝過,確定是否要更新gralde版本

image

步驟3 : 接著只要一直按next,最後按finish就可以在eclipse使用gradle

2015年11月18日

Gradle(10)–– Web專案

在本章節我們會介紹使用gradle架構下,web專案的架構和常用的設定

  • web 架構

(1) 專案架構

+---bank
+------src
+-----------main
+-------------------java
+---------------------|---com
+---------------------------|-account
+--------------------------------|----createAccount.java                  
+--------------------webapp
+------------------------------jsp/
+-----------------------------------Account.jsp

 

apply plugin: ‘java’
apply plugin: ‘eclipse-wtp’   //有使用eclispe需要