# Java 模块目录结构指南

## 文档定位

本文档约定的是 `ineed-core` 及同类 Java Maven 仓库中的“模块物理目录结构”。

它回答的是：

- 一个目标目录到底应该是聚合模块、BOM 模块、普通代码模块，还是业务聚合模块
- 什么类型的模块应该有 `src`
- 什么类型的模块只能有 `pom.xml` 和子模块目录，不能生成 `src`

如果你要创建的是业务聚合模块骨架，继续读 [business-module-layout-guide.md](../project-development/business-module-layout-guide.md)。
如果你要确认当前仓库真实声明了哪些模块，继续读 [module-inventory.md](module-inventory.md)。

## 先判断模块类型，再决定目录结构

开发者、代码生成器或自动化工具在创建 Java 模块前，必须先判断目标属于哪一类。

当前至少区分四类：

| 类型 | 典型示例 | `packaging` | 是否应有 `src` |
|------|----------|-------------|----------------|
| 根聚合模块 | `ineed-core/` | `pom` | 否 |
| 分组聚合模块 | `ineed-core-modules/`、`ineed-core-reactive-modules/`、`ineed-core-tests/`、`ineed-core-starters/` | `pom` | 否 |
| BOM 模块 | `ineed-core-bom/` | `pom` | 否 |
| 普通代码模块 | `ineed-core-base/`、`ineed-core-data-base/`、`ineed-rdb-metadata/`、`ineed-core-webmvc/`、`ineed-core-data-jpa/`、`ineed-starter-druid/`、`ineed-core-test-webmvc/` | 通常为 `jar` 默认值 | 是 |

额外说明：

- 业务聚合模块属于“特殊聚合模块”，目录结构继续按 [business-module-layout-guide.md](../project-development/business-module-layout-guide.md) 处理
- 不允许在还没判断模块类型前，就机械地创建 `src/main/java`

## 根聚合模块

根聚合模块只负责：

- 声明顶级 `<modules>`
- 统一版本、插件和依赖管理
- 作为整个仓库入口

标准形态：

```text
{repo-root}/
  pom.xml
  README.md
  docs/
  {child-module-a}/
  {child-module-b}/
```

规则：

- 根聚合模块本身不放 `src/main/java`
- 不在根聚合模块下直接放业务 Java 源码
- 新增顶层模块前，先确认是否真的需要进入根 `pom.xml` 的 `<modules>`

## 分组聚合模块

分组聚合模块本身是 `packaging=pom` 的父级目录，负责聚合一组同类型子模块。

例如：

- `ineed-core-modules`
- `ineed-core-reactive-modules`
- `ineed-core-tests`
- `ineed-core-starters`

标准形态：

```text
{aggregate-module}/
  pom.xml
  {child-module-a}/
  {child-module-b}/
  {child-module-c}/
```

规则：

- 分组聚合模块自身不生成 `src/main/java`
- 分组聚合模块自身不直接承载 Java 源码、资源文件、测试代码
- 真正的源码只能放在其子模块里
- 子模块目录必须和 `pom.xml` 中 `<modules>` 声明保持一致

## BOM 模块

BOM 模块只负责 `dependencyManagement`，不负责承载运行时代码。

例如：

- `ineed-core-bom`

标准形态：

```text
{bom-module}/
  pom.xml
```

规则：

- BOM 模块不生成 `src/main/java`
- BOM 模块不生成 `src/test/java`
- BOM 模块不承载业务实现、配置类、测试类、样板代码
- 不要把 BOM 模块误当成普通代码模块去补目录骨架

## 普通代码模块

普通代码模块是实际承载 Java 源码、资源和测试的模块。

例如：

- `ineed-core-base`
- `ineed-core-data-base`
- `ineed-rdb-metadata`
- `ineed-core-context`
- `ineed-core-engine`
- `ineed-core-webmvc`
- `ineed-core-data-core`
- `ineed-core-data-jpa`
- `ineed-core-data-jdbc`
- `ineed-core-data-mybatis-flex`
- `ineed-core-context-reactive`
- `ineed-core-engine-reactive`
- `ineed-core-webflux`
- `ineed-core-data-core-reactive`
- `ineed-core-data-r2dbc`
- `ineed-starter-druid`
- `ineed-core-test-webmvc`
- `ineed-core-test-webflux`

标准物理目录模板：

```text
{code-module}/
  pom.xml
  src/
    main/
      java/
        .gitkeep
      resources/
        .gitkeep
    test/
      java/
        .gitkeep
      resources/
        .gitkeep
```

规则：

