- Spring實戰(第6版)
- (美)克雷格·沃斯
- 4329字
- 2022-12-20 19:14:49
1.2 初始化Spring應用
在本書的課程中,我們將會創建一個名為Taco Cloud的在線應用,它能夠訂購人類所發明的一種美食——墨西哥煎玉米卷(taco)[1]。當然,在這個過程中,為了達成目標,我們將會用到Spring、Spring Boot及各種相關的庫和框架。
有多種初始化Spring應用的可選方案。盡管我可以教你手動創建項目目錄結構和定義構建規范的各個步驟,但這無疑是浪費時間,我們最好將時間花在編寫應用代碼上。因此,我們將會學習如何使用Spring Initializr初始化應用。
Spring Initializr是一個基于瀏覽器的Web應用,同時也是一個REST API,它能夠生成一個Spring項目結構的骨架,我們還可以使用各種想要的功能來填充它。使用Spring Initializr的幾種方式如下所示:
● 通過地址為https://start.spring.io/的Web應用;
● 在命令行中使用curl命令;
● 在命令行中使用Spring Boot命令行接口;
● 在Spring Tool Suite中創建新項目;
● 在IntelliJ IDEA中創建新項目;
● 在NetBeans中創建新項目;
● 在Apache NetBeans中創建新項目。
我將這些細節放到了附錄中,這樣就不用在這里花費很多頁的篇幅介紹每種可選方案了。在本章和本書的其他章節中,我都會向你展示如何使用我最鐘愛的方式創建新項目,也就是在Spring Tool Suite中使用Spring Initializr。
顧名思義,Spring Tool Suite是一個非常棒的Spring開發環境,能夠以Eclipse、Visual Studio Code或Theia IDE擴展的方式來使用。我們也可以在Spring網站的Spring Tools頁面下載直接可運行的Spring Tool Suite二進制文件。Spring Tool Suite提供了便利的Spring Boot Dashboard特性,讓我們能夠在IDE中很容易地啟動、重啟和停止Spring Boot應用。
如果你不是Spring Tool Suite用戶,那也沒有關系,我們依然可以做朋友。你可以跳轉到附錄中,查看最適合你的Initializr方案,以此來替換后面小節中的內容。但是,在本書中,我偶爾會提到Spring Tool Suite特有的特性,比如Spring Boot Dashboard。你如果不使用Spring Tool Suite,那么需要調整這些指令以適配你的IDE。
1.2.1 使用Spring Tool Suite初始化Spring項目
要在Spring Tool Suite中初始化一個新的Spring項目,我們首先要點擊File菜單,選擇New,接下來選擇Spring Starter Project。圖1.2展現了要查找的菜單結構。

圖1.2 在Spring Tool Suite中使用Initializr初始化一個新項目
在選擇Spring Starter Project之后,將會出現一個新的向導對話框(見圖1.3)。向導的第一頁會詢問一些項目的通用信息,比如項目名稱、描述和其他必要的信息。如果你熟悉Maven pom.xml文件的內容,那么就可以識別出大多數的輸入域條目最終都會成為Maven的構建規范。對于Taco Cloud應用來說,我們可以按照圖1.3的樣子來填充對話框,然后選擇Next。
向導的下一頁會讓我們選擇要添加到項目中的依賴(見圖1.4)。注意,在對話框的頂部,我們可以選擇項目要基于哪個Spring Boot版本。它的默認值是最新的可用版本。一般情況下,最好使用默認值,除非你需要使用不同的版本。
至于依賴項本身,你可以打開各個區域并手動查找所需的依賴項,也可以在Available頂部的搜索框中對依賴進行搜索。對于Taco Cloud應用來說,我們最初的依賴項如圖1.4所示。

圖1.3 為Taco Cloud應用指定通用的項目信息

圖1.4 選擇Starter依賴
現在,你可以選擇Finish來生成項目并將其添加到工作空間中。但是,如果你還想多體驗一些功能,可以再次選擇Next,看一下新Starter項目向導的最后一頁,如圖1.5所示。

圖1.5 指定備用的Initializr地址
默認情況下,新項目的向導會調用Spring Initializr來生成項目。通常情況下,沒有必要覆蓋默認值,這也是我們可以在向導的第二頁直接選擇Finish的原因。但是,如果你基于某種原因托管了自己的Initializr克隆版本(可能是本地機器上的副本或者公司防火墻內部運行的自定義克隆版本),那么你可能需要在選擇Finish之前修改Base Url輸入域的值,使其指向自己的Initializr實例。
選擇Finish之后,項目會從Initializr下載并加載到工作空間中。此時,要等待它加載和構建,然后你就可以開始開發應用的功能了。但首先,我們看一下Initializr都為我們提供了什么。
1.2.2 檢查Spring項目的結構
項目加載到IDE中之后,我們將其展開,看一下其中都包含什么內容。圖1.6展現了Spring Tool Suite中已展開的Taco Cloud項目。

