Code Is Only Differentiator
源碼:https://github.com/shuxingliu/microservices
一、生成項目文件(設(shè)置開發(fā)環(huán)境)
SpringCloud是Spring Boot的子集,我們可以使用Spring Boot預(yù)先配置網(wǎng)頁(http://start.spring.io)來選擇構(gòu)建工具(Maven、Gradle)、項目元元數(shù)據(jù)(組名稱、工件名稱)。如果我們需要更多選擇,我們需要點擊"Switch to Full Version",在全部版本里,我們可以編輯更多的項目元數(shù)據(jù)信息(依賴項、打包格式、Java版本等),并選擇安全、Web服務(wù)器、關(guān)系型/非關(guān)系型數(shù)據(jù)庫、云服務(wù)的注冊/配置/路由/發(fā)現(xiàn)、微服務(wù)的熔斷等依賴項。我們要感謝Pivotol為我們提供了Spring Boot這么好的起點,大大簡化了JavaWeb應(yīng)用的開發(fā)。
本節(jié)示例中,我們使用Maven來作為構(gòu)建工具,工件命名為booking car,是一個開發(fā)打車微服務(wù)的演示項目,打包格式為jar,使用Java最新版本Java1.8,包的名稱設(shè)為:com.accenture.j2c.bookingcar,如下圖所示。

在頁面下面的依賴項,我們選擇了Web、Eureka Server等依賴項。


選擇依賴項后,界面顯示如下:

點擊Generate Project后,項目文件會打包成“項目名+zip”格式并自動下載到本地

我們使用NetBeans作為IDE,從項目zip文件導(dǎo)入剛才的項目


在導(dǎo)入項目的過程中,如果本地Maven庫里沒有聲明的依賴項,NetBeans會給我們提示,我們點擊“Resolve”即可,NetBeans會自動下載缺失的依賴項到本地Maven庫里。
項目文件導(dǎo)入后,我們發(fā)現(xiàn)項目中已經(jīng)有下列文件:

我們可以看到項目的包名為com.accenture.j2c.bookingcar
其中,main程序位于BookingcarApplication.java內(nèi),main調(diào)用了Spring Boot的SpringApplication.run()方法來啟動應(yīng)用程序。

二、EurekaClient的實現(xiàn)
為了能使微服務(wù)自動在Eureka服務(wù)器上注冊,bookingcar應(yīng)用要聲明為Eureka Client。通過以下的兩個步驟聲明即可。
1. 導(dǎo)入包:org.springframework.cloud.netflix.eureka.EnableEurekaClient;
2. 添加注解:@EnableEurekaClient

三、實體、值對象的實現(xiàn)
在上一節(jié)的分析中,我們也可以發(fā)現(xiàn),聚合中的實體、值對象位于戰(zhàn)術(shù)建模的最底層,聚合、服務(wù)、存儲庫都依賴于實體、值對象。領(lǐng)域事務(wù)的實現(xiàn)過于復(fù)雜,我們在本次演示里暫不涉及,以后可以單獨開辟一個單獨的章節(jié)將領(lǐng)域事件的實現(xiàn)。
我們把實體放到包com.accenture.j2c.bookingcar.domain.entity里,把值對象放到包:com.accenture.j2c.bookingcar.domain.vo里
各個實體類的實現(xiàn):
1. 抽象類Entity的實現(xiàn)
對于所有實體,ID和name都是常見的,因此,我們可以如下定義抽象類Entity作為實體的抽象。
Entity實現(xiàn)代碼如下所示:


2. Order聚合的實現(xiàn)
Order是打車管理系統(tǒng)中的核心聚合,Order實體會作為Order聚合的聚合根。對Order的描述放到OrderVO里。User及Driver的實現(xiàn)同Order類似,不再累述。
OrderVO的實現(xiàn):




Order實體的實現(xiàn):




四、存儲庫類的實現(xiàn)
在本示例中,對于每一類實體,包括用戶、司機、訂單等,在某個時段里都會存在多個實例。比如,我們會有很多的用戶,張三、李四、王二麻子,有很多的司機,有很多的訂單。對于每一類實體,我們需要有個統(tǒng)一的接口來保存并引用這些實體。比如,對于用戶實體,我們應(yīng)該有一個用戶存儲庫,用來存儲所有的用戶,管理用戶的增、刪、改、查。對于司機、訂單也是類似,也需要分別有一個存儲庫來對應(yīng)。
我們需要三個存儲庫:UserRepository,DriverRepository, OrderRepository。
開始時,我們首先創(chuàng)建兩個抽象:ReadOnlyRepository和Repository。ReadOnlyRepository用于提供只讀操作的抽象,例如get,getall等。而Repository用于執(zhí)行所有類型的操作,包括增、刪、改、查。
1. ReadOnlyRepository的實現(xiàn)如下:


2. Repository在ReadOnlyRepository基礎(chǔ)上進(jìn)行擴展,提供增加、刪除、更新等操作接口,實現(xiàn)如下:

3. UserRepository、DriverRepository、OrderRepository接口在Repository接口上擴展,UserRepository、DriverRepository增加了containsName以及findByName兩個操作,OrderRepository還添加了findByUserId接口,通過用戶Id找到對應(yīng)訂單。
僅以O(shè)rderRepository為例展示實現(xiàn)代碼:

4. 倉儲庫的實現(xiàn)
在Spring框架中,使用@Repository注解來定義實現(xiàn)存儲庫的bean。另外,我們把演示數(shù)據(jù)直接放到內(nèi)存中,代替實際的數(shù)據(jù)庫操作。
本次例程里,實現(xiàn)了用戶和訂單的倉儲庫。僅以訂單的倉儲庫實現(xiàn)為例:





五、領(lǐng)域服務(wù)類的實現(xiàn)
領(lǐng)域服務(wù)定義了CRUD和一些界面操作。
我們抽象出ReadOnlyBaseService基類和BaseService基類,以及DomainService接口
1. ReadOnlyBaseService的實現(xiàn)如下:

2. BaseService繼承于ReadOnlyBaseService,實現(xiàn)如下:


3. 在Spring框架中,使用@Repository注解來定義實現(xiàn)領(lǐng)域服務(wù)的bean。對訂單操作的領(lǐng)域服務(wù)實現(xiàn)如下:



六、REST控制器類的實現(xiàn)
微服務(wù)最終會提供Restful接口給外面的程序調(diào)用。在微服務(wù)實現(xiàn)中,REST控制器是必不可少的。REST控制器用來處理HTTP請求,有四個常用的注解。
@RestController:類級注解,表明該類是REST控制器,用來處理HTTP請求,即表明該類可以提供Restful接口。
@RequestMapping:1)類級別,將URI映射到類上;2)方法級別:將路徑映射到不同的方法。從這兒可以看出,一個微服務(wù)可以通過@RequestMapping注解映射不同的接口。
@RequestParam和PathVariable用來傳遞HTTP請求的參數(shù)。在someUrl/{param=value}中的param可以通過@RequestParam將HTTP請求的參數(shù)和方法的參數(shù)綁定,而someUrl/{paramId}的paramId可通過@Pathvariable注解綁定它傳過來的值到方法的參數(shù)上。
本例程中,為了更好地演示,除了實現(xiàn)了上節(jié)里設(shè)計的使用用戶Id查找訂單的微服務(wù)接口外,還實現(xiàn)了使用訂單Id查詢訂單、使用用戶id查找用戶,使用用戶名字查找用戶等接口。這四個接口的端點如下:
使用用戶Id查找訂單:http://.../v1/order?userid={userid}
使用訂單id查詢訂單:http://.../v1/order/{id}
使用用戶id查找用戶:http://.../v1/user/{id}
使用用戶名稱查找用戶:http://.../v1/user?name={name}
我們使用了兩個控制器類UserController和OrderController來實現(xiàn)上面的四個接口端點
1. UserController的實現(xiàn)如下:



