在 Spring Boot 项目中,以下是几个包结构设计。
- 基于领域驱动设计和分层架构的包结构(上一篇介绍)
- 基于功能分层而非按业务模块的包结构
基于功能分层而非按业务模块的包结构
为了减少包重复冗余,同时保持代码组织清晰并适配 MyBatis Dynamic SQL,下面设计了一种按功能分层而非按业务模块分包的优化结构。这种结构既保持了代码的清晰组织,又避免了模块化分包带来的冗余问题。
优化后的包结构设计
bash
src/main/java
└── com
└── example
└── demo
├── Application.java # 启动类
│
├── config # 配置类
│ ├── MyBatisDynamicConfig.java
│ ├── WebMvcConfig.java
│ └── SecurityConfig.java
│
├── common # 公共模块
│ ├── annotation # 自定义注解
│ ├── constant # 常量
│ ├── enums # 枚举类
│ │ ├── AppErrorCode.java
│ │ └── ErrorCode.java
│ ├── exception # 异常处理
│ │ ├── GlobalExceptionHandler.java
│ │ └── BusinessException.java
│ ├── model # 公共模型
│ │ ├── page # 分页相关
│ │ │ ├── PageRequest.java
│ │ │ ├── PageResult.java
│ │ │ └── PaginationUtils.java
│ │ ├── response # 响应封装
│ │ │ ├── Result.java
│ │ └── validation # 验证工具
│ └── util # 工具类
│
├── controller # 控制器层
│ ├── UserController.java
│ ├── ProductController.java
│ └── ...
│
├── service # 服务层
│ ├── UserService.java
│ ├── ProductService.java
│ └── impl # 服务实现
│ ├── UserServiceImpl.java
│ ├── ProductServiceImpl.java
│ └── ...
│
├── repository # 数据访问层
│ ├── generated # MyBatis Generator 生成 MyBatis Dynamic SQL 代码
│ │ ├── UserMapper.java
│ │ ├── UserDynamicSqlSupport.java
│ │ ├── ProductMapper.java
│ │ ├── ProductDynamicSqlSupport.java
│ │ └── ...
│ ├── custom # 自定义Mapper接口
│ │ ├── UserCustomMapper.java
│ │ ├── ProductCustomMapper.java
│ │ └── ...
│ │ └──builder # 构建 SelectStatementProvider
│ │ ├── UserQueryBuilder.java
│ │ ├── ProductQueryBuilder.java
│ │ └── ...
│ │
├── model # 数据模型层
│ ├── entity # 实体类 (MyBatis Generator 生成)
│ │ ├── UserEntity.java
│ │ ├── ProductEntity.java
│ │ └── ...
│ ├── dto # 数据传输对象
│ │ ├── request # 请求DTO
│ │ │ ├── UserCreateRequest.java
│ │ │ ├── UserUpdateRequest.java
│ │ │ ├── UserQueryRequest.java
│ │ │ └── ...
│ │ └── response # 响应DTO
│ │ ├── UserResponse.java
│ │ ├── ProductResponse.java
│ │ └── ...
│ └── query # 查询条件封装
│ ├── UserQueryCondition.java
│ ├── ProductQueryCondition.java
│ └── ...
│
└── converter # 对象转换器
├── UserConverter.java
├── ProductConverter.java
└── ...
src/main/resources
├─ application.yml // 配置文件
└─ generatorConfig.xml // MyBatis Generator 配置
优势与特点
- 避免包冗余:按功能分层而非按业务模块分包,减少重复结构
- 分层清晰:按功能(controller/service/repository)而非业务模块分包
- 代码组织清晰:相同功能的类放在同一包下,便于查找和维护
- 高度可扩展:新增业务只需添加新类,无需创建新包结构
- 适配 MyBatis Dynamic SQL :
- 生成的代码放在
repository/generated
下 - 自定义Mapper接口与生成的代码分离
- 生成的代码放在
- 统一分页处理 :
- 基础 Mapper 接口提供通用分页方法
- 分页请求类可扩展特定字段验证
- 类型安全 :
- 使用 MyBatis Dynamic SQL 构建类型安全的查询
- DTO 与实体分离,明确职责边界
- 易于维护 :
- 对象转换器集中处理模型转换
- 仓储实现封装数据访问细节
分页查询流程
sequenceDiagram
participant Client
participant Controller
participant Service
participant Repository
participant Mapper
participant DB
Client->>Controller: GET /users?page=2&size=5&username=alice
Controller->>Service: UserQueryRequest
Service->>Repository: findByCondition(condition, request)
Repository->>Mapper: selectPage(completer, pageRequest)
Mapper->>Mapper: 1. 执行count查询
Mapper->>DB: SELECT COUNT(*) FROM user WHERE ...
DB-->>Mapper: 48
Mapper->>Mapper: 2. 执行分页查询
Mapper->>DB: SELECT * FROM user WHERE ... LIMIT 5,5
DB-->>Mapper: List
Mapper-->>Repository: PageResult
Repository-->>Service: PageResult
Service->>Service: 转换为PageResult
Service-->>Controller: PageResult
Controller-->>Client: 200 OK + JSON
这种非模块化分包结构既保持了代码的清晰组织,又避免了模块化分包带来的冗余问题,同时完美适配了 MyBatis Dynamic SQL 的代码生成需求。它特别适合中小型项目或业务模块之间高度耦合的项目,能够有效提高代码的可维护性和开发效率。