看完這篇,別人的開源項目結(jié)構(gòu)應(yīng)該能看懂了

image

我為什么要寫這篇

近來,和不少初學(xué)Spring或Spring Boot的小伙伴私信交流了關(guān)于項目目錄結(jié)構(gòu)劃分和代碼分層的問題。

很多小伙伴表示網(wǎng)上下載下來的開源項目看不懂,項目結(jié)構(gòu)和代碼分層看得很蒙,不知道應(yīng)該以一個什么樣的思路去學(xué)習(xí)和吸收別人的項目。

好,今天熬夜肝了這篇文章,和大家一起來交流探討一下,不足之處也請小伙伴們批評指正。


先看看阿里是怎么約定的

我印象中,以前在看《阿里巴巴Java開發(fā)手冊》時,好像有關(guān)于工程結(jié)構(gòu)和應(yīng)用分層相關(guān)的內(nèi)容,于是我回翻了一下,果然有:

image

它這里面講的內(nèi)容大概就是:關(guān)于一個正常的企業(yè)項目里一種通用的項目結(jié)構(gòu)和代碼層級劃分的指導(dǎo)意見。

按這本書上說的,一般分為如下幾層:

  • 開放接口層
  • 終端顯示層
  • Web 層
  • Service 層
  • Manager 層
  • DAO 層
  • 外部接口或第三方平臺

由于書中的篇幅關(guān)系,它這地方講得比較籠統(tǒng)了,估計初學(xué)者看了還是會懵,所以接下來結(jié)合實際項目代碼結(jié)構(gòu),來嘮一嘮具體的項目結(jié)構(gòu)和代碼分層。


通常的項目結(jié)構(gòu)

首先說在前面的是:這東西并沒有一套通用的標(biāo)準(zhǔn),不同公司或者團(tuán)隊的使用習(xí)慣和規(guī)范也不盡相同。

我們就以當(dāng)下非常火熱的Spring Boot典型項目結(jié)構(gòu)為例,創(chuàng)建出來的項目應(yīng)該總體分為三大層:

image
  • 項目根目錄/src/main/java:放置項目Java源代碼
  • 項目根目錄/src/main/resources:放置項目靜態(tài)資源和配置文件
  • 項目根目錄/src/test/java:放置項目測試用例代碼

而位于/src/main/java目錄下的Java源代碼的組織結(jié)構(gòu)大家比較關(guān)心,這地方也只能給出一個通常典型的結(jié)構(gòu),畢竟不同項目和團(tuán)隊實踐不一樣,稍許有區(qū)別,但整體安排應(yīng)該差不多。而且如果是多模塊的項目的話,下面的結(jié)構(gòu)應(yīng)該只對應(yīng)其中一個模塊,其他模塊的代碼組織也大致差不多。

image

各個目錄詳細(xì)介紹:

|_annotation:放置項目自定義注解
|_aspect:放置切面代碼
|_config:放置配置類
|_constant:放置常量、枚舉等定義
   |__consist:存放常量定義
   |__enums:存放枚舉定義
|_controller:放置控制器代碼
|_filter:放置一些過濾、攔截相關(guān)的代碼
|_mapper:放置數(shù)據(jù)訪問層代碼接口
|_model:放置數(shù)據(jù)模型代碼
   |__entity:放置數(shù)據(jù)庫實體對象定義
   |__dto:存放數(shù)據(jù)傳輸對象定義
   |__vo:存放顯示層對象定義
|_service:放置具體的業(yè)務(wù)邏輯代碼(接口和實現(xiàn)分離)
   |__intf:存放業(yè)務(wù)邏輯接口定義
   |__impl:存放業(yè)務(wù)邏輯實際實現(xiàn)
|_utils:放置工具類和輔助代碼

然后接下來/src/main/resources目錄,里面主要存放靜態(tài)配置文件和頁面靜態(tài)資源等東西:

