Spring Cloud工程模塊劃分
現在網絡上都在講Spring Cloud
的各個組件,但當我們自己也把Spring Cloud
引入進來的時候,卻發現第一個要解決的問題是:
工程的模塊如何劃分
在之前我寫過一篇重構購物車的過程的文章,下面就以這個購物車工程,來說明當時我是如何思考和如何做的。
工程要分幾個模塊
API模塊
當時的購物車工程是基於Spring Cloud
搭建的,並對外暴露Resful
接口。那麼第一個要思考的問題是,調用方如何使用購物車的微服務接口呢。有一種方式是由服務提供方生成一個SDK
包,調用方引入SDK
直接使用。這種方式目前應該是主流的做法,我個人也比較推崇這種方式。
因此,在工程裏,我們應該有個API
工程,這個工程定義了所有的微服務接口,然後可以使用一些構建工具,生成一個SDK
包。
shopcart-api
這個API
工程只有兩樣東西,一個是微服務接口,另外一個是DTO
對象。可以用package
來區分。
shopcart-api
api //包名
dto //包名
API
包裏可以用interface
定義出所有的微服務接口。
public interface ShopCartApi {
@RequestMapping(value = "/addToCart", method = RequestMethod.POST)
ResponseDTO addToCart(@RequestBody(required = false) AddToCartDTO request) throws Exception;
//其他接口
}
至於DTO
,是用於網絡傳輸的對象。當我們想提供微服務接口的時候,首先要考慮的就是入參和出參。一般來說可以用DTO
來表示的,所有DTO
對象都必須以DTO
結尾。這些DTO
會以SDK
包的形式,被調用方使用,調用方也必須將自己的業務數據封裝成DTO
入參,然後才能調用後端的微服務接口。
後面我們只需要使用Maven
或者Gradle
,構建一個SDK
包出來即可。如果是使用Maven
,那麼組合使用
mvn clean install
mvn clean deploy
就可以生成SDK包,並且上傳到公司的Maven私服上了。
server工程
server
工程用於存放controller
的,是實際對外的resful
微服務接口。
shopcart-server
server
工程必須依賴api工程,並去實現API
工程定義的微服務接口。
@RestController
public class ShopCartController implements ShopCartApi {
@Override
public ResponseDTO addSkuToShopCart(@RequestBody AddToCartDTO request) throws Exception {
return null;
}
}
這裏的ShopCartApi
就是之前在API
工程裏面定義的interface
。那麼server
工程裏的微服務接口可以直接去實現複雜的業務邏輯嗎?還是說再抽取一個模塊出來,專門用於實現業務邏輯呢?有一些公司,直接就在server
工程裏實現複雜的業務邏輯,然後用一個service
包,將業務邏輯servce
類放入進去。理由是,再抽取一個service
模塊用處不大呀,又無需用它來單獨build
一個包,供外部使用。其實這樣做也沒啥問題,但是通常來說,業務邏輯實現類,最好還是單獨抽取成一個模塊,除了層次清晰一些之外,業務邏輯實現類還有另外一些職責,就是【穩定】【靈活】【通用】【易於測試】,是需要精心設計的,建議別跟controller
混在一個模塊裏。
隨着業務不斷的增多,server
工程裏的controller
接口會不斷的增多和變化,但是經過精心設計的業務邏輯層,卻未必。
service工程
shopcart-service
如上所說,建議再建立一個service
工程,將核心的業務邏輯封裝起來。service
層對外暴露的對象是業務對象,統一以BO
結尾。這裏就會有個問題,server
工程調用完service
層的接口,獲取到BO
對象後,需要轉換成DTO
對象。不過現在已經有非常成熟性能又好的映射工具了。orika
就是其中的佼佼者。
模塊之間的依賴
server
工程依賴api
工程和service
工程。
需要再搞個domain模塊嗎
我理解的domain
也屬於業務邏輯的一部分,我個人是不太喜歡再搞個domain
模塊的,直接將domain放置在service
模塊裏即可。
客戶端如何調用服務端
在Spring Cloud裏,可以藉助feign
@FeignClient(value = "xxxxx",path = "/yyyyy")
public interface ShopCartClient extends ShopCartApi {
}
這裏的ShopCartApi
就是購物車工程中api模塊的接口類。想要調用購物車的接口,直接使用ShopCartClient
類即可。
進一步的思考
如果是使用
Spring Cloud
來提供微服務的話,由於是Resful
協議的,那麼調用方也可以不用SDK
的方式來調用服務方接口,直接用RestTemplate
調用即可,客戶端的接入成本很低,也不用擔心SDK
的接口版本問題。使用
SDK
來調用服務端接口的方式,使用起來確實比較方便,不看接口文檔都可以直接編程了。但是要小心服務端接口的版本問題。聽網友說
feign
不靈活,目前就我自己的使用情況看,還好,歡迎網友在本文評論中說出自己的看法。部分網友也提出,微服務工程本來就很細粒度了,無需在微服務工程裏再分模塊了,不然會增加複雜度,我覺得有一定的道理,但是目前我還是傾向於分模塊哈。。
使用領域驅動設計來劃分模塊
也有些公司,使用領域驅動設計來劃分模塊,這塊我目前還不太熟悉,不過看起來挺高大上的,也希望網友在文章的評論裏,多多發表意見。
寫一篇文章不容易哈,覺得文章寫的還行,請在文章上方左側的位置點一下贊哈,萬分感謝。如下圖: