? 企業(yè)級(jí)項(xiàng)目結(jié)構(gòu)封裝釋義
如果你剛畢業(yè),作為JAVA新手程序員進(jìn)入一家企業(yè),拿到代碼之后,你有什么感覺呢?如果你沒有聽過多模塊、分布式這類的概念,那么多半會(huì)傻眼。為什么一個(gè)項(xiàng)目會(huì)有這么多個(gè)子項(xiàng)目?這個(gè)項(xiàng)目里為何沒有版本,這個(gè)parent是指向啥?
今天我們模擬真實(shí)企業(yè)場(chǎng)景,來讓大家掌握一些項(xiàng)目架構(gòu)方面的知識(shí)。
? 前提假設(shè)
我們是同一家公司woniu科技,這家公司有5個(gè)開發(fā)小組,其中3個(gè)小組負(fù)責(zé)開發(fā)運(yùn)營電影票務(wù)網(wǎng)站,另外2個(gè)小組開發(fā)運(yùn)營外賣網(wǎng)站。
? 思考
那么從技術(shù)管理的角度,幾個(gè)項(xiàng)目組之間需要有哪些層面上的相同呢?
一般而言,公司內(nèi)部會(huì)考慮統(tǒng)一技術(shù)棧和框架的版本,也會(huì)提供統(tǒng)一的工具類。
好處顯而易見:
-
方便進(jìn)行管理,比如,統(tǒng)一升級(jí)版本,統(tǒng)一加入某項(xiàng)功能等等。
-
降低學(xué)習(xí)研究的成本,企業(yè)級(jí)開發(fā)框架種類繁多,版本眾多,統(tǒng)一之后程序員要學(xué)習(xí)的技術(shù)是最小的,相關(guān)技術(shù)專家也可以深入的研究某項(xiàng)技術(shù)徹底hold住。
-
減少出問題的概率以及排錯(cuò)的成本,一旦出錯(cuò)所有人都可以加入解決問題。
-
統(tǒng)一的技術(shù)框架之間是兼容的,方便項(xiàng)目之間的互相操作、互相調(diào)用,共享代碼等等。
-
降低人員調(diào)動(dòng)、招聘及培訓(xùn)成本。
…
所以,一個(gè)公司會(huì)盡力統(tǒng)一能夠統(tǒng)一的一切,除非特殊的業(yè)務(wù)或者技術(shù)的需求。
? 統(tǒng)一規(guī)范
? 技術(shù)選型
一般而言,技術(shù)選型是一早確定的。比如選用SpringBoot還是Play框架,選用單體還是分布式,選用MySQL還是Oracle。選型結(jié)束之后變動(dòng)的成本巨大,一般不會(huì)大改。開發(fā)團(tuán)隊(duì)在需要使用某項(xiàng)技術(shù)之前,應(yīng)當(dāng)先向技術(shù)負(fù)責(zé)人確定是否有已經(jīng)定好的框架,避免不同團(tuán)隊(duì)之前使用不同的技術(shù)。
? 統(tǒng)一版本
技術(shù)框架選定之后,還需要統(tǒng)一版本。這個(gè)怎么做呢?
一個(gè)流行的解決方案是通過全公司共享一個(gè)總父項(xiàng)目,各個(gè)子項(xiàng)目不加版本,由這個(gè)總父項(xiàng)目來控制版本,子項(xiàng)目會(huì)根據(jù)情況自動(dòng)升級(jí)。
這種專門管理版本的項(xiàng)目,我們一般稱為BOM(Bill Of Materials 物料清單)。已經(jīng)成為非常成熟的模式。如果你沿著spring-boot的parent往上追溯也會(huì)找到spring-boot-dependencies,就是一個(gè)BOM。
這里需要了解下 <dependencyManagement> 這個(gè)標(biāo)簽,它會(huì)管理依賴的版本,包括依賴排除這些,但是不會(huì)為子項(xiàng)目加入這個(gè)依賴。這點(diǎn)跟 <dependency> 是不同的,這也是BOM的關(guān)鍵技術(shù)。
另外,子項(xiàng)目通過 <parent> 指定父項(xiàng)目。
比如woniu科技會(huì)創(chuàng)建一個(gè)woniu-parent項(xiàng)目,負(fù)責(zé)管理版本全局統(tǒng)一的父pom。
? 統(tǒng)一工具類
一般公司內(nèi)部都有自己的工具類,會(huì)提供一些類似如日期格式化,ID生成等等的工具類。這類的工具類是非常通用的,每個(gè)項(xiàng)目的每個(gè)模塊都會(huì)需要用上。所以會(huì)考慮直接在總父pom中加入依賴。一旦加入就是全局引入,所有項(xiàng)目就自動(dòng)獲得這個(gè)依賴。所以除了這個(gè)統(tǒng)一工具類的依賴以外,很少會(huì)再加入其他依賴。
比如woniu科技會(huì)創(chuàng)建一個(gè)woniu-commons項(xiàng)目(單純的maven-quickstart項(xiàng)目)來統(tǒng)一提供工具類,具體功能如下:
-
提供各種基礎(chǔ)工具
-
統(tǒng)一響應(yīng)格式(統(tǒng)一結(jié)果,但是通過攔截器封裝結(jié)果)
-
統(tǒng)一錯(cuò)誤碼
-
統(tǒng)一的異常父類
-
統(tǒng)一的ID生成工具
…
? 統(tǒng)一項(xiàng)目結(jié)構(gòu)
項(xiàng)目當(dāng)然可以是單體項(xiàng)目。但是既然是為了解決可能面對(duì)的復(fù)雜問題,我們就來模擬一個(gè)復(fù)雜的項(xiàng)目結(jié)構(gòu)。
這里涉及到maven多模塊項(xiàng)目的概念。
maven多模塊項(xiàng)目其實(shí)是指在一個(gè)項(xiàng)目中包含多個(gè)獨(dú)立的模塊項(xiàng)目,每個(gè)模塊可以單獨(dú)打包成jar或者war。如下圖所示。
最外層是一個(gè)總的項(xiàng)目(稱為總控pom),這個(gè)項(xiàng)目只有一個(gè)pom而沒有src等,僅用來管理依賴,并聯(lián)系起所有的模塊。
模塊項(xiàng)目指的是在項(xiàng)目目錄下的項(xiàng)目。可以是任何項(xiàng)目。
總控pom與子模塊怎么確認(rèn)呢?
-
總控pom里通過和確認(rèn)子模塊
-
子模塊通過確定總控pom
模塊與模塊之間通過來建立起聯(lián)系。
如下圖示意,藍(lán)色方框表示總控pom,淺藍(lán)色方框表示模塊:
理論上,模塊可以有任意多個(gè),也可以是任何名稱。這個(gè)問題跟技術(shù)無關(guān),理論上你可以叫dog,cat,miaomiaomiao,但是顯然不夠?qū)I(yè)和實(shí)用。這就是公司內(nèi)部要確定的規(guī)范了。
那么具體有哪些模塊呢?
這里舉例如下,woniu科技確定的統(tǒng)一的項(xiàng)目結(jié)構(gòu)及解釋如下:
-
common 項(xiàng)目工具模塊
-
facade 給外部用的AP接口,打包后發(fā)布給其他服務(wù)調(diào)用方作為接口來使用
-
service 服務(wù)
-
dao 數(shù)據(jù)庫訪問層
-
model 數(shù)據(jù)模型層
-
domain 領(lǐng)域?qū)樱脕砭酆蠌?fù)雜的領(lǐng)域模型
-
integration 集成層,集成外部的服務(wù),例如云服務(wù)
-
web 提供web服務(wù),目前這層基本沒有了
-
assembly 打包層,將所有內(nèi)容打包
下圖展示了最少模塊數(shù)量的一個(gè)多模塊項(xiàng)目,除了common和facade以外的內(nèi)容都放在assembly中
? 統(tǒng)一配置
多個(gè)開發(fā)組之間可能會(huì)共用一些資源,比如用同一個(gè)redis集群,mq集群。那么這些配置是一致的,能夠不重復(fù)配置是最理想的。萬一redis集群地址更改也不需要每個(gè)項(xiàng)目改動(dòng)。
還有一個(gè)可能是存在通用配置,比如日期格式在全公司是統(tǒng)一的,日志配置都是統(tǒng)一的,actuator暴露的端點(diǎn)也是一致的。
這類配置管理需求在spring-boot出現(xiàn)之前是非常難實(shí)現(xiàn)的。spring-boot的特性之一是外化配置,加上nacos的配置管理客戶端,將配置完全交給nacos來管理。
nacos支持共享配置,那么就可以將一個(gè)share.properties加入到每個(gè)項(xiàng)目中,管理公共配置。一旦配置變更就可以自動(dòng)在所有項(xiàng)目中啟用。
spring: Application: name: user cloud: nacos: config: server-addr: localhost:8848 shared-configs[0]: data-id: share.properties group: DEFAULT_GROUP refresh: true
比如,woniu科技的公共配置內(nèi)容包括:
-
環(huán)境配置
-
nacos地址
-
mq地址
-
redis地址
-
…
-
-
spring-boot配置
-
actuator配置
-
-
常用配置
-
mvc和json的日期格式
-
日志配置
-
總結(jié)
用下圖總結(jié)上文所述,希望大家有所收獲