官术网_书友最值得收藏!

3.1 創(chuàng)建Spring Boot項(xiàng)目

3.1.1 利用Spring Initializr創(chuàng)建項(xiàng)目

如2.3.1節(jié)所述,開發(fā)一個新的Spring Boot項(xiàng)目,首先要利用Spring Boot Initializr創(chuàng)建符合Spring Boot標(biāo)準(zhǔn)的項(xiàng)目,Initializr的工作原理與使用Maven Archetype創(chuàng)建項(xiàng)目是完全一致的,但I(xiàn)nitializr對創(chuàng)建Spring Boot項(xiàng)目更友好。

首先,打開Spring Boot Initializr官網(wǎng),將項(xiàng)目類型設(shè)定為Maven,項(xiàng)目語言設(shè)定為Java,此外還有以下參數(shù)需要指定:

? Spring Boot版本:2.2.10

? Group:com.broadview

? Artifact:coupon-cloud-center

? Name:broadview-coupon

? Package name:com.broadview.coupon

? Packaging:jar

? Java:8

然后單擊GENERATE按鈕,網(wǎng)站將產(chǎn)生一個空白的Spring Boot項(xiàng)目,并自動下載到本地,開發(fā)者可以將該項(xiàng)目導(dǎo)入自己熟悉的IDE,如IntelliJ。

此外,開發(fā)者也可以使用STS(Spring Tool Suit,Spring工具包)創(chuàng)建Spring Boot項(xiàng)目,STS的操作方式本書不會涉及,請讀者自行探索。

3.1.2 項(xiàng)目結(jié)構(gòu)

按照業(yè)務(wù)需求衡量優(yōu)惠券項(xiàng)目,該項(xiàng)目復(fù)雜度相對較高,因此在設(shè)計(jì)系統(tǒng)時,我們將遵循DDD(Domain Drive Design,領(lǐng)域驅(qū)動設(shè)計(jì))的最佳實(shí)踐,先創(chuàng)建一個主項(xiàng)目spring-boot-starter-parent,用于定義子項(xiàng)目間的關(guān)系和整個項(xiàng)目需要使用的依賴,再按照不同的業(yè)務(wù)領(lǐng)域?qū)⒄w項(xiàng)目分解為如下四個子項(xiàng)目:

? coupon-shared-components:提供工具類和POJO(Plain Ordinary Java Object,簡單Java對象)的共享組件。

? coupon-calculation-service:提供優(yōu)惠券計(jì)算服務(wù)。

? coupon-template-service:提供定制優(yōu)惠券規(guī)則模板服務(wù)。

? coupon-user-service:提供用戶領(lǐng)取和消費(fèi)優(yōu)惠券服務(wù)。

四個子項(xiàng)目各自負(fù)責(zé)自己的業(yè)務(wù)邏輯,并且它們的parent都是主項(xiàng)目。第一個子項(xiàng)目(coupon-shared-components)為其他三個子項(xiàng)目(coupon-calculation-service、coupon-template-service、coupon-user-service)提供工具類,除第一個子項(xiàng)目外,其他三個子項(xiàng)目均為Spring Boot項(xiàng)目。

此業(yè)務(wù)系統(tǒng)是依據(jù)某電商的真實(shí)優(yōu)惠券業(yè)務(wù)相關(guān)場景抽象脫敏而來,其整體架構(gòu)根據(jù)不同的用戶場景和邊界上下文(bounded context)將被分解為三個不同的微服務(wù)(即三個子項(xiàng)目coupon-calculation-service、coupon-template-service、coupon-user-service)。

此外,子項(xiàng)目coupon-shared-components為所有微服務(wù)(coupon-calculation-service、coupon-template-service、coupon-user-service)提供工具類,即該子項(xiàng)目被三個微服務(wù)所依賴。

從項(xiàng)目管理的角度評估系統(tǒng),設(shè)計(jì)者傾向于將整體項(xiàng)目設(shè)計(jì)為一個父項(xiàng)目,其下有多個子項(xiàng)目。原因在于,當(dāng)項(xiàng)目組采用敏捷開發(fā)時,可以將多個子項(xiàng)目并行開發(fā)。如果將所有功能都分配在一個大項(xiàng)目之中,那么并行開發(fā)的難度將會提高很多,而且對多團(tuán)隊(duì)協(xié)作開發(fā)也不友好。

按照上述設(shè)計(jì),此項(xiàng)目應(yīng)當(dāng)將根目錄作為父項(xiàng)目,其余四個項(xiàng)目作為該項(xiàng)目下的子項(xiàng)目,但項(xiàng)目實(shí)現(xiàn)卻與此設(shè)計(jì)略有出入。這是因?yàn)樵诒緯校琒pring Boot內(nèi)容只是全書的一部分,為維護(hù)項(xiàng)目的擴(kuò)展性,筆者將所有與Spring Boot相關(guān)的內(nèi)容合并為一個模塊,并將其根目錄設(shè)定為父項(xiàng)目(如何擴(kuò)展此項(xiàng)目?后續(xù)章節(jié)將會一一呈現(xiàn))。

基于上述原因,項(xiàng)目的最終結(jié)構(gòu)如圖3-1所示。

圖3-1 項(xiàng)目結(jié)構(gòu)

3.1.3 在項(xiàng)目中添加Starter

為了開發(fā)的便捷性和可控的依賴管理,Spring Boot官方為廣大開發(fā)者提供了各種各樣的Starter(關(guān)于Starter請回顧2.3.1節(jié))。在本節(jié)中,筆者將通過優(yōu)惠券項(xiàng)目向讀者展示Spring Boot Starter的各種功能。

在優(yōu)惠券項(xiàng)目結(jié)構(gòu)中,coupon-shared-components是一個公共模塊,它為其他子模塊提供工具類,我們無需為其添加任何Starter。coupon-calculation-service主要提供計(jì)算邏輯服務(wù),我們需要通過添加spring-boot-starter-web依賴項(xiàng)引入Web支持,相關(guān)代碼如下:

此外,該項(xiàng)目作為Spring Boot項(xiàng)目要成功運(yùn)行,必須引入spring-boot-starter,但在項(xiàng)目中卻沒有顯式地引入,為什么?要知道原因,可以利用Maven的dependency tree插件進(jìn)行分析,相關(guān)分析日志如下:

分析上面的日志,可見Web Starter(spring-boot-starter-web)依賴于spring-boot-starter,calculation service直接依賴于Web Starter,從而間接地引入了spring-boot-starter依賴,因此無需重復(fù)顯式地引入。

由于coupon template service需要訪問數(shù)據(jù)庫,因此它的依賴中必須引入兩種Starter,相關(guān)代碼如下:

同calculation service一樣,我們不需要專門顯式地引入spring-boot-starter。但由于它使用JPA訪問數(shù)據(jù)庫,所以需要加載對應(yīng)的數(shù)據(jù)庫驅(qū)動,本項(xiàng)目使用MySQL數(shù)據(jù)庫,因此引入的是MySQL驅(qū)動,加載MySQL驅(qū)動的代碼如下:

此外,application.yml文件中對應(yīng)的數(shù)據(jù)庫配置也不可缺少(參考Spring Boot配置文檔),否則該項(xiàng)目將無法啟動。

coupon user service也需要訪問數(shù)據(jù)庫并對外提供Web Service,因此它需要的Starter和template service的Starter是相同的。

三個微服務(wù)都要滿足一些額外的非功能性需求,例如提供簡單的監(jiān)控和JMX功能等,根據(jù)2.3.4節(jié)Actuator的介紹,項(xiàng)目需要引入Actuator Starter,具體代碼如下:

引入Actuator Starter之后,通過暴露各種不同的endpoint,Spring Boot項(xiàng)目可以提供以下功能:

