使用Gradle構(gòu)建Java項(xiàng)目
這個(gè)指南將指導(dǎo)你如何使用Gradle構(gòu)建一個(gè)簡(jiǎn)單的Java項(xiàng)目
你將構(gòu)建什么
你將創(chuàng)建一個(gè)簡(jiǎn)單的項(xiàng)目,由Gradle構(gòu)建。
你需要什么
- 大約15分鐘
- 一個(gè)你喜愛(ài)的文本編輯器或者IDE
- JDK 6 或者 往后至最新的JDK
怎么完整走完這個(gè)指南
就像很多Spring入門(mén)指南,你可以從零開(kāi)始,一步一個(gè)腳印實(shí)現(xiàn),或者你可以跳過(guò)你熟悉的步驟,不管怎么樣,你最后會(huì)得到可以工作的代碼。
移步到++設(shè)置項(xiàng)目++,從頭開(kāi)始
做以下步驟以跳過(guò)基本教程:
- ++下載++并且解壓本指南的源代碼倉(cāng)庫(kù),或者使用Git克隆
git clone https://github.com/spring-guides/gs-gradle.git
- cd進(jìn)入
gs-gradle/initial
- 跳到 Install Gradle
當(dāng)你完成上面的步驟,你可以那你得到的結(jié)果與
gs-gradle/complete
里的代碼對(duì)比。
設(shè)置項(xiàng)目
首先,為Gradle設(shè)置一個(gè)java項(xiàng)目來(lái)構(gòu)建。為了把重點(diǎn)放在Gradle,我們盡量地把例子做得簡(jiǎn)單。
創(chuàng)建目錄結(jié)構(gòu)
在一個(gè)由你選擇的項(xiàng)目文件夾,創(chuàng)建以下子目錄機(jī)構(gòu);例如,在類(lèi)unix系統(tǒng)運(yùn)行
mkdir -p src/main/java/hello
└── src
└── main
└── java
└── hello
在 src/main/java/hello 目錄里,你可以自由新建Java類(lèi)。為了簡(jiǎn)單的緣故和為了下文的操作保持一致性,Spring推薦你創(chuàng)建兩個(gè)類(lèi):==HelloWorld.java== 和 ==Greeter.java.==
==src/main/java/hello/HelloWorld.java==
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==
package hello;
public class Greeter {
public String sayHello() {
return "Hello world!";
}
}
安裝Gradle
既然現(xiàn)在有了一個(gè)可以使用Gradle構(gòu)建的項(xiàng)目,那么接著安裝Gradle
強(qiáng)烈推薦使用安裝器:
- SDKMAN
- Homebrew(brew install gradle)
如果以上工具都不適用于你的情況,你可以從 https://www.gradle.org/downloads 下載二進(jìn)制文件,這是最后的手段。只有二進(jìn)制文件是不可缺的,所以請(qǐng)查找指向gradle-version-bin.zip的鏈接。(也可以選擇gradle-version-all.zip以獲取源代碼和文檔以及二進(jìn)制文件。)
解壓縮下載的文件,并且把bin文件夾加入到環(huán)境變量。
運(yùn)行Gradle,測(cè)試Gradle的安裝是否成功(項(xiàng)目文件夾內(nèi))。使用以下命令。
gradle
如果一切順利,會(huì)看到一個(gè)歡迎信息:
:help
Welcome to Gradle 2.3.
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
那么你現(xiàn)在就已經(jīng)安裝好Gradle了。
看看Gradle能做什么
既然現(xiàn)在Gradle已經(jīng)安裝好了,那就看看它能做什么。在你創(chuàng)建一個(gè)項(xiàng)目的build.gradle文件時(shí),你可以查看它有哪些任務(wù)是可用的。
gradle tasks
你應(yīng)該看到一個(gè)可用任務(wù)列表。假設(shè)你運(yùn)行Gradle在一個(gè)沒(méi)有build.gradle文件的文件夾,你會(huì)看見(jiàn)一些非?;A(chǔ)的任務(wù),例如:
:tasks
== All tasks runnable from root project
== Build Setup tasks
setupBuild - Initializes a new Gradle build. [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
即使這些任務(wù)可以使用,沒(méi)有一個(gè)項(xiàng)目構(gòu)建配置,他們沒(méi)有多大的價(jià)值。當(dāng)你提供了build.gradle文件,一些任務(wù)變得更有用。當(dāng)你向build.gradle加入插件,任務(wù)列表會(huì)變長(zhǎng),所以你會(huì)有時(shí)會(huì)想再次運(yùn)行 task 來(lái)看那些任務(wù)可用。
說(shuō)到加入插件,下一步是加入一個(gè)啟用基本java構(gòu)建功能的插件。
構(gòu)建java代碼
從簡(jiǎn)單開(kāi)始,創(chuàng)建一個(gè)最基礎(chǔ)的build.gradel文件到項(xiàng)目文件夾,這個(gè)文件夾是你在指南開(kāi)頭創(chuàng)建的。在文件中只需寫(xiě)入一行代碼:
apply plugin: 'java'
在構(gòu)建配置中的這一行代碼帶來(lái)了非常有用的作用。再次運(yùn)行 gradle tasks,會(huì)看到新的任務(wù)加入了這個(gè)列表,包括構(gòu)建項(xiàng)目,創(chuàng)建JavaDoc,運(yùn)行測(cè)試的任務(wù)。
你將經(jīng)常使用 gradle build 任務(wù)。這個(gè)任務(wù)編譯,測(cè)試,組裝代碼到一個(gè)JAR文件。你可以運(yùn)行以下命令來(lái)使用:
gradle build
等待幾秒,“BUILD SUCCESSFUL”說(shuō)明構(gòu)建已經(jīng)完成。
請(qǐng)檢查 build 文件夾,查看構(gòu)建工作的結(jié)果。在其中你會(huì)找到一系列的文件夾,包括以下三個(gè)值得注意的文件夾。
- classes。此項(xiàng)目的已編譯的.class文件。
- reports。該文件夾由build生成(比如test reports)
- libs。整合的項(xiàng)目的庫(kù)(通常是JAR或者WAR文件)。
classes 文件夾包含 從Java代碼編譯出來(lái)的.class文件。特別地,你應(yīng)該在里面找HelloWorld.class和Greeter.class.
在此刻,這個(gè)項(xiàng)目沒(méi)有任何庫(kù)依賴(lài),所以在dependency_cache文件夾中沒(méi)有任何文件。
reports 文件夾應(yīng)包含一個(gè)項(xiàng)目的運(yùn)行時(shí)單元測(cè)試報(bào)告。因?yàn)檫@個(gè)項(xiàng)目還沒(méi)有單元測(cè)試,所以這個(gè)報(bào)告不會(huì)有趣。
libs 文件夾應(yīng)包含一個(gè)以項(xiàng)目文件夾名字命名的JAR文件。再向下,你將看見(jiàn)你如何指定JAR文件名和它的版本的方法
聲明依賴(lài)
這個(gè)簡(jiǎn)單的Hello World例子是完全地獨(dú)立和不依賴(lài)任何額外的庫(kù)。然而,很多應(yīng)用依賴(lài)于外部的庫(kù)來(lái)處理通常的或者復(fù)雜的功能。
舉個(gè)例子,假設(shè)除了說(shuō)“Hello,World”之外,你想要這個(gè)應(yīng)用打印當(dāng)前日期和時(shí)間,你應(yīng)當(dāng)使用原生java庫(kù)里的日期和時(shí)間工具,不過(guò)你也可以使用Joda Time庫(kù)使得它更有趣。
首先,編輯 HelloWorld.java 如以下:
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類(lèi)來(lái)獲得和打印當(dāng)前時(shí)間
如果你現(xiàn)在運(yùn)行g(shù)radle build 來(lái)構(gòu)建項(xiàng)目,那么它會(huì)失敗,因?yàn)槟氵€沒(méi)有聲明Jada Time 作為這次構(gòu)建的編譯依賴(lài)
對(duì)于初學(xué)者,需要為第三方庫(kù)加入源。
repositories {
mavenCentral()
}
repositories代碼塊指示了這次構(gòu)建應(yīng)該從Maven Central 庫(kù)中解決它的依賴(lài)關(guān)系。Gradle嚴(yán)重依賴(lài)由Maven 構(gòu)建工具創(chuàng)建的規(guī)范和功能,包括使用Maven Central的可選項(xiàng)當(dāng)作庫(kù)依賴(lài)的源。
既然我們已經(jīng)加入了第三方庫(kù),那么讓我們聲明他們。
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile "joda-time:joda-time:2.2"
testCompile "junit:junit:4.12"
}
根據(jù)dependencies代碼塊,你聲明一個(gè)Joda Time的單一的依賴(lài)。特別地,你請(qǐng)求的是joda-time組中的joda-time庫(kù)的2.2版本。
關(guān)于這個(gè)依賴(lài)有一點(diǎn)值得注意,就是它是一個(gè)compile依賴(lài),說(shuō)明了在compole-time過(guò)程中它可能是可用的(如果你正在構(gòu)建一個(gè)WAR文件,包括這個(gè)WAR的/WEB-INF/libs文件夾)另外值得注意的依賴(lài)類(lèi)型包括:
- providedCompile。編譯代碼所必要的依賴(lài),但是它由一個(gè)運(yùn)行這代碼的容器在運(yùn)行時(shí)提供的(例如,Java Servlet API)
- testCompole。被用來(lái)編譯和運(yùn)行測(cè)試的依賴(lài),但是對(duì)于構(gòu)建或運(yùn)行項(xiàng)目的運(yùn)行時(shí)代碼是非必須的。
最后,讓我們指定我們JAR成品的名字。
jar {
baseName = 'gs-gradle'
version = '0.1.0'
}
jar代碼塊決定這個(gè)JAR將怎樣被命名,在這里,它的名字是gs-gradle-0.1.0.jar。
現(xiàn)在如果你運(yùn)行g(shù)radle build,Gradle應(yīng)該會(huì)從Maven Central倉(cāng)庫(kù)中解決Joda Time的依賴(lài)并且構(gòu)建將會(huì)成功。
使用Gradle Wrapper 構(gòu)建你的項(xiàng)目
Gradle Wrapper是啟動(dòng)一個(gè)Gradle build的首選方法。它由windows批處理腳本和OSX、Linux的shell腳本組成。這些腳本允許你無(wú)需在你的系統(tǒng)中安裝Gradle即可運(yùn)行一個(gè)Gradle build。這些原本是被添加到build文件的東西,現(xiàn)在他們已經(jīng)被包含在Gradle里,所以不再有任何額外的要求。簡(jiǎn)單地使用以下命令:
gradle wrapper --gradle-version 2.13
在任務(wù)執(zhí)行完后,會(huì)出現(xiàn)一些新文件,當(dāng)wrapper jar和properties文件被加入到一個(gè)新的==gradle/wrapper==文件夾,這兩個(gè)腳本在最上層的文件夾(root of the folder)
└── <project folder>
└── gradlew
└── gradlew.bat
└── gradle
└── wrapper
└── gradle-wrapper.jar
└── gradle-wrapper.properties
現(xiàn)在可以用Gradle Wrapper來(lái)構(gòu)建你的項(xiàng)目了。把它加入到你的版本控制系統(tǒng),每個(gè)克隆你項(xiàng)目的人就可以以同樣的配置構(gòu)建它了。它的使用方法同==安裝版本的Gradle==一樣。運(yùn)行wrapper腳本來(lái)進(jìn)行構(gòu)建任務(wù),就像你之前做的:
./gradlew build
第一次運(yùn)行Gradle的某版本的wrapper,它會(huì)下載和緩存該版本的的Gradle二進(jìn)制文件。Gradle Wrapper 文件設(shè)計(jì)為已經(jīng)被提交到了資源控制,這樣子不必每個(gè)人安裝和配置Gradle的某個(gè)版本,來(lái)構(gòu)建項(xiàng)目。
在這個(gè)階段,你將編寫(xiě)你的代碼,你會(huì)在這看到結(jié)果。
build
├── classes
│ └── main
│ └── hello
│ ├── Greeter.class
│ └── HelloWorld.class
├── dependency-cache
├── libs
│ └── gs-gradle-0.1.0.jar
└── tmp
└── jar
└── MANIFEST.MF
包括兩個(gè)預(yù)期的class文件:Greeter和HelloWorld,還有JAR文件??焖兕A(yù)覽:
$ 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
這些類(lèi)文件被綁在了一起。需要非常注意的是,即使你聲明了joda-time作為依賴(lài),此處也不會(huì)有該類(lèi)庫(kù)。而且JAR文件也不可運(yùn)行。
為了使這些代碼可以運(yùn)行,我們可以使用gradle的application補(bǔ)丁。把它加入到你的build.gradle文件
apply plugin: 'application'
mainClassName = 'hello.HelloWorld'
然后就可以把a(bǔ)pp跑起來(lái)了。
$ ./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
打包依賴(lài)需要更多的考慮。比如說(shuō),如果我們要打包一個(gè)WAR包(一種格式,通常關(guān)聯(lián)到第三方依賴(lài)的打包),我們可以使用gradle的 WAR 插件,如果你正使用SpringBoot而且想得到一個(gè)可運(yùn)行的JAR文件,使用spring-boot-gradle-plugin是非常方便的。在這一步中,gradle對(duì)你的系統(tǒng)并不夠了解,無(wú)法做出選擇,不過(guò)現(xiàn)在,使用gradle讓它跑起來(lái)是足夠了的。
要完成本指南的內(nèi)容,這里有已完成的build.gradle文件:
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
mainClassName = 'hello.HelloWorld'
// tag::repositories[]
repositories {
mavenCentral()
}
// end::repositories[]
// tag::jar[]
jar {
baseName = 'gs-gradle'
version = '0.1.0'
}
// end::jar[]
// tag::dependencies[]
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile "joda-time:joda-time:2.2"
testCompile "junit:junit:4.12"
}
// end::dependencies[]
// tag::wrapper[]
// end::wrapper[]