|_mapper:存放mybatis的XML映射文件(如果是mybatis項目)
|_static:存放網(wǎng)頁靜態(tài)資源,比如下面的js/css/img
   |__js:
   |__css:
   |__img:
   |__font:
   |__等等
|_template:存放網(wǎng)頁模板,比如thymeleaf/freemarker模板等
   |__header
   |__sidebar
   |__bottom
   |__XXX.html等等
|_application.yml       基本配置文件
|_application-dev.yml   開發(fā)環(huán)境配置文件
|_application-test.yml  測試環(huán)境配置文件
|_application-prod.yml  生產(chǎn)環(huán)境配置文件

當(dāng)然,這地方估計有一個很多人都會糾結(jié)的關(guān)于DTO/VO/DO數(shù)據(jù)模型定義的區(qū)分。

這在《阿里巴巴Java開發(fā)手冊》中倒是做了一個所謂的嚴(yán)格區(qū)分,那本書上是這樣去定義的:

  • DO(Data Object):與數(shù)據(jù)庫表結(jié)構(gòu)一一對應(yīng),通過DAO層向上傳輸數(shù)據(jù)源對象。
  • DTO(Data Transfer Object):數(shù)據(jù)傳輸對象,Service或Manager向外傳輸?shù)膶ο蟆?/li>
  • BO(Business Object):業(yè)務(wù)對象。由Service層輸出的封裝業(yè)務(wù)邏輯的對象。
  • AO(Application Object):應(yīng)用對象。在Web層與Service層之間抽象的復(fù)用對象模型,極為貼近展示層,復(fù)用度不高。
  • VO(View Object):顯示層對象,通常是Web向模板渲染引擎層傳輸?shù)膶ο蟆?/li>
  • Query:數(shù)據(jù)查詢對象,各層接收上層的查詢請求。注意超過2個參數(shù)的查詢封裝,禁止使用Map類來傳輸。

老實講,看到這么多對象的定義,我也是很蒙的。實際項目開發(fā)時,我覺得沒有必要刻意照搬去定義這么多層對象,這樣后續(xù)做對象轉(zhuǎn)換工作都能煩skr人。

出于簡單起見,我個人覺得,只要保證業(yè)務(wù)邏輯層Service和數(shù)據(jù)庫DAO層的操作對象嚴(yán)格劃分出來,確?;ハ嗖粷B透,不混用,問題應(yīng)該就不大。

比如在我上面舉例的這個項目的代碼結(jié)構(gòu)中,Service層處理的對象都定義在了dto包里,而DAO層處理的對象都放在了entity包里了。


項目結(jié)構(gòu)劃分總結(jié)

如果從一個用戶訪問一個網(wǎng)站的情況來看,對應(yīng)著上面的項目代碼結(jié)構(gòu)來分析,可以貫穿整個代碼分層:

image

對應(yīng)代碼目錄的流轉(zhuǎn)邏輯就是:

image

我想,應(yīng)該看得比較清楚了吧。

所以,以后每當(dāng)我們拿到一個新的項目到手時,只要按照這個思路去看別人項目的代碼,應(yīng)該基本都是能理得順的。


一些注意事項

1、Contorller層參數(shù)傳遞建議不要使用HashMap,建議使用數(shù)據(jù)模型定義

2、Controller層里可以做參數(shù)校驗、異常拋出等操作,但建議不要放太多業(yè)務(wù)邏輯,業(yè)務(wù)邏輯盡量放到Service層代碼中去做

3、Service層做實際業(yè)務(wù)邏輯,可以按照功能模塊做好定義和區(qū)分,相互可以調(diào)用

4、功能模塊Service之間引用時,建議不要滲透到DAO層(或者mapper層),基于Service層進(jìn)行調(diào)用和復(fù)用比較合理

5、業(yè)務(wù)邏輯層Service和數(shù)據(jù)庫DAO層的操作對象不要混用。Controller層的數(shù)據(jù)對象不要直接滲透到DAO層(或者mapper層);同理數(shù)據(jù)表實體對象Entity也不要直接傳到Controller層進(jìn)行輸出或展示。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容