一、Java 项目目录结构标准
1.1 Java 项目标准目录结构总览
标准 Java 项目目录结构(以 Maven / Gradle 通用结构为基础):
project-root/
├── src/
│ ├── main/
│ │ ├── java/ # 主业务逻辑代码(核心 Java 类)
│ │ ├── resources/ # 配置资源文件(不包含 Java 类)
│ └── test/
│ ├── java/ # 测试代码(JUnit 单元测试)
│ └── resources/ # 测试时需要用到的资源文件
├── pom.xml # Maven 项目构建文件(Maven 项目)
├── build.gradle # Gradle 项目构建文件(Gradle 项目)
├── README.md # 项目说明文件
├── target/ 或 build/ # 编译输出目录(自动生成)
1.2 各目录详细解释
>1. src/main/java
存放 主程序代码(Java 源文件
.java
)。按照包结构组织代码,如
com.example.app
⇒src/main/java/com/example/app/
示例结构:
src/main/java/
└── com/└── example/├── MainApp.java // 启动类├── service/│ └── UserService.java└── model/└── User.java
>2. src/main/resources
存放非代码类资源,如:
application.properties
/application.yml
(Spring Boot 配置)日志配置
log4j.xml
数据库连接配置
jdbc.properties
模板文件(HTML、freemarker、thymeleaf)
示例结构:
src/main/resources/
├── application.yml
├── logback.xml
└── static/└── index.html
注意:resources 下的文件在构建时会自动加入到 classpath,程序中可以通过ClassLoader.getResourceAsStream()
加载。
>3. src/test/java
存放 测试代码,一般用于 JUnit 单元测试或集成测试。
包结构应与
src/main/java
保持一致,便于测试类与实际类一一对应。
示例:
src/test/java/
└── com/└── example/└── service/└── UserServiceTest.java
>4. src/test/resources
测试中需要的配置文件、模拟数据(如 JSON、YAML、mock 文件)等,作用同
main/resources
,只在测试中可用。
1.3 项目根目录常见文件解释
文件/目录名 | 说明 |
---|---|
pom.xml | Maven 配置文件(声明依赖、插件、编译信息等) |
build.gradle | Gradle 配置文件(同上) |
README.md | 项目说明文件 |
.gitignore | Git 忽略文件配置 |
.idea/ 、.vscode/ | IDE 项目文件 |
target/ 或 build/ | 编译后生成的 .class 、.jar 等内容 |
1.4 包结构命名规范
包命名建议以公司域名倒序开头:
com.example.projectname.module
举例结构:
src/main/java/com/example/blog/
├── BlogApplication.java # 主类
├── controller/ # 控制器层(MVC)
├── service/ # 业务逻辑
├── model/ # 实体类(POJO)
├── repository/ # 持久层(DAO)
└── util/ # 工具类
1.5 构建产物目录(自动生成)
对应构建工具:
Maven:
target/
Gradle:
build/
这些目录在执行 mvn package
/ gradle build
后自动生成,用于存放:
编译后的
.class
文件打包后的
.jar
/.war
测试报告、日志、临时文件等
不建议手动修改,通常在 .gitignore
中忽略提交。
1.6 标准结构带来的好处
优点 | 说明 |
---|---|
清晰模块分工 | 将业务代码、测试、资源等分类明确 |
IDE 支持良好 | IntelliJ IDEA / Eclipse 可直接识别 |
自动化构建支持 | Maven / Gradle 构建无需额外配置 |
测试代码与主逻辑隔离 | 避免生产环境中包含调试/测试代码 |
包路径与文件路径映射清晰 | com.xxx 对应目录结构清晰直观 |
1.7 整体结构图示意
project-root/
├── src/
│ ├── main/
│ │ ├── java/ ← Java 源码(包结构)
│ │ └── resources/ ← 配置文件、静态资源
│ └── test/
│ ├── java/ ← 测试源码(JUnit)
│ └── resources/ ← 测试用的配置或模拟数据
├── pom.xml / build.gradle ← 构建工具配置
├── target/ 或 build/ ← 编译输出(自动生成)
├── README.md ← 项目说明
└── .gitignore ← Git 忽略文件
二、Maven
Maven 是 Java 领域中最常用的 构建工具和依赖管理系统,它的核心职责:
功能 | 说明 |
---|---|
依赖管理 | 自动下载第三方 jar 包 |
构建项目 | 编译、测试、打包、部署 |
插件系统 | 支持代码编译、打包、测试、部署等插件 |
统一结构 | 使用标准目录结构,便于协作开发 |
2.1 pom.xml
基本结构
Maven 项目的核心配置文件就是 pom.xml
(Project Object Model)。
一个最基本的 pom.xml
文件如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId> <!-- 包名(组织ID) --><artifactId>my-app</artifactId> <!-- 项目名 --><version>1.0.0</version> <!-- 项目版本 --><packaging>jar</packaging> <!-- 打包类型:jar/war/pom --></project>
2.2 依赖管理
Maven 依赖通过 <dependencies>
标签引入:
<dependencies><!-- 1. 生产依赖 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><!-- 2. 测试依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope> <!-- 只在测试时有效 --></dependency></dependencies>
常见的 scope
范围含义
scope | 说明 |
---|---|
compile | 默认值,主程序运行和编译都需要(最常用) |
test | 测试阶段使用 |
provided | 编译期需要,运行时不包含(如 Servlet API) |
runtime | 编译期不需要,运行时需要 |
system | 本地 jar 包,需要手动指定路径,不推荐使用 |
2.3 依赖仓库与本地缓存
Maven 会自动从远程仓库(默认是 Maven Central)下载 jar 包,并保存在本地仓库中:
默认本地仓库路径:
~/.m2/repository/
如果依赖未指定版本,Maven 会报错或使用最近一次缓存的版本。
2.4 插件使用(build/plugins)
Maven 构建生命周期依赖插件来实现,比如编译、打包、测试等。
1)编译插件示例(maven-compiler-plugin
)
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source> <!-- Java 源码版本 --><target>1.8</target> <!-- 字节码版本 --></configuration></plugin></plugins>
</build>
2)打包插件示例(maven-jar-plugin
)
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.2</version><configuration><archive><manifest><mainClass>com.example.MainApp</mainClass> <!-- 指定启动类 --></manifest></archive></configuration></plugin></plugins>
</build>
打包后就可以直接运行:
java -jar target/my-app-1.0.0.jar
3)常用插件列表
插件名 | 功能 |
---|---|
maven-compiler-plugin | 编译 Java 代码 |
maven-jar-plugin | 打包 jar |
maven-surefire-plugin | 运行单元测试 |
maven-dependency-plugin | 依赖分析、复制 |
maven-clean-plugin | 清理 target/ 目录 |
maven-assembly-plugin | 打包带依赖的 fat jar |
2.5 完整 pom.xml
示例
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>myapp</artifactId><version>1.0.0</version><packaging>jar</packaging><dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency></dependencies><build><plugins><!-- 编译插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><!-- 打包插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.2</version><configuration><archive><manifest><mainClass>com.example.MainApp</mainClass></manifest></archive></configuration></plugin></plugins></build>
</project>
2.6 常用 Maven 命令回顾
命令 | 说明 |
---|---|
mvn clean | 清理 target/ |
mvn compile | 编译主程序 |
mvn test | 执行测试类 |
mvn package | 编译 + 打包 |
mvn install | 安装 jar 到本地仓库 |
mvn dependency:tree | 查看依赖树 |
mvn help:effective-pom | 查看完整的有效 POM |
2.7 小结
pom.xml 配置结构:
├── groupId / artifactId / version # 基础身份
├── dependencies # 依赖管理
├── build
│ └── plugins # 构建插件
│ └── compiler / jar / ...
├── properties # 自定义属性(如 Java 版本)
└── profiles(可选) # 多环境配置(开发/测试/生产)
三、Gradle
Gradle 是一个现代化、基于 Groovy/Kotlin DSL 的构建工具,用于:
功能 | 描述 |
---|---|
依赖管理 | 类似 Maven,自动引入 jar 包 |
构建流程 | 编译、测试、打包、部署 |
插件化 | 自定义构建任务,灵活可编程 |
性能高 | 支持增量构建和缓存机制 |
Android 开发 | 官方推荐构建工具 |
3.1 Gradle 项目的基本目录结构
Gradle 项目也遵循和 Maven 相似的标准结构:
project-root/
├── build.gradle ← Gradle 配置文件(核心)
├── settings.gradle ← 项目名与模块声明
├── src/
│ ├── main/
│ │ ├── java/ ← 主程序代码
│ │ └── resources/ ← 资源文件
│ └── test/
│ ├── java/ ← 测试代码
│ └── resources/
├── build/ ← 编译输出目录(自动生成)
3.2 build.gradle
详解(Groovy DSL)
下面是一个典型的 Java 项目的 build.gradle
文件结构:
// 1. 插件(功能)
plugins {id 'java' // 应用 Java 插件
}// 2. 项目信息
group = 'com.example' // 组织名称
version = '1.0.0' // 项目版本// 3. 仓库(依赖从哪儿下)
repositories {mavenCentral() // 使用中央仓库
}// 4. 项目依赖
dependencies {// 编译期依赖(默认)implementation 'org.apache.commons:commons-lang3:3.12.0'// 测试期依赖testImplementation 'junit:junit:4.13.2'
}// 5. 编译器配置(可选)
tasks.withType(JavaCompile) {options.encoding = 'UTF-8' // 设置文件编码
}
3.3 依赖导入方式(dependencies 块)
Gradle 支持多种依赖作用范围:
1)常见依赖作用域
作用域 | 说明 |
---|---|
implementation | 编译期 & 运行期依赖(推荐) |
api | 公开依赖(用于库项目) |
compileOnly | 编译期依赖(运行时无效) |
runtimeOnly | 运行期依赖(编译时无效) |
testImplementation | 测试代码专用依赖 |
2)示例依赖导入
dependencies {// 主程序依赖implementation 'com.google.guava:guava:32.1.2-jre'// 只在测试中用testImplementation 'junit:junit:4.13.2'// 编译期依赖但不打包compileOnly 'javax.servlet:servlet-api:2.5'// 运行期依赖(不参与编译)runtimeOnly 'mysql:mysql-connector-java:8.0.33'
}
3)本地 jar 文件依赖
dependencies {implementation files('libs/mylib.jar')
}
4)自定义仓库
repositories {mavenCentral()mavenLocal()maven {url 'https://repo.spring.io/milestone'}
}
3.4 常用插件及配置
Gradle 插件添加方式(Groovy DSL):
1)Java 插件(编译 Java 项目)
plugins {id 'java'
}
2)Application 插件(指定 main 方法并允许运行)
plugins {id 'application'
}application {mainClass = 'com.example.MainApp'
}
执行命令:
gradle run
3.5 常用命令
命令 | 功能 |
---|---|
gradle build | 编译、测试并打包 |
gradle clean | 清理 build 目录 |
gradle test | 执行测试类 |
gradle run | 运行 main 函数(需配置 application 插件) |
gradle dependencies | 查看依赖树 |
gradle --offline | 离线构建 |
3.6 补充:settings.gradle 文件
如果是单模块项目:
rootProject.name = 'myapp'
如果是多模块项目:
rootProject.name = 'parent-project'
include 'module-a', 'module-b'
3.7 完整 build.gradle
示例
plugins {id 'java'id 'application'
}group = 'com.example'
version = '1.0.0'repositories {mavenCentral()
}dependencies {implementation 'org.apache.commons:commons-lang3:3.12.0'testImplementation 'junit:junit:4.13.2'
}application {mainClass = 'com.example.MainApp'
}tasks.withType(JavaCompile) {options.encoding = 'UTF-8'
}
3.8 小结
build.gradle
├── plugins # 插件(java、application等)
├── group/version # 项目信息
├── repositories # 依赖仓库(mavenCentral)
├── dependencies # 项目依赖(impl、testImpl)
├── application # 入口类配置(mainClass)
└── tasks.withType # 编译设置(编码、警告等)
四、单元测试
JUnit 是 Java 中最常用的单元测试框架,用于对 Java 方法进行自动化测试。
它的作用是:
功能 | 描述 |
---|---|
自动验证函数行为 | 比如:加法是否正确、异常是否抛出 |
回归测试 | 每次修改后自动跑测试,保证老功能没出问题 |
提高质量 | 提高代码的健壮性和可维护性 |
自动集成 | 可与 Maven/Gradle/CI/CD 集成自动执行测试 |
4.1 JUnit 常见版本
版本 | 特点 |
---|---|
JUnit 4.x | 最广泛使用,使用注解 @Test |
JUnit 5.x | 新一代框架,分为 3 个模块(Jupiter、Platform、Vintage),更强大但结构更复杂 |
这里用最常见的 JUnit 4 讲解
4.2 Maven/Gradle 中引入 JUnit
Maven 中添加依赖:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>
Gradle 中添加依赖:
dependencies {testImplementation 'junit:junit:4.13.2'
}
4.3 测试代码目录规范
project-root/
├── src/
│ ├── main/
│ │ └── java/com/example/Calculator.java ← 被测试类
│ └── test/
│ └── java/com/example/CalculatorTest.java ← 测试类
测试类放在 src/test/java
,包路径与主类保持一致
4.4 一个最基本的测试类示例
被测试类(Calculator.java
):
package com.example;public class Calculator {public int add(int a, int b) {return a + b;}public int divide(int a, int b) {return a / b; // 可能抛出异常}
}
对应测试类(CalculatorTest.java
):
package com.example;import org.junit.Test;
import static org.junit.Assert.*;public class CalculatorTest {@Testpublic void testAdd() {Calculator c = new Calculator();int result = c.add(2, 3);assertEquals(5, result); // 断言结果为 5}@Test(expected = ArithmeticException.class)public void testDivideByZero() {Calculator c = new Calculator();c.divide(10, 0); // 应该抛异常}
}
4.5 常用断言方法(org.junit.Assert
)
方法 | 说明 |
---|---|
assertEquals(expected, actual) | 判断相等(值类型) |
assertTrue(condition) | 判断为 true |
assertFalse(condition) | 判断为 false |
assertNull(obj) | 判断为 null |
assertNotNull(obj) | 判断不为 null |
assertArrayEquals(expected, actual) | 判断数组相等 |
assertThrows(Exception.class, () -> xxx) | 判断抛出异常(JUnit 5) |
@Test(expected = Exception.class) | 判断抛出异常(JUnit 4) |
4.6 测试生命周期注解(JUnit 4)
注解 | 说明 |
---|---|
@Before | 每个测试方法执行前运行(初始化) |
@After | 每个测试方法执行后运行(清理) |
@BeforeClass | 所有测试前执行一次(必须是 static) |
@AfterClass | 所有测试后执行一次(必须是 static) |
@Test | 表示该方法是测试方法 |
示例:
@Before
public void setUp() {System.out.println("每次测试前初始化");
}@After
public void tearDown() {System.out.println("每次测试后清理");
}
4.7 如何运行测试
方式 1:命令行运行
- Maven:
mvn test
- Gradle:
gradle test
方式 2:IDEA 中运行
- 右键点击测试类或方法 → Run
>测试结果展示
测试通过 ✔ :绿色
测试失败 ✘ :红色(IDE 会显示期望值与实际值差异)
4.8 使用测试套件(Test Suite)
当有很多测试类时,可以用 @RunWith
和 @SuiteClasses
组织一个测试集合:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;@RunWith(Suite.class)
@Suite.SuiteClasses({CalculatorTest.class,OtherTest.class
})
public class AllTests {// 空类,仅用于组合多个测试
}
4.9 小结
测试类结构
├── Calculator.java ← 生产类
├── CalculatorTest.java ← 测试类
│ ├── @Test ← 测试函数
│ ├── assertEquals 等 ← 断言
│ ├── @Before / @After ← 生命周期钩子
├── 测试运行方式:mvn test / gradle test / IDE
五、Java 项目运行流程
一个标准 Java 项目的运行流程,大致可以总结为以下 5 步:
1. 确定主类(含 main 方法入口)
2. 编译源代码(.java → .class)
3. 加载依赖(jar 包、本地类)
4. 构建 ClassPath(类路径)
5. JVM 调用 main() 执行程序
5.1 主类(程序入口)
> 什么是主类?
主类是包含 public static void main(String[] args)
方法的类。
public class MainApp {public static void main(String[] args) {System.out.println("Hello, Java!");}
}
main 方法是 Java 应用程序的入口点
它必须是
public static
修饰,接收String[]
作为参数
> 运行方式
通过 IDE(右键 → Run
MainApp.main()
)命令行方式:
javac MainApp.java # 编译成 class 文件
java MainApp # 运行,执行 main 方法
5.2 模块(module)
1)模块在标准项目中的含义
在非模块化(传统)项目中,“模块”通常指:
项目中的一个子系统(如
user
,order
,common
模块)独立的包结构 + 代码目录
例如:
com.example.user
com.example.payment
2)Java 9+ 模块化系统
Java 9 引入了正式的模块系统(module-info.java
),但并不是所有项目都使用。
示例:
module com.example.myapp {requires java.sql;exports com.example.myapp.api;
}
初学阶段可以不接触 Java Module System(复杂度较高)
5.3 依赖(第三方/内部)
> 什么是依赖?
Java 项目中调用的 不是你写的类(外部库、jar 包),就是依赖。
如:Spring、Guava、Jackson、JDBC Driver
> 依赖加载方式
来源 | 加载方式 |
---|---|
本地 .class 文件 | 自动加载进内存 |
本地 .jar 包 | JVM 通过 classpath 加载 |
远程依赖(Maven/Gradle) | 会先下载 → 缓存到本地 .m2 或 .gradle 仓库,然后加入构建路径 |
示例依赖:使用 commons-lang3
import org.apache.commons.lang3.StringUtils;String str = "abc";
System.out.println(StringUtils.isNotEmpty(str));
这段代码依赖了 Apache 的 commons-lang3 库,需要添加:
Maven:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version>
</dependency>
Gradle:
implementation 'org.apache.commons:commons-lang3:3.12.0'
5.4 ClassPath 与类加载
> ClassPath 是什么?
ClassPath 是 JVM 在运行时查找
.class
文件的路径。含义类似 Python 的 sys.path、Linux 的 PATH。
可以通过命令查看:
java -cp target/classes:libs/* com.example.MainApp
> 类加载器(ClassLoader)作用
JVM 使用以下几种类加载器:
类加载器 | 作用 |
---|---|
BootstrapClassLoader | 加载核心类(rt.jar) |
ExtensionClassLoader | 加载扩展库(lib/ext) |
AppClassLoader | 加载我们自己的类 |
自定义 ClassLoader | 特殊用途(框架、热部署) |
5.5 Java 程序执行流程详解图
启动 JVM → 找到入口类 main() → 加载依赖(jar)→ 创建 ClassLoader → 执行方法
图解:
+------------------+
| java MainApp |
+--------+---------+|v
+------------------------+
| 加载 MainApp.class |
+------------------------+|v
+--------------------------+
| 初始化依赖类(StringUtils)|
+--------------------------+|v
+-------------------+
| 执行 main() |
| 打印输出 |
+-------------------+
5.6 打包运行流程(.jar)
Maven 打包命令:
mvn clean package
会在 target/
目录生成 xxx.jar
设置 mainClass 打包运行:
<build><plugins><plugin><artifactId>maven-jar-plugin</artifactId><configuration><archive><manifest><mainClass>com.example.MainApp</mainClass></manifest></archive></configuration></plugin></plugins>
</build>
运行 jar:
java -jar target/myapp-1.0.0.jar
5.7 实践建议
使用 Maven 或 Gradle 来管理依赖和构建流程
主类必须有
main()
且所在包正确(IDEA 会自动识别)每个模块职责明确(如 service、controller、model)
合理组织目录结构,遵循
src/main/java
标准
5.8 小结
Main Class(main 方法)↓
编译为 .class↓
查找依赖(内部类 + 外部 jar)↓
由 JVM 的类加载器加载进内存↓
执行 main()↓
运行中的堆/栈/方法栈执行逻辑