1、背景
項目結構這東西一般并沒什麼非常嚴格的标準,業内所使用的習慣和規範也不盡相同。《阿裡巴巴Java開發手冊》中也有提到關于工程結構和應用分層相關的内容,如下:
它這裡面講的内容大概就是:關于一個正常的企業項目裡一種通用的項目結構和代碼層級劃分的指導意見。
按這本書上說的,一般分為如下幾層:
- 開放接口層
- 終端顯示層
- Web 層
- Service 層
- Manager 層
- DAO 層
- 外部接口或第三方平台
接下來,我們結合實際項目代碼結構,來制訂一下關于公司内部的項目結構和代碼分層
2、項目結構
2.1 總體結構
- 項目根目錄/src/main/java:放置項目Java源代碼
- 項目根目錄/src/main/resources:放置項目靜态資源和配置檔案
- 項目根目錄/src/test/java:放置項目測試用例代碼
2.2 server結構
各個目錄詳細介紹:
2.2.1 位于/src/main/java目錄下的Java源代碼的組織結構
java
|_annotation:放置項目自定義注解
|_aop:放置切面代碼
|_config:放置配置類
|_constant:放置常量、枚舉等定義
|__constants:存放常量定義
|__enums:存放枚舉定義
|_repository:放置與資料庫互動的實作類與接口
|_mapper:放置資料通路層代碼接口,一般是MapStruct的類
|_mq:放置消息中間件相關的代碼
|__producer:放置與MQ的生産者代碼
|__consumer:放置與MQ的消費者代碼
|_model:放置資料模型代碼
|__entity:放置資料庫實體對象定義
|__dto:存放資料傳輸對象定義
|__vo:存放顯示層對象定義
|_service:放置具體的業務邏輯代碼(接口和實作分離)
|__intf:存放業務邏輯接口定義
|__impl:存放業務邏輯實際實作
|_util:放置工具類和輔助代碼
|_web:放置Web相關的代碼
|__ interceptor:放置Web的攔截器代碼
|__security:放置與Web認證相關的代碼
|__filter:放置一些過濾器相關的代碼
|__controller:放置控制器代碼
關于DTO/VO/DO等資料模型定義的區分,Entity與DTO有強制要求,其它并無強制使用,下面定義供參考:
- Entity:與資料庫表結構一一對應,通過DAO層向上傳輸資料源對象,與表名保持一緻,不需要加字尾。
- DTO(Data Transfer Object):資料傳輸對象,Service或Manager向外傳輸的對象。
- BO(Business Object):業務對象。由Service層輸出的封裝業務邏輯的對象。
- AO(Application Object):應用對象。在Web層與Service層之間抽象的複用對象模型,極為貼近展示層,複用度不高。
- VO(View Object):顯示層對象,通常是Web向模闆渲染引擎層傳輸的對象。
- Query:資料查詢對象,各層接收上層的查詢請求。注意超過2個參數的查詢封裝,禁止使用Map類來傳輸。
2.2.2 位于/src/main/resources目錄,裡面主要存放靜态配置檔案和頁面靜态資源等東西:
resources
|_i18n:國際化語言資源檔案夾
|_application.yml:通用的應用配置
|_application-dev.yml:開發環境的配置
|_application-test.yml:測試環境的配置
|_application-prod.yml:生産環境的配置
|_banner.txt:Banner文字
|_bootstrap.yml:項目啟動時的配置,記錄nacos的位址
|_logback.yml:日志格式配置
2.3 api接口項目結構
各個目錄詳細介紹:
2.3.1 位于/src/main/java目錄下的Java源代碼的組織結構
java
|_config:放置配置類
|_api:FeignClient對外接口定義
|_model:放置資料模型代碼
|_ao:應用對象
|_bo:業務對象
|_query:資料查詢對象
|_vo:顯示層對象
|_response:響應對象
2.3.2 位于/src/main/resources目錄,裡面主要存放靜态配置檔案:
resources
|_META-INF:
|_spring.factories:自動裝配類的定義
3、服務間調用關系
4、項目内部請求關系
4、一些注意事項
1、Contorller層參數傳遞建議不要使用HashMap,建議使用資料模型定義
2、Controller層裡可以做參數校驗、異常抛出等操作,但建議不要放太多業務邏輯,業務邏輯盡量放到Service層代碼中去做
3、Service層做實際業務邏輯,可以按照功能子產品做好定義和區分,互相可以調用
4、功能子產品Service之間引用時,建議不要滲透到Repository層,基于Service層進行調用和複用比較合理
5、業務邏輯層Service和資料庫DAO層的操作對象不要混用。Controller層的資料對象不要直接滲透到Repository層;同理資料表實體對象Entity也不要直接傳到Controller層進行輸出或展示。