使用Gradle構建Java項目
這個手冊將通過一個簡單的Java項目向大家介紹如何使用Gradle構建Java項目。
我們將要做什麼?
我們將在這篇文檔航中創建一個簡單的Java項目,然後使用Gradle構建它。
需要準備什麼?
- 預留15分鐘空閒時間
- 一件稱手的兵器(你最喜歡的IDE或者文本編輯器)
- Java環境([JDK6](http://www.oracle.com/technetwork/java/javase/downloads/index.html”JDK”及以上版本)
如何完成這個手冊的內容?
與大多數Spring的入門手冊一樣,你可以從頭開始一步步完成教程中的每一步工作,也可以跳過你已經爛熟的基礎步驟。不管採用那種方式,你最後都會得到可工作的代碼。
- 如果要重頭開始,猛戳這裏
- 如果要跳過基礎部分,需執行以下操作:
當你完成後,你可以使用gs-gradle/complete
來檢查你的結果。
配置項目
首先需要配置一個項目給Gradle進行構建。爲了保證我們能專注於Gradle,目前最好創建最簡單的Java項目。
創建目錄結構
在項目主目錄下,創建以下子目錄;在*nix系統下可以使用命令:mkdir -p src/main/java/hello
1
2
3
4
|
└──
src └──
main └──
java └──
hello |
在src/main/java/hello
目錄中,你可以創建任何Java類。爲簡單起見並且爲了與指南的其餘部分保持一致,我們建議創建兩個雷HelloWorld.java
和Greeter.java
src/main/java/hello/HelloWorld.java
的源代碼:
1
2
3
4
5
6
7
8
|
package
hello; public
class
HelloWorld { public
static
void
main(String[] args) { Greeter
greeter = new
Greeter(); System.out.println(greeter.sayHello()); } } |
src/main/java/hello/Greeter.java
的源代碼:
1
2
3
4
5
6
7
|
package
hello; public
class
Greeter { public
String sayHello() { return
"Hello world!" ; } } |
安裝Gradle
到目前爲止,我們已經搭建了一個可以用來使用Gradle構建的項目,現在到了安裝Gradle的時候了。
Gradle可以從http://www.gradle.org/downloads下載。我們僅需要下載Gradle的二進制發佈包,所以在剛纔提供的連接上尋找gradle-version-bin.zip
文件(當然,也可以下載gradle-version-all.zip
,它包含源代碼、文檔以已編譯代碼)
解壓縮下載的文件,並將解壓後目錄中的bin
目錄加到環境變量中。
可以在命令行中執行以下代碼來測試Gradle是否安裝成功
1
|
gradle |
如果你很幸運,嘛事都OK,你會看到下面的welcome信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:help Welcome
to Gradle 1.8 . To
run a build, run gradle <task> ... To
see a list of available tasks, run gradle tasks To
see a list of command-line options, run gradle --help BUILD
SUCCESSFUL Total
time: 2.675
secs |
看到這個了,說明Gradle已經成功安裝到系統中了。如果沒看到……再去看看Gradle的手冊先。
Gradle可以做些什麼呢?
Gradle已經安裝到系統上了,那麼它可以做什麼呢?在我們爲項目創建build.gradle
文件之前,我們可以先問一下Gradle目前有哪些可用的任務(Tasks):
1
|
gradle
tasks |
我們可以看到可用任務(Tasks)的列表。假設你執行Gradle的目錄不存在build.gradle
文件,你可以看到一些非常基礎的任務,類似於:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
:tasks ==
All tasks runnable from root project ==
Build Setup tasks setupBuild
- Initializes a new
Gradle build. [incubating] wrapper
- Generates Gradle wrapper files. [incubating] ==
Help tasks dependencies
- Displays all dependencies declared in
root project 'gs-gradle' . dependencyInsight
- Displays the insight into a specific dependency in
root project 'gs-gradle' . help
- Displays a help message projects
- Displays the sub-projects of root project 'gs-gradle' . properties
- Displays the properties of root project 'gs-gradle' . tasks
- Displays the tasks runnable from root project 'gs-gradle' . To
see all tasks and more detail, run with
--all. BUILD
SUCCESSFUL Total
time: 3.077
secs |
儘管上面的列出的任務是可用的,但是如果沒有項目的構建配置他們無法提供太多的價值。當配置了項目的build.gradle
後,一些任務將變得非常有用。
如果在build.gradle
中配置了插件(plugins)上面的任務列表會變得更長,最好在配置插件後使用gradle
task
看看那些任務是可用的。
剛說到配置插件,馬上我們就會配置一個插件來啓用基礎的Java構建功能。
構建Java代碼
先從簡單的開始,創建一個最簡單的只有一行的build.gradle
文件:
1
|
apply
plugin: 'java' |
別看只有一行配置,提供的能力可不是一點點哦。再執行一下gradle task
,我們可以看到任務列表中增加了一些內容,比如:用來編譯java項目的任務、用來創建JavaDoc的任務、用來執行單元測試的任務。
我們經常使用的任務是gradle build
,這個任務執行以下操作:編譯、執行單元測試、組裝Jar文件:
1
|
gradle
build |
幾秒鐘以後,會看到”BUILD SUCCESSFUL”輸出,說明構建已經完成了。
可以到”build”目錄中查看構建結構,在這個目錄中我們可以看到很多子目錄,其中有三個我們需要特別注意:
- classes: 保存被編譯後的.class文件
- reports: 構建報告(如:測試報告)
- lib: 組裝好的項目包(通常爲:.jar或者.war文件)
classes目錄包含編譯生成的所有.class文件。執行完編譯後,我們應該可以在這裏找到”HelloWorld.class”和”Greeter.class”。
到目前爲止,我們項目並沒有申明任何依賴,所以”debendency_cache”目錄是空的。
“reports”目錄會包含項目單元測試的測試報告,當然,當前項目並未編寫任何單元測試,所以,也是空目錄。
“lib”目錄包含打包後的jar或war文件,在後面的內容中我們將學會如何定義JAR的名稱和版本號。
申明依賴
我們的Hello World例程非常簡單且不依賴於任何第三方庫,但是大多數應用程序都會依賴第三方庫提供的通用或複雜的功能。
例如:假設我們希望更好的說”Hello World!”,我們希望應用程序能同時輸出當前的日期和時間。當然這可以使用Java自身的日期和時間相關庫,但是我們可以使用”Joda Time”庫實現更有趣的功能。
首先,把HelloWorld.jara類修改成下面這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package
hello; import
org.joda.time.LocalTime; public
class
HelloWorld { public
static
void
main(String[] args) { LocalTime
currentTime = new
LocalTime(); System.out.println( "The
current local time is: "
+ currentTime); Greeter
greeter = new
Greeter(); System.out.println(greeter.sayHello()); } } |
這裏我們的HelloWorld
使用”Joda Time”的LocalTime
類來獲取和輸出當前時間。
如果我們馬上執行gradle build
來構建項目,構建過程將會失敗,因爲我們並未將”Joda Time”庫聲明爲編譯時依賴庫。
首先,我們需要添加一些配置來定義第三方庫的來源:
1
2
3
4
|
repositories
{ mavenLocal() mavenCentral() } |
上面的repositories
定義,告訴構建系統通過Maven中央庫來檢索項目依賴的軟件包,Gradle在很大程度上依賴Maven構建工具的許多約定和基礎功能,包括使用Maven中央的庫來處理依賴關係。
現在我們可以使用第三方庫了,但現需要定義:
1
2
3
|
dependencies
{ compile
"joda-time:joda-time:2.2" } |
使用dependencies
塊,我們定義了一條Joda Time的依賴項。這裏,明確指定使用joda-time組內的版本爲2.2的joda-time庫。
另一個要注意的是,我們在這個依賴定義中指定依賴是compile
範圍的。意思是,這個庫在編譯和運行時都需要(如果我們正在構建WAR文件,這個文件會在/WEB-INF/libs
目錄下)。另外值得注意的依賴類型包括:
providedCompile
:在編譯期間需要這個依賴包,但在運行期間可能由容器提供相關組件(比如:Java Servlet API)testCompile
:依賴項僅在構建和運行測試代碼時需要,在項目運行時不需要這個依賴項。
最後,我們來定義我們將生成的Jar文件的名字:
1
2
3
4
|
jar
{ baseName
= 'gs-gradle' version
= '0.1.0' } |
jar
塊定義如何命名JAR文件,在上面的例子中,我們的JAR文件的名字爲:gs-gradle-0.1.0.jar
。
注:這個時候如果執行gradle build
,Gradle會花一些時間從Maven中央庫下載Joda Time包(具體下載時間依賴於你的網速)
使用Gradle Wrapper來構建項目
Gradle Wrapper是開始一個Gradle構建的首選方式。它包含了windows批處理以及OS X和Linux的Shell腳本。這些腳本允許我們在沒有安裝Gradle的系統上執行Gradle構建。要實現這個功能,我們需要在我們的build.gradle
文件中增加以下代碼:
1
2
3
|
task
wrapper(type: Wrapper) { gradleVersion
= '1.11' } |
執行下面代碼來下載和初始化wrapper腳本:
1
|
gradle
wrapper |
命令執行完後,我們可以看到增加了一些新文件。有兩個文件在根目錄下,wapper的jar文件和properties文件在新增的gradle/wrapper
目錄下。
1
2
3
4
5
6
7
|
└──
initial └──
gradlew └──
gradlew.bat └──
gradle └──
wrapper └──
gradle-wrapper.jar └──
gradle-wrapper.properties |
現在Gradle Wrapper已經可以用來構建系統了。把這些文件增加到版本控制系統中,然後再任何時候、任何地方只要遷出這些文件就一個按照同樣的方式(與當前生成 Wrapper的Gradle版本一致)構建系統。運行wrapper腳本來構建系統,跟我們之前橋的命令很像:
1
|
./gradlew
build |
當第一次通過wrapper使用指定版本的Gradle構建系統時,wrapper首先下載對應版本的Gradle可執行文件。Gradle Wrapper的所有文件在都可以被提交到版本庫中,所以,任何人都可以在沒有安裝Gradle的環境下使用相同版本的Gradle構建系統。
在這個時候,我們需要重新構建我們的代碼,構建的結果目錄如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
build ├──
classes │
└── main │
└── hello │
├── Greeter. class │
└── HelloWorld. class ├──
dependency-cache ├──
libs │
└── gs-gradle- 0.1 . 0 .jar └──
tmp └──
jar └──
MANIFEST.MF |
Jar文件中包含我們希望打包的Gretter
和HelloWorld
類。
1
2
3
4
5
6
|
$
jar tvf build/libs/gs-gradle- 0.1 . 0 .jar 0
Fri May 30
16 : 02 : 32
CDT 2014
META-INF/ 25
Fri May 30
16 : 02 : 32
CDT 2014
META-INF/MANIFEST.MF 0
Fri May 30
16 : 02 : 32
CDT 2014
hello/ 369
Fri May 30
16 : 02 : 32
CDT 2014
hello/Greeter. class 988
Fri May 30
16 : 02 : 32
CDT 2014
hello/HelloWorld. class |
需要注意的,即使我們聲明瞭joda-time依賴,但這裏也沒有包括對應的庫文件,而且生成的JAR文件也不是可運行JAR文件。
要想讓代碼可以運行,我們可以使用Gradle的application
插件。增加以下內容到build.gradle
文件中。
1
2
3
|
apply
plugin: 'application' mainClassName
= 'hello.HelloWorld' |
現在我們的app可以執行了。
1
2
3
4
5
6
7
8
9
10
11
|
$
./gradlew run :compileJava
UP-TO-DATE :processResources
UP-TO-DATE :classes
UP-TO-DATE :run The
current local time is :
16 : 16 : 20.544 Hello
world! BUILD
SUCCESSFUL Total
time: 3.798
secs |
爲了能夠將依賴包也以一起打包,比如,我們希望構建一個WAR包,可以包含第三方組件的打包格式,我們可以使用Gradle的WAR插件。如果我們使用Spring Boot並且希望得到一個可執行的JAR文件,我們可以使用spring-boot-gradle-plugin插件。在我們的示例中,gradle沒有足夠的信息來了解我們的目標系統。但是,目前介紹的內容已經足夠我們開始使用Gradle了。
下面是本文需要用的的build.gradle
文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
apply
plugin: 'java' apply
plugin: '<span
class="wp_keywordlink"><a href="http://res.importnew.com/eclipse" title="Eclipse ImportNew主頁" target="_blank">Eclipse</a></span>' apply
plugin: 'application' mainClassName
= 'hello.HelloWorld' //
tag::repositories[] repositories
{ mavenLocal() mavenCentral() } //
end::repositories[] //
tag::jar[] jar
{ baseName
= 'gs-gradle' version
= '0.1.0' } //
end::jar[] //
tag::dependencies[] dependencies
{ compile
"joda-time:joda-time:2.2" } //
end::dependencies[] //
tag::wrapper[] task
wrapper(type: Wrapper) { gradleVersion
= '1.11' } //
end::wrapper[] |
注意:文件中有很多start/end註釋,這些註釋是爲了方便拷貝文件中的內容到文章的各個部分,在實際使用中不需要包含他們。
總結
恭喜,你已經創建了一個簡單的然而可用的Gradle構建文件來構建Java項目。