Web应用程序多模块单体应用代码目录结构设计
Web应用程序多模块单体应用代码目录结构设计
前言
每个有经验的开发者都有自己程序的开发规范,这篇文章是根据个人经验,以SpringBoot框架,java开发语言为示例,归纳总结出的一种代码目录结构。
在开发实践中不一定完全适合所有人,但是对于大部分人来说,应该可以满足大部分的场景。同时在实践中,需要基于需求,进行相应的调整,但大体上建议遵循该目录结构,提高代码的可读性以及可维护性.
后端
模块划分
即使是单体应用程序,也建议按照模块进行划分,每个模块对应一个目录,目录下存放该模块的代码。
📁 推荐模块结构(点击展开)
framework:框架模块,为整个应用程序提供基础功能,例如:数据库连接、缓存连接、日志记录、异常处理等;common:通用模块,为整个应用程序提供通用功能,例如:文件上传、图片处理、数据验证等,同时实体类、枚举类、工具类也可以放在该模块下;- 业务模块:为业务功能提供支持,例如:后台管理、用户管理、权限管理、订单管理等。
常见业务模块示例:
admin:后台模块,为后台提供功能,例如:用户管理、角色管理、权限管理等;user:用户模块,为用户提供功能,例如:用户注册、用户登录、用户注销、用户信息管理等;auth:认证模块,为用户提供认证功能,例如:用户登录、用户注册、用户注销等;命名要求
数据库
表名
要求使用下划线
_分隔前缀说明(
视需求而定)sys_:管理端数据表前缀,例如:系统配置表sys_configtb_:功能业务相关表,记录业务数据,也可以使用其他前缀,例如:业务中台bme_
注意
在 单体应用 或 系统体量较小 的情况下,不建议使用前缀。极其不推荐使用拼音缩写作为表名,建议使用英文单词!
字段名
- 要求使用下划线
_分隔 - 建议使用英文单词
✅ 正确示范:
user_name
❌ 错误示范:yhm
实体类
项目中应只出现三种后缀实体类:DTO、VO、PO。
提示
有些项目会使用一个 entity 类作为全局数据传输的数据封装类,这样的好处是避免了数据传输对象和实体对象之间的转换。但当页面展示内容与实体类存在差异时,需修改实体类,导致其臃肿复杂。因此,除非必要,尽量避免仅使用 entity 类作为全局数据传输对象。
领域驱动设计(DDD)提示
这里可能有些读者阅读过领域驱动设计(DDD)的设计文章,因此可以看出这是一个 贫血模型。如果想要引入 充血模型,则需要考虑当前系统是否存在领域模型。如果存在,则应该创建领域模型,当前的实体模型只用来和数据库进行交互。
存放位置
- 实体类应都存在于
model包中 - 每种类型的实体类应新建独立子包(如
dto、vo、po) - 在各类型包下再按 业务内容 创建子包
📌 示例路径:model/dto/user/CreateUserDTO
其中 user 是根据对象内容新增的一层归纳。
命名规范
| 类型 | 用途 | 命名示例 |
|---|---|---|
DTO | 接口请求参数 / 多入参封装 | CreateUserDTO |
VO | 接口响应参数 / 多返回值封装 | QueryUserDetailInfoVO |
PO | 数据库实体 / DB 映射字段 | UserPO, PaginatedQueryUserInfoListPO |
方法名命名
方法命名采用 蛇形命名法(camelCase),首字母小写,格式为:{action}{object}{data range}{condition}
🔍 命名组件说明
action:动作(create,update,delete,query,paginatedQuery)object:操作对象(如User)data range(可选):detailInfo,infoListcondition(可选):如ByUnCode
💡 Service 接口方法命名示例(UserService)
- Boolean createUser(CreateUserDTO createUserDTO)
- Boolean updateUser(UpdateUserDTO updateUserDTO)
- Boolean deleteUser(String unCode) 或 Boolean deleteUser(DeleteUserDTO deleteUserDTO)
- QueryUserDetailInfoVO queryUserDetailInfo(String unCode)
- PaginatedQueryUserInfoListVO paginatedQueryUserInfoList(Page page)
变量名命名
变量名需“名副其实”,见名知意。若需注释补充,应考虑优化命名。
| 类型 | 建议 | 示例 |
|---|---|---|
| 布尔值 | 使用正逻辑(is, exist) | ✅ isSuccess❌ flag, notSuccess |
| 字符串 | 可加 Str 后缀 | errorMsgStr |
| 数值 | 明确对象 | timeOfRequestRetry |
| 数组 | 可加 Arry 后缀 | idArry |
| 列表 | 可加 List 后缀 | userList |
警告
极特殊情况下,变量命名 isXxxx 可能在序列化时导致错误。
代码功能划分
在继续对后端进行目录结构设计时,我们需要有以下共识作为前提:
- 每个业务实体都要有几个通用属性,例如:表id、业务id、创建人、创建时间、更新人、更新时间、逻辑删除标识、版本号等(详见 通用功能 章节);
通用功能
(内容待补充)
数据封装
(内容待补充)
控制器
每个业务模块下应有对应的控制器,负责处理用户请求并返回数据。
响应数据应封装到统一对象中,包含 数据、状态码、消息 等信息。
// 示例:统一响应结构(此处保留原空代码块)前端
(内容待补充)
中间件
(内容待补充)