專案結構說明
本文檔說明基於 AppFuse Server 的專案推薦結構,以 app-server 參考實作為範例。
標準專案結構
my-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/yourcompany/yourapp/
│ │ │ ├── config/ # 配置類別
│ │ │ ├── entity/ # 領域模型(Entity)
│ │ │ ├── repository/ # 資料存取層
│ │ │ ├── service/ # 業務邏輯層
│ │ │ ├── controller/ # REST API 控制器
│ │ │ └── Application.java # 主程式
│ │ └── resources/
│ │ ├── application.yml # Spring 內建屬性
│ │ └── {app-name}.yml # 應用程式自訂屬性
│ └── test/
│ └── java/
│ └── com/yourcompany/yourapp/
├── build.gradle.kts # Gradle 建置腳本
└── README.md # 專案說明
套件組織
config/ - 配置類別
存放 Spring Configuration 類別:
config/
├── SecurityConfig.java # 安全配置
├── CacheConfig.java # 快取配置
├── JpaAuditingConfig.java # JPA 審計配置
├── MailConfig.java # 郵件配置
├── TenantConfig.java # 多租戶配置
└── WebConfig.java # Web 配置
職責:
- 配置 Spring Beans
- 整合框架元件
- 環境特定設定
範例:參考 app-server/config
entity/ - 領域模型
按業務模組組織 Entity:
entity/
├── base/ # 基礎實體
│ ├── AuditableBase.java # 審計基底類別
│ ├── AuditableTenantEntity.java
│ ├── Country.java
│ └── Currency.java
├── tenant/ # 多租戶模組
│ └── Tenant.java
├── auth/ # 認證模組
│ ├── Account.java
│ ├── Role.java
│ └── Authority.java
├── sales/ # 銷售模組(業務範例)
│ ├── Product.java
│ ├── ProductCategory.java
│ └── ProductStatus.java
├── order/ # 訂單模組(業務範例)
│ ├── Order.java
│ ├── OrderItem.java
│ └── OrderStatus.java
└── customer/ # 客戶模組(業務範例)
├── Customer.java
├── Contact.java
└── Address.java
設計原則:
- 按業務領域劃分子套件
- 基礎類別放在
base/中 - Entity 專注於資料結構定義
範例:參考 app-server/entity
repository/ - 資料存取層
按業務模組組織 Repository:
repository/
├── tenant/
│ └── TenantRepository.java
├── auth/
│ ├── AccountRepository.java
│ └── AuthorityRepository.java
├── sales/
│ ├── ProductRepository.java
│ └── ProductCategoryRepository.java
├── order/
│ └── OrderRepository.java
└── customer/
└── CustomerRepository.java
職責:
- 定義資料存取介面
- 擴展 Spring Data JPA Repository
- 自定義查詢方法
範例:參考 app-server/repository
service/ - 業務邏輯層
按業務模組組織 Service:
service/
├── auth/
│ ├── AccountDetailsService.java
│ └── TokenBlacklistService.java
├── sales/
│ ├── ProductService.java
│ └── ProductCategoryService.java
├── order/
│ └── OrderService.java
├── customer/
│ └── CustomerService.java
└── cache/
├── UserCacheService.java
└── SessionCacheService.java
職責:
- 實作業務邏輯
- 協調多個 Repository 操作
- 處理交易邊界
範例:參考 app-server/service
controller/ - REST API 控制器
按業務模組組織 REST Controllers:
controller/
├── auth/
│ └── AuthController.java
├── sales/
│ └── ProductController.java
├── order/
│ └── OrderController.java
├── customer/
│ └── CustomerController.java
└── base/
├── ReferenceDataController.java
└── StagingFileController.java
職責:
- 處理 HTTP 請求/回應
- 參數驗證
- 呼叫 Service 執行業務邏輯
- 建構 HATEOAS 連結
範例:參考 app-server/controller
配置檔案組織
AppFuse 採用配置檔分離策略,將 Spring 內建屬性與應用程式自訂屬性分開管理:
配置檔命名慣例
| 檔案 | 內容 | 說明 |
|---|---|---|
application.yml | Spring 內建屬性 | server、spring、management、logging 等 |
{app-name}.yml | 應用程式自訂屬性 | app.* 等自訂配置 |
檔名 {app-name} 對應 spring.application.name,例如 app-server 專案使用 app-server.yml。
配置載入順序
appfuse-server 的 Environ 模組支援外部配置,載入順序如下(後者覆蓋前者):
1. classpath:application.yml ← Spring 內建屬性
2. classpath:{app-name}.yml ← 應用程式自訂屬性
3. ${app.home}/conf/{app-name}.yml ← 外部配置(部署時覆蓋)
application.yml(Spring 內建屬性)
存放 Spring 框架相關配置:
server:
servlet:
context-path: /app-server
spring:
application:
name: app-server
datasource:
url: jdbc:h2:file:${user.home}/var/data/appdb
jpa:
hibernate:
ddl-auto: update
logging:
level:
io.leandev.app: DEBUG
{app-name}.yml(應用程式自訂屬性)
存放應用程式特定的配置:
app:
storage:
type: database
jwt:
expiration: 900000
cors:
allowed-origins: "http://localhost:*"
外部配置(部署環境)
部署時可在 ${app.home}/conf/ 放置外部配置檔覆蓋預設值:
# 設定 app.home
export APP_HOME=/opt/app-server
# 建立外部配置
mkdir -p $APP_HOME/conf
cat > $APP_HOME/conf/app-server.yml << EOF
app:
cors:
allowed-origins: "https://app.example.com"
EOF
外部配置優先於 classpath 內的配置,適合管理環境特定設定。
Schema 管理
app-server 參考實作使用 Hibernate ddl-auto: update 自動管理 Schema:
spring:
jpa:
hibernate:
ddl-auto: update
ddl-auto 選項:
| 值 | 說明 | 適用環境 |
|---|---|---|
update | 自動新增欄位/表,不刪除 | 開發環境 |
validate | 僅驗證 Schema 一致性 | 生產環境(搭配遷移工具) |
create-drop | 啟動時建立、關閉時刪除 | 測試環境 |
none | 不做任何操作 | 由遷移工具管理 |
生產環境建議使用 Flyway 或 Liquibase 管理 Schema 遷移,
搭配 ddl-auto: validate 確保 Entity 與實際 Schema 一致。
測試結構
測試目錄鏡射 main 的套件結構:
test/java/com/yourcompany/yourapp/
├── entity/
│ └── sales/
│ └── ProductTest.java # 單元測試
├── repository/
│ └── sales/
│ └── ProductRepositoryTest.java # Repository 測試
├── service/
│ └── sales/
│ └── ProductServiceTest.java
└── controller/
└── sales/
└── ProductControllerTest.java # API 整合測試
架構設計原則
分層架構
app-server 採用分層架構(Layered Architecture),將程式碼按技術職責分層:
┌─────────────────────────────────────┐
│ controller/ │ ← HTTP 請求處理
├─────────────────────────────────────┤
│ service/ │ ← 業務邏輯
├─────────────────────────────────────┤
│ repository/ │ ← 資料存取
├─────────────────────────────────────┤
│ entity/ │ ← 領域模型
└─────────────────────────────────────┘
優點:
- 職責清晰,易於理解
- 各層可獨立測試
- 符合 Spring 生態系慣例
業務模組劃分
在每一層內,按業務模組(如 sales/、order/、customer/)組織程式碼:
entity/
├── sales/ # 銷售相關 Entity
├── order/ # 訂單相關 Entity
└── customer/ # 客戶相關 Entity
service/
├── sales/ # 銷售相關 Service
├── order/ # 訂單相關 Service
└── customer/ # 客戶相關 Service
這種「分層 + 模組」的組織方式兼顧了:
- 技術層面:清晰的依賴方向(controller → service → repository → entity)
- 業務層面:相關功能集中在同一子套件
配置分離
- Spring 內建屬性 →
application.yml - 應用程式自訂屬性 →
{app-name}.yml - 部署環境覆蓋 →
${app.home}/conf/{app-name}.yml - 敏感資訊 → 環境變數
下一步
參考資源
- app-server 專案結構 - 參考實作完整範例
- Spring Boot Project Structure