- 所有普通代码模块都应统一具备 `src/main/java`、`src/main/resources`、`src/test/java`、`src/test/resources`
- 即使暂时没有源码，也应先保留四类目录；空目录通过 `.gitkeep` 入库
- 不允许只创建 `src/main/java` 而忽略测试目录
- 不允许把 `entity`、`controller`、`service`、`repository` 直接散落在模块根目录
- 如果同一代码模块中同时暴露阻塞式与响应式共享 `service` 契约，统一使用 `service/` 与 `service/reactive/` 分包
- `.settings`、`target`、IDE 文件、构建输出不属于需要生成或提交的目录骨架

## 业务聚合模块是特殊情况

业务聚合模块不是单个代码模块，而是“聚合目录 + 多个子模块”的组合。

标准形态继续按 [business-module-layout-guide.md](../project-development/business-module-layout-guide.md)：

```text
{business-aggregate}/
  pom.xml
  {business-aggregate}-core/
  {business-aggregate}-engine/
  {business-aggregate}-jpa/
  {business-aggregate}-jdbc/
  {business-aggregate}-mybatis-flex/
  {business-aggregate}-webmvc/
  {business-aggregate}-engine-reactive/
  {business-aggregate}-r2dbc/
  {business-aggregate}-webflux/
```

关键点：

- 业务聚合模块本身是聚合目录，不是直接写 Java 源码的地方
- 真正放源码的是各个业务子模块
- `core` 是共享契约层，不再单独创建 `{module}-reactive-core`

## 共享 service 契约的目录落点

如果业务聚合模块中的 `core` 子模块需要同时暴露阻塞式与响应式共享 `service` 契约，推荐物理落点如下：

```text
{business-aggregate}-core/
  src/main/java/com/ineed/{domain}/{object}/service/
  src/main/java/com/ineed/{domain}/{object}/service/reactive/

{business-aggregate}-webmvc/
  src/main/java/com/ineed/{domain}/{object}/service/

{business-aggregate}-webflux/
  src/main/java/com/ineed/{domain}/{object}/service/reactive/
```

规则：

- `core` 子模块中的 `service/` 与 `service/reactive/` 放共享接口定义
- `webmvc` / `webflux` 子模块中的对应目录只放本线适配实现，不重复定义另一套共享契约
- 不要把跨模块复用的共享接口只放进某个 `webmvc` 或 `webflux` 实现模块

## 模块类型与目录结构的映射规则

创建新模块时，必须满足下面的映射：

| 判断结果 | 应创建的目录 |
|----------|--------------|
| 根聚合模块 | `pom.xml` + 子模块目录，不创建 `src` |
| 分组聚合模块 | `pom.xml` + 子模块目录，不创建 `src` |
| BOM 模块 | 仅 `pom.xml`，不创建 `src` |
| 普通代码模块 | `pom.xml` + 标准四类 `src` 目录 |
| 业务聚合模块 | `pom.xml` + 业务子模块目录；各子模块内部再创建标准四类 `src` 目录 |

## 常见错误点

下面这些都是错误生成方式：

- 把 `packaging=pom` 的聚合模块生成成带 `src/main/java` 的代码模块
- 在 `ineed-core-modules/`、`ineed-core-reactive-modules/`、`ineed-core-tests/`、`ineed-core-starters/` 下面直接写源码
- 给 `ineed-core-bom/` 生成 `src` 目录
- 把业务聚合目录当成单模块，在聚合目录根下直接放 `controller`、`service`、`entity`
- 忽略 `src/test/java` 和 `src/test/resources`
- 重复发明 `{module}-reactive-core`
- 把阻塞式与响应式共享契约混放在同一个 `service` 根包，或者不使用 `service/reactive/`
- 把跨模块共享接口只定义在 `webmvc` / `webflux` 实现模块中
- 没有先看 `pom.xml` 中 `<modules>` 和 `<packaging>`，就凭名字猜目录结构

## 创建前自检

创建任何 Java 模块前，至少先检查：

1. 目标目录是根聚合模块、分组聚合模块、BOM 模块、普通代码模块，还是业务聚合模块
2. 目标 `pom.xml` 是否是 `packaging=pom`
3. 如果是聚合/BOM 模块，是否错误地准备生成 `src`
4. 如果是普通代码模块，是否已补齐四类 `src` 目录
5. 如果是业务聚合模块，是否转去遵循 [business-module-layout-guide.md](../project-development/business-module-layout-guide.md)
6. 子模块目录名是否与父级 `<modules>` 声明一致
7. 是否错误把 IDE / 构建输出目录当成应入库骨架

如果以上检查未完成，不应直接创建目录结构。

## 阅读建议

- 想确认当前仓库有哪些真实模块，读 [module-inventory.md](module-inventory.md)
- 想创建业务聚合模块，读 [business-module-layout-guide.md](../project-development/business-module-layout-guide.md)
- 想约束业务代码生成，结合 [development-contract.md](../project-development/development-contract.md) 和 [code-style-guide.md](../project-development/code-style-guide.md) 一起使用本文档

> 最后更新：2026-05-15