? 監(jiān)控服務(wù)的健康狀況。

? 收集并展示各種所需的系統(tǒng)指標(biāo)。

? 提供JMX console。

3.1.4 偷懶神器lombok

本項(xiàng)目除基于Spring Boot的服務(wù)外,還有一個共享組件,主要提供工具類和POJO,對于傳統(tǒng)的POJO,與之相伴的是臃腫的Getter和Setter代碼,而且使用者還要設(shè)計(jì)如何構(gòu)造POJO對象,這些代碼大多不可或缺但卻非常煩瑣。雖然很多IDE都提供生成工具,但這種代碼風(fēng)格完全不符合代碼整潔之道,開發(fā)者需要更加優(yōu)雅的解決方案。基于當(dāng)前技術(shù)棧,當(dāng)然非lombok莫屬。

要使用lombok,需要為項(xiàng)目引入新依賴,具體代碼如下:

lombok是一個在編譯期處理代碼注釋(Annotation)的處理器,它提供了很多簡單明了的注釋供開發(fā)者使用,以此減少代碼量。此外,它還通過注釋提供了很多經(jīng)典設(shè)計(jì)模式的最佳實(shí)踐。

如何簡化大量必需而又煩瑣的代碼,以一個簡單的POJO為例,代碼如下:

上述lombok代碼的運(yùn)行效果如下:

? Data注釋:產(chǎn)生所有屬性(field)的getter、setter、toString、equals、hashcode方法和一個構(gòu)造函數(shù)。這個構(gòu)造函數(shù)支持兩種屬性,一種是final修飾的屬性,另一種是非final修飾但標(biāo)有@NonNull的屬性。

? NoArgsConstructor和AllArgsConstructor注釋:顧名思義,就是各自產(chǎn)生一個無參數(shù)構(gòu)造函數(shù)和一個全參數(shù)構(gòu)造函數(shù)。此外,lombok還提供各種構(gòu)造函數(shù)的注釋。

? Builder注釋:與Data不同,這是建造者(Builder)模式的一種實(shí)現(xiàn)方式。任何class只要添加了lombok的Builder注釋,那么調(diào)用者在使用該class時,就可以按照建造者模式來構(gòu)造此class的對象。

此外,lombok還提供了大量的代碼最佳實(shí)踐。比如Spring框架一般都推薦采用unchecked exception的方式來構(gòu)建代碼,但是在JDK中仍然存在大量的checked exception,解決此問題的較好方式是捕捉checked exception,再將其轉(zhuǎn)化為runtime exception,從而無需逐層捕獲異常。未使用lombok時的代碼如下所示:

雖然可以達(dá)到捕獲異常的目的,但是代碼不夠簡潔、優(yōu)雅。如果使用lombok的@SneakyThrows注解,則代碼會簡潔許多,示例如下:

事實(shí)上,lombok提供了非常多的功能來簡化代碼,筆者在本書中只演示了上述功能,更多的lombok功能請讀者自己學(xué)習(xí)。

請注意,在引入lombok之后必須在IDE中安裝相應(yīng)的插件,否則將無法編譯和運(yùn)行含有l(wèi)ombok注釋的代碼。關(guān)于在IDE中安裝lombok插件的過程,請讀者自行研究。

主站蜘蛛池模板: 宁海县| 马边| 彩票| 秭归县| 临桂县| 永和县| 柳江县| 马公市| 正镶白旗| 南雄市| 宽城| 米泉市| 女性| 八宿县| 子长县| 安塞县| 古浪县| 青田县| 斗六市| 乐都县| 天峻县| 宜兰市| 手机| 石渠县| 卫辉市| 栖霞市| 武城县| 康平县| 临汾市| 台中市| 江口县| 通河县| 于田县| 治多县| 沙坪坝区| 仙桃市| 灵璧县| 潼南县| 娄烦县| 衡山县| 青海省|