本文目录导读:

Java 包结构(Package)的规范主要目的是为了实现命名空间隔离、逻辑模块化和代码可维护性。
下面从通用规范、常见模式(分层 vs 模块化)以及一个完整案例三个方面来说明。
核心命名规范(必须遵守)
- 全部小写:包名禁止使用大写字母、下划线或特殊字符。
com.example.myproject(正确)com.example.MyProject(错误)com.example.my_project(错误,应使用myproject)
- 域名倒序:以公司或组织的域名倒序开头,确保全局唯一性。
com.google、org.apache、io.github.yourname
- 单数形式:除非包内必须包含复数概念(如
dto本身就是缩写),否则尽量使用单数。com.example.user(推荐)com.example.users(不太推荐)
- 见名知意:包名应准确反映其功能和职责,不要用
utils1、core2这种模糊命名。
两种主流架构模式
Java开发中主要有两种包结构组织方式,根据项目复杂度选择。
模式1:按技术分层(传统三层架构)
适合简单的 CRUD 项目、小团队、单体应用,缺点是业务分散,当业务逻辑多时包会膨胀。
com.example.myapp
├── controller # 控制层(接收请求)
├── service # 业务逻辑层(接口)
├── service.impl # 业务逻辑实现类
├── repository # 数据访问层(DAO/Mapper)
├── entity # 数据实体(数据库映射)
├── dto # 数据传输对象(请求/响应体)
├── config # 配置类
├── common # 公共工具、常量、异常
│ ├── exception
│ ├── constant
│ └── util
└── MyApplication.java
模式2:按功能模块(微服务/DDD倾向)
适合复杂业务、多人协作、代码量大,核心思想是“高内聚、低耦合”,每个业务模块自成一体。
com.example.myapp
├── order # 订单模块(核心业务)
│ ├── controller
│ ├── service
│ ├── repository
│ ├── entity
│ ├── dto
│ └── config # 订单模块特有的配置
├── user # 用户模块
│ ├── controller
│ ├── service
│ ├── repository
│ ├── entity
│ └── dto
├── payment # 支付模块
│ ├── controller
│ ├── service
│ └── ...
├── common # 全局通用工具(不依赖具体业务)
│ ├── util
│ ├── constant
│ └── exception
└── MyApplication.java
完整规范案例(Spring Boot 项目)
假设公司域名是 example.com,项目名是 order-management(订单管理系统)。
基础包: com.example.ordermanagement
com.example.ordermanagement
│
├── OrderManagementApplication.java # 启动类
│
├── common # 全局公共模块(跨模块复用)
│ ├── constant # 常量定义
│ │ └── ApiConstant.java
│ ├── exception # 全局异常定义
│ │ ├── BusinessException.java
│ │ └── GlobalExceptionHandler.java
│ ├── response # 统一响应封装
│ │ └── Result.java
│ └── util # 工具类
│ ├── DateUtils.java
│ └── JsonUtils.java
│
├── config # 全局配置
│ ├── SwaggerConfig.java
│ ├── WebMvcConfig.java
│ └── JacksonConfig.java
│
├── framework # 框架/基础设施层
│ ├── mybatis # 持久层相关(分页、插件等)
│ └── redis # Redis相关配置与工具
│
├── module # 业务模块(核心)
│ │
│ ├── user # 用户模块
│ │ ├── controller # 对外接口
│ │ │ └── UserController.java
│ │ ├── service # 业务接口
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── UserServiceImpl.java
│ │ ├── repository # 数据访问(Mapper/DAO)
│ │ │ └── UserMapper.java
│ │ ├── entity # 数据库实体(ORM映射)
│ │ │ └── UserEntity.java
│ │ ├── dto # 数据传输对象
│ │ │ ├── request
│ │ │ │ └── UserCreateRequest.java
│ │ │ └── response
│ │ │ └── UserResponse.java
│ │ └── converter # 对象转换器(Entity -> DTO)
│ │ └── UserConverter.java
│ │
│ └── order # 订单模块(结构同上)
│ ├── controller
│ │ └── OrderController.java
│ ├── service
│ │ ├── OrderService.java
│ │ └── impl
│ │ └── OrderServiceImpl.java
│ ├── repository
│ │ └── OrderMapper.java
│ ├── entity
│ │ └── OrderEntity.java
│ ├── dto
│ │ ├── request
│ │ │ └── OrderCreateRequest.java
│ │ └── response
│ │ └── OrderResponse.java
│ └── converter
│ └── OrderConverter.java
│
└── resources # 资源文件
├── mapper # MyBatis XML映射文件(与module对应)
│ ├── user
│ │ └── UserMapper.xml
│ └── order
│ └── OrderMapper.xml
└── application.yml
几个关键命名规范细节
| 分类 | 命名示例 | 说明 |
|---|---|---|
| 控制层 | UserController |
以 Controller 接收 HTTP 请求 |
| 业务层 | UserService / UserServiceImpl |
接口用 Service,实现类用 ServiceImpl |
| 数据层 | UserMapper / UserDao |
Mapper 或 Dao,视框架而定 |
| 实体对象 | UserEntity / UserPojo |
对应数据库表,如果只有一个 POJO 可简写为 User |
| DTO 对象 | UserCreateRequest / UserResponse |
明确命名 Request / Response / VO / DTO |
| 转换器 | UserConverter / UserAssembler |
用于 Entity 与 DTO 之间的相互转换 |
| 配置类 | SwaggerConfig / RedisConfig |
以 Config 结尾 |
| 异常类 | BusinessException / NotFoundException |
以 Exception 结尾 |
| 工具类 | StringUtils / DateUtils |
以 Utils 或 Helper 结尾 |
高频易错点总结
- 避免循环依赖:
common模块不要引入具体的业务模块(如module.user),只能是工具类。 - 避免包名冲突:不要使用 Java 或常用的第三方库关键字,如
com.example.java、com.example.string。 - 避免过深的层级:通常不超过 4~5 层。
com.example.module.user.service.impl已经较深,如果业务简单可以去掉.impl直接放 service 里。 - 区分 Entity 和 DTO:
Entity只映射数据库字段,DTO是给前端看的,两者不要混用,否则会导致接口字段泄漏或数据库表结构外露。 - 保持模块内高内聚:在按功能模块划分时,
repository和entity尽量放在对应模块里,不要全部扔到顶层。
简单项目可以这样简化
如果项目很小(比如只有 5 个类),不需要强行拆分 module,用三层结构即可:
com.example.myapp ├── controller ├── service ├── repository ├── entity ├── dto ├── common │ └── util └── MyApplication.java
原则: 包结构是为了解决代码组织问题,不是为了复杂而复杂。当业务模块代码量超过 2000 行时,建议开始拆模块。