圖1.6 Spring Tool Suite中所展現的初始Spring項目結構
你可能已經看出來了,這就是一個典型的Maven或Gradle項目結構,其中應用的源碼放到了“src/main/java”中,測試代碼放到了“src/test/java”中,而非Java的資源放到了“src/main/resources”中。在這個項目結構中,我們需要注意以下幾點。
● mvnw和mvnw.cmd:這是Maven包裝器(wrapper)腳本。借助這些腳本,即便你的機器上沒有安裝Maven,也可以構建項目。
● pom.xml:這是Maven構建規范,隨后我們將會深入介紹該文件。
● TacoCloudApplication.java:這是Spring Boot主類,它會啟動該項目。隨后,我們會詳細介紹這個類。
● application.properties:這個文件起初是空的,但是它為我們提供了指定配置屬性的地方。在本章中,我們會稍微修改一下這個文件,但是我會將配置屬性的詳細闡述放到第6章。
● static:在這個文件夾下,你可以存放任意為瀏覽器提供服務的靜態內容(圖片、樣式表、JavaScript等),該文件夾初始為空。
● templates:這個文件夾中存放用來渲染內容到瀏覽器的模板文件。這個文件夾初始是空的,不過我們很快就會往里面添加Thymeleaf模板。
● TacoCloudApplicationTests.java:這是一個簡單的測試類,它能確保Spring應用上下文成功加載。在開發應用的過程中,我們會將更多的測試添加進來。
隨著Taco Cloud應用功能的增長,我們會不斷使用Java代碼、圖片、樣式表、測試以及其他附屬內容來充實這個項目結構。不過,在此之前,我們先看一下Spring Initializr提供的幾個條目。
探索構建規范
在填充Initializr表單的時候,我們聲明項目要使用Maven來進行構建。因此,Spring Initializr所生成的pom.xml文件已經包含了我們所選擇的依賴。程序清單1.1展示了Initializr為我們提供的完整pom.xml。
程序清單1.1 初始的Maven構建規范
<?xml version = "1.0" encoding = "UTF-8"?><project
xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version> ?---Spring Boot的版本
<relativePath />
</parent>
<groupId>sia</groupId>
<artifactId>taco-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>taco-cloud</name>
<description>Taco Cloud Example</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency> ?---Starter依賴
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin> ?---Spring Boot插件
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
首先要注意的是<parent>元素,更具體來說是它的<version>子元素。這表明我們的項目要以spring-boot-starter-parent作為其父POM。除了其他的一些功能之外,這個父POM為Spring項目常用的一些庫提供了依賴管理。對于這些父POM中所涵蓋到的庫,我們不需要指定它們的版本,因為它會通過父POM繼承下來。這里的2.5.3表明要使用Spring Boot 2.5.3,所以就會根據這個版本的Spring Boot定義來繼承依賴管理。除了指定其他的依賴之外,2.5.3版本的Spring Boot依賴管理會指定底層的核心Spring框架的版本為5.3.9。
既然我們談到了依賴的話題,那么需要注意在<dependencies>元素下聲明了4個依賴。你可能會對前三個感到更熟悉一些。它們直接對應我們在Spring Tool Suite新項目向導中,點擊Finish之前所選擇的Spring Web、Thymeleaf和Spring Boot DevTools依賴。第四個依賴提供了很多有用的測試功能。我們沒有必要在專門的復選框中選擇它,因為Spring Initializr會假定我們要編寫測試(希望你能正確地開展這項工作)。
你可能也注意到了,除了DevTools依賴之外,其他的這些依賴的artifactId上都有starter這個單詞。Spring Boot starter依賴的特別之處在于它們本身并不包含庫代碼,而是傳遞性地拉取其他的庫。這種starter依賴主要有以下幾個好處。
● 構建文件會顯著減小并且更易于管理,因為這樣不必為所需的每個依賴庫都聲明依賴。
● 我們能夠根據它們所提供的功能來思考依賴,而不是根據庫的名稱。如果要開發Web應用,只需添加web starter依賴,而不必添加一堆單獨的庫。
● 我們不必再擔心庫版本的問題。你可以直接相信給定版本的Spring Boot,傳遞性引入的庫的版本都是兼容的。現在,你只需要關心使用的是哪個版本的Spring Boot就可以了。
最后,構建規范還包含一個Spring Boot插件。這個插件提供了一些重要的功能,如下所示:
● 它提供了一個Maven goal,允許我們使用Maven來運行應用;
● 它會確保依賴的所有庫都會包含在可執行JAR文件中,并且能夠保證它們在運行時類路徑下是可用的;
● 它會在JAR中生成一個manifest文件,將引導類(在我們的場景中,也就是TacoCloudApplication)聲明為可執行JAR的主類。
談到了引導類,我們打開它看一下。
引導應用
因為我們將會通過可執行JAR文件的形式來運行應用,所以很重要的一點就是要有一個主類,它將會在JAR運行的時候被執行。我們同時還需要一個最小化的Spring配置,用來引導該應用。這就是TacoCloudApplication類所做的事情,如程序清單1.2所示。
程序清單1.2 Taco Cloud的引導類
package tacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication ?---Spring Boot應用
public class TacoCloudApplication {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args); ?---運行應用
}
}
TacoCloudApplication盡管只有很少的代碼,但是包含了很多的內容。其中,最強大的一行代碼看上去很短:@SpringBootApplication注解明確表明這是一個Spring Boot應用。但是,@SpringBootApplication遠比看上去更強大。
@SpringBootApplication是一個組合注解,組合了3個其他的注解。
● @SpringBootConfiguration:將該類聲明為配置類。盡管這個類目前還沒有太多的配置,但是后續我們可以按需添加基于Java的Spring框架配置。這個注解實際上是@Configuration注解的特殊形式。
● @EnableAutoConfiguration:啟用Spring Boot的自動配置。我們隨后會介紹自動配置的更多功能。就現在來說,我們只需要知道這個注解會告訴Spring Boot自動配置它認為我們會用到的組件。
● @ComponentScan:啟用組件掃描。這樣我們能夠通過像@Component、@Controller、@Service這樣的注解聲明其他類,Spring會自動發現它們并將它們注冊為Spring應用上下文中的組件。
TacoCloudApplication另外一個很重要的地方是它的main()方法。這是JAR文件執行的時候要運行的方法。在大多數情況下,這個方法都是樣板代碼,我們編寫的每個Spring Boot應用都會有一個類似或完全相同的方法(類名不同則另當別論)。
這個main()方法會調用SpringApplication中靜態的run()方法,后者會真正執行應用的引導過程,也就是創建Spring的應用上下文。傳遞給run()的兩個參數中,一個是配置類,另一個是命令行參數。盡管傳遞給run()的配置類不一定要和引導類相同,但這是最便利和最典型的做法。
你可能并不需要修改引導類中的任何內容。對于簡單的應用程序來說,你可能會發現在引導類中配置一兩個組件是非常方便的,但是對于大多數應用,最好還是要為沒有實現自動配置的功能創建單獨的配置類。在本書的整個過程中,我們將會創建多個配置類,所以請繼續關注后續的細節。
測試應用
測試是軟件開發的重要組成部分。我們始終可以通過在命令行中構建應用、運行測試,從而實現項目的手動測試:
$ ./mvnw package
...
$ java -jar target/taco-cloud-0.0.1-SNAPSHOT.jar
或者,鑒于我們在使用Spring Boot,Spring Boot的Maven插件會使這個過程更加簡單:
$ ./mvnw spring-boot:run
但是,手動測試就意味著有人類的參與,因此有可能會出現人為的錯誤或者不一致的測試。自動測試會更加一致和可重復。
在這一點上,Spring Initializr為我們提供了一個測試類作為起步。程序清單1.3展現了這個測試類的概況。
程序清單1.3 應用測試類的概況
package tacos;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest ?---Spring Boot測試
public class TacoCloudApplicationTests {
@Test ?---測試方法
public void contextLoads() {
}
}
TacoCloudApplicationTests類中的內容并不多:這個類中只有一個空的測試方法。即便如此,這個測試類還是會執行必要的檢查,確保Spring應用上下文成功加載。如果你所做的變更導致Spring應用上下文無法創建,這個測試將會失敗,這樣你就可以做出反應來解決相關的問題。
@SpringBootTest會告訴JUnit在啟動測試的時候要添加上Spring Boot的功能。像@SpringBootApplication一樣,@SpringBootTest也是一個組合注解,它本身使用了ExtendWith(SpringExtension.class),從而能夠將Spring的測試功能添加到JUnit 5中。就現在來講,我們可以認為這個測試類與在main()方法中調用SpringApplication.run()是等價的。在這本書中,我們將會多次看到@SpringBootTest,并不斷見識它的威力。
最后,就是測試方法本身了。盡管@SpringBootTest會為測試加載Spring應用上下文,但是如果沒有任何測試方法,那么它其實什么事情都沒有做。即便沒有任何斷言或代碼,這個空的測試方法也會提示該注解完成了它的工作并成功加載Spring應用上下文。這個過程中出現任何問題,測試都會失敗。
要在命令行運行這個測試類及任意其他的測試類,我們都可以使用如下的Maven指令:
$ ./mvnw test
至此,我們已經看完了Spring Initializr提供的代碼。我們看到了一些用來開發Spring應用程序的基礎樣板,但是還沒有編寫任何的代碼。現在是時候啟動IDE、準備好鍵盤,向Taco Cloud應用程序添加一些自定義的代碼了。