2. OrderController的實現(xiàn)如下:



七. 應(yīng)用屬性的配置
要使微服務(wù)自動注冊到Eureka
Server里,我們要配置應(yīng)用的屬性。
應(yīng)用屬性的文件名稱為application.properties,在項目中的路徑如下:

本實現(xiàn)中,配置如下:
spring.application.name=bookingcar-lsx
spring.freemarker.enabled=false
spring.thymeleaf.cache=false
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
server.port=2227
八、測試REST API
1. 按照系列文章中第一部分的描述,啟動Eureka Server

2. 選擇bookingcar項目,右鍵彈出快捷菜單

3. 在Run Maven的窗口里,Goals輸入"spring-boot:run"

4. Bookingcar應(yīng)用啟動后,刷新Eureka Server的界面,我們會發(fā)現(xiàn)bookingcar的微服務(wù)已經(jīng)在“Instances currently registered with Eureka"下

5. 點擊微服務(wù)后面的鏈接,我們會進(jìn)入微服務(wù)的入口,輸入不同的請求參數(shù),我們可以觀察到不同的反饋。
1) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user/1
查找id為1的用戶,結(jié)果如下:

2) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user?name=2
查找用戶名為2的用戶,結(jié)果如下:

3)http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order/2
查找id為2的訂單,結(jié)果如下:

4) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order?userid=1
查找用戶id為1的訂單集合,結(jié)果如下:

利用Spring Cloud實現(xiàn)微服務(wù)(七)- 內(nèi)部調(diào)用
利用Spring Cloud實現(xiàn)微服務(wù)(六)- 服務(wù)網(wǎng)關(guān)
利用Spring Cloud實現(xiàn)微服務(wù)(五)- 負(fù)載均衡
利用Spring Cloud實現(xiàn)微服務(wù)(三)- 業(yè)務(wù)領(lǐng)域驅(qū)動微服務(wù)設(shè)計