Java API 目录结构
概述
MyBatis 官方推荐了一套标准的项目目录布局。虽然不是强制要求,但统一的目录结构能显著降低团队沟通成本,让新人(比如飞翔科技刚入职的小崔)快速定位配置文件、映射器和测试代码的位置。
推荐目录结构
/my_application
/bin <-- 编译输出目录
/devlib <-- 开发期依赖 jar
/lib <-- MyBatis *.jar 及运行时依赖
/src
/org/myapp/
/action <-- 控制器层(Servlet/Controller)
/data <-- MyBatis 核心配置区 ★
/mybatis-config.xml <-- MyBatis 全局配置
/BlogMapper.java <-- Mapper 接口
/BlogMapper.xml <-- Mapper XML 映射文件
/model <-- 实体类/POJO
/service <-- 业务逻辑层
/view <-- 视图层(JSP/模板)
/properties <-- 外部属性文件(db.properties 等)
/test
/org/myapp/
/action <-- 控制器测试
/data <-- Mapper 测试 ★
/model <-- 实体测试
/service <-- 服务测试
/view <-- 视图测试
/properties <-- 测试环境属性文件
/web
/WEB-INF
/web.xml <-- Web 应用部署描述符
Mermaid 目录树
各目录职责详解
/src/org/myapp/data/ — MyBatis 配置中枢
这是整个 MyBatis 集成最关键的目录,包含三类文件:
| 文件类型 | 示例 | 职责 |
|---|---|---|
| 全局配置文件 | mybatis-config.xml | 定义数据源、事务、插件、设置等全局行为 |
| Mapper 接口 | BlogMapper.java | 声明数据库操作方法签名 |
| Mapper XML | BlogMapper.xml | 编写 SQL 语句、ResultMap、动态 SQL |
约定:Mapper 接口和 XML 放在同一目录,保证 MyBatis 能自动关联。如果 XML 放在
resources/下,需确保编译后 classpath 路径与接口一致。
/src/org/myapp/model/ — 实体层
存放 POJO 或 DTO,与数据库表一一对应。飞翔科技的项目里就有:
/data/model/
├── Employee.java // 员工实体
├── Department.java // 部门实体
└── SalaryRecord.java // 薪资记录实体
/src/org/myapp/service/ — 业务逻辑层
调用 Mapper 完成业务流程。例如孔蓝负责的 EmployeeService:
public class EmployeeService {
private EmployeeMapper employeeMapper;
public void transferDepartment(int empId, int newDeptId) {
Employee emp = employeeMapper.findById(empId);
emp.setDeptId(newDeptId);
employeeMapper.update(emp);
}
}
/src/org/myapp/action/ — 控制器层
接收 HTTP 请求,调用 Service,返回结果。在现代项目中常被 controller 包替代。
/src/properties/ — 属性文件
存放 db.properties 等外部化配置,便于环境切换:
# 开发环境
db.url=jdbc:mysql://localhost:3306/feixiang_dev
db.username=dev_user
db.password=dev123
# 生产环境(上线时切换)
# db.url=jdbc:mysql://10.0.1.100:3306/feixiang_prod
# db.username=prod_user
# db.password=强密码
主代码与测试代码的镜像关系
这是该目录结构最精妙的设计:src/ 和 test/ 下的包结构完全一致。
镜像关系的三大好处:
- 测试类可见性:同包路径下,测试类可以直接访问主代码的包级私有(default)成员,无需破坏封装。
- 快速定位:黄俪(测试工程师)看到一个
EmployeeService.java,立刻知道对应的测试类在test/下同路径,反之亦然。 - 构建分离:Maven/Gradle 构建时,
src/打包进最终产物,test/只在测试阶段生效,不会污染生产包。
飞翔科技实战:小崔上手项目
小崔入职第一天,白歌(高级开发)让他先熟悉项目结构:
白歌:"打开
src/org/feixiang/data/,你会看到mybatis-config.xml和所有 Mapper。这是整个持久层的入口。然后去test/下同路径看对应的测试用例,跑通它们就基本理解业务了。"
小崔按图索骥:
src/org/feixiang/data/
├── mybatis-config.xml ← 数据源配置
├── EmployeeMapper.java ← 接口定义
├── EmployeeMapper.xml ← SQL 实现
├── DepartmentMapper.java
└── DepartmentMapper.xml
test/org/feixiang/data/
├── EmployeeMapperTest.java ← 镜像测试
└── DepartmentMapperTest.java
小崔花了半天时间跑通了所有测试,对项目结构了然于胸。
易错场景提醒
1. Mapper XML 放错位置
// ❌ 错误:XML 放在 resources/mapper/ 下,但接口在 org/feixiang/data/
// 导致 MyBatis 无法自动关联,需额外配置 <mapper resource="mapper/EmployeeMapper.xml"/>
// ✅ 正确做法一:XML 与接口同包
src/org/feixiang/data/EmployeeMapper.java
src/org/feixiang/data/EmployeeMapper.xml
// ✅ 正确做法二:Maven 项目中将 XML 放在 resources 下但保持相同包结构
src/main/java/org/feixiang/data/EmployeeMapper.java
src/main/resources/org/feixiang/data/EmployeeMapper.xml
2. properties 文件加载顺序混乱
多个 properties 文件时,MyBatis 按声明顺序加载,后加载的覆盖先加载的。如果 mybatis-config.xml 内部 <properties resource="db.properties"/> 和外部代码 config.getVariables() 同时存在,可能产生意外覆盖。
3. 测试目录忘记镜像
// ❌ 错误:测试类放在 test/ 根目录,包路径与主代码不一致
// 导致无法访问包级私有方法,IDE 也会警告
面试考点
MyBatis 推荐的项目目录结构中,Mapper 接口和 XML 应该放在哪里?
- 放在同一包路径下(如
src/org/myapp/data/),确保 MyBatis 自动关联。Maven 项目中也可将 XML 放在resources/下但保持相同目录结构。
- 放在同一包路径下(如
src/和test/目录为什么要镜像?- 保证测试类与被测类同包,可访问包级私有成员;方便快速定位对应测试;构建时自动分离,测试代码不进入生产包。
/data/目录下通常有哪些文件?mybatis-config.xml(全局配置)、Mapper 接口(.java)、Mapper XML 映射文件(.xml)。
properties 目录的作用是什么?
- 存放数据库连接等外部化配置,方便不同环境(开发/测试/生产)切换,敏感信息不入库。