Code Is Only Differentiator
源碼:https://github.com/shuxingliu/microservices
一、生成項目文件(設置開發環境)
SpringCloud是Spring Boot的子集,我們可以使用Spring Boot預先配置網頁(http://start.spring.io)來選擇構建工具(Maven、Gradle)、項目元元數據(組名稱、工件名稱)。如果我們需要更多選擇,我們需要點擊"Switch to Full Version",在全部版本里,我們可以編輯更多的項目元數據信息(依賴項、打包格式、Java版本等),并選擇安全、Web服務器、關系型/非關系型數據庫、云服務的注冊/配置/路由/發現、微服務的熔斷等依賴項。我們要感謝Pivotol為我們提供了Spring Boot這么好的起點,大大簡化了JavaWeb應用的開發。
本節示例中,我們使用Maven來作為構建工具,工件命名為booking car,是一個開發打車微服務的演示項目,打包格式為jar,使用Java最新版本Java1.8,包的名稱設為:com.accenture.j2c.bookingcar,如下圖所示。
在頁面下面的依賴項,我們選擇了Web、Eureka Server等依賴項。
選擇依賴項后,界面顯示如下:
點擊Generate Project后,項目文件會打包成“項目名+zip”格式并自動下載到本地
我們使用NetBeans作為IDE,從項目zip文件導入剛才的項目
在導入項目的過程中,如果本地Maven庫里沒有聲明的依賴項,NetBeans會給我們提示,我們點擊“Resolve”即可,NetBeans會自動下載缺失的依賴項到本地Maven庫里。
項目文件導入后,我們發現項目中已經有下列文件:
我們可以看到項目的包名為com.accenture.j2c.bookingcar
其中,main程序位于BookingcarApplication.java內,main調用了Spring Boot的SpringApplication.run()方法來啟動應用程序。
二、EurekaClient的實現
為了能使微服務自動在Eureka服務器上注冊,bookingcar應用要聲明為Eureka Client。通過以下的兩個步驟聲明即可。
1. 導入包:org.springframework.cloud.netflix.eureka.EnableEurekaClient;
2. 添加注解:@EnableEurekaClient
三、實體、值對象的實現
在上一節的分析中,我們也可以發現,聚合中的實體、值對象位于戰術建模的最底層,聚合、服務、存儲庫都依賴于實體、值對象。領域事務的實現過于復雜,我們在本次演示里暫不涉及,以后可以單獨開辟一個單獨的章節將領域事件的實現。
我們把實體放到包com.accenture.j2c.bookingcar.domain.entity里,把值對象放到包:com.accenture.j2c.bookingcar.domain.vo里
各個實體類的實現:
1. 抽象類Entity的實現
對于所有實體,ID和name都是常見的,因此,我們可以如下定義抽象類Entity作為實體的抽象。
Entity實現代碼如下所示:
2. Order聚合的實現
Order是打車管理系統中的核心聚合,Order實體會作為Order聚合的聚合根。對Order的描述放到OrderVO里。User及Driver的實現同Order類似,不再累述。
OrderVO的實現:
Order實體的實現:
四、存儲庫類的實現
在本示例中,對于每一類實體,包括用戶、司機、訂單等,在某個時段里都會存在多個實例。比如,我們會有很多的用戶,張三、李四、王二麻子,有很多的司機,有很多的訂單。對于每一類實體,我們需要有個統一的接口來保存并引用這些實體。比如,對于用戶實體,我們應該有一個用戶存儲庫,用來存儲所有的用戶,管理用戶的增、刪、改、查。對于司機、訂單也是類似,也需要分別有一個存儲庫來對應。
我們需要三個存儲庫:UserRepository,DriverRepository, OrderRepository。
開始時,我們首先創建兩個抽象:ReadOnlyRepository和Repository。ReadOnlyRepository用于提供只讀操作的抽象,例如get,getall等。而Repository用于執行所有類型的操作,包括增、刪、改、查。
1. ReadOnlyRepository的實現如下:
2. Repository在ReadOnlyRepository基礎上進行擴展,提供增加、刪除、更新等操作接口,實現如下:
3. UserRepository、DriverRepository、OrderRepository接口在Repository接口上擴展,UserRepository、DriverRepository增加了containsName以及findByName兩個操作,OrderRepository還添加了findByUserId接口,通過用戶Id找到對應訂單。
僅以OrderRepository為例展示實現代碼:
4. 倉儲庫的實現
在Spring框架中,使用@Repository注解來定義實現存儲庫的bean。另外,我們把演示數據直接放到內存中,代替實際的數據庫操作。
本次例程里,實現了用戶和訂單的倉儲庫。僅以訂單的倉儲庫實現為例:
五、領域服務類的實現
領域服務定義了CRUD和一些界面操作。
我們抽象出ReadOnlyBaseService基類和BaseService基類,以及DomainService接口
1. ReadOnlyBaseService的實現如下:
2. BaseService繼承于ReadOnlyBaseService,實現如下:
3. 在Spring框架中,使用@Repository注解來定義實現領域服務的bean。對訂單操作的領域服務實現如下:
六、REST控制器類的實現
微服務最終會提供Restful接口給外面的程序調用。在微服務實現中,REST控制器是必不可少的。REST控制器用來處理HTTP請求,有四個常用的注解。
@RestController:類級注解,表明該類是REST控制器,用來處理HTTP請求,即表明該類可以提供Restful接口。
@RequestMapping:1)類級別,將URI映射到類上;2)方法級別:將路徑映射到不同的方法。從這兒可以看出,一個微服務可以通過@RequestMapping注解映射不同的接口。
@RequestParam和PathVariable用來傳遞HTTP請求的參數。在someUrl/{param=value}中的param可以通過@RequestParam將HTTP請求的參數和方法的參數綁定,而someUrl/{paramId}的paramId可通過@Pathvariable注解綁定它傳過來的值到方法的參數上。
本例程中,為了更好地演示,除了實現了上節里設計的使用用戶Id查找訂單的微服務接口外,還實現了使用訂單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來實現上面的四個接口端點
1. UserController的實現如下:
2. OrderController的實現如下:
七. 應用屬性的配置
要使微服務自動注冊到Eureka
Server里,我們要配置應用的屬性。
應用屬性的文件名稱為application.properties,在項目中的路徑如下:
本實現中,配置如下:
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應用啟動后,刷新Eureka Server的界面,我們會發現bookingcar的微服務已經在“Instances currently registered with Eureka"下
5. 點擊微服務后面的鏈接,我們會進入微服務的入口,輸入不同的請求參數,我們可以觀察到不同的反饋。
1) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user/1
查找id為1的用戶,結果如下:
2) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/user?name=2
查找用戶名為2的用戶,結果如下:
3)http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order/2
查找id為2的訂單,結果如下:
4) http://cpx-bkdhx46cy4h.dir.svc.accenture.com:2227/v1/order?userid=1
查找用戶id為1的訂單集合,結果如下:
利用Spring Cloud實現微服務(三)- 業務領域驅動微服務設計