Maven 详解(上)
Maven 标准目录结构详解
Maven 为项目定义了一套清晰、标准化的目录布局。只要你的项目遵循这个结构,Maven 就能自动识别源代码、资源文件、测试代码等,并在正确的阶段进行处理,无需你进行额外的配置。
以下是 Maven 项目的完整标准目录结构:
my-project/ # 项目根目录 (包含 pom.xml)
│
├── pom.xml # Maven 项目的核心配置文件
│
├── src/ # 所有源代码和资源的根目录
│ │
│ ├── main/ # 主代码 (生产代码) 目录
│ │ │
│ │ ├── java/ # 主 Java 源代码 (包结构)
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myapp/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── model/
│ │ │ └── MyApplication.java
│ │ │
│ │ ├── resources/ # 主资源文件 (会被打包进最终的 JAR/WAR)
│ │ │ ├── application.properties # Spring Boot 配置文件
│ │ │ ├── application.yml # 或 YAML 格式
│ │ │ ├── logback-spring.xml # 日志配置
│ │ │ ├── static/ # Web 项目:静态资源 (CSS, JS, 图片)
│ │ │ └── templates/ # Web 项目:模板文件 (Thymeleaf, FreeMarker)
│ │ │
│ │ └── webapp/ # Web 项目 (WAR 打包) 的 Web 资源目录 (可选)
│ │ ├── WEB-INF/
│ │ │ └── web.xml # 可选的 Servlet 配置文件
│ │ ├── index.jsp # JSP 页面
│ │ └── ... # 其他前端资源
│ │
│ └── test/ # 测试代码目录
│ │
│ ├── java/ # 测试 Java 源代码 (JUnit, TestNG 等)
│ │ └── com/
│ │ └── example/
│ │ └── myapp/
│ │ └── service/
│ │ └── UserServiceTest.java
│ │
│ └── resources/ # 测试资源文件 (仅用于测试)
│ └── application-test.properties # 测试专用配置
│
├── target/ # **构建输出目录** (由 Maven 自动生成和管理)
│ ├── classes/ # 编译后的主类文件 (.class)
│ ├── test-classes/ # 编译后的测试类文件 (.class)
│ ├── maven-archiver/ # Maven 归档插件生成的文件
│ ├── surefire-reports/ # Surefire (测试) 插件生成的报告
│ ├── my-project-1.0.0.jar # 最终打包的 JAR/WAR 文件
│ └── ... # 其他构建过程中的临时文件
│
└── (其他文件) # 如 README.md, LICENSE 等核心目录详解
1. pom.xml (Project Object Model)
- 位置: 项目根目录。
- 作用: 这是 Maven 项目的心脏。它是一个 XML 文件,包含了项目的所有配置信息:
- 项目坐标 (GAV: groupId, artifactId, version)
- 依赖列表 (Dependencies)
- 构建配置 (Build)
- 项目信息 (名称、描述、URL)
- 开发者信息
- 插件配置
- 重要性: Maven 的所有操作都基于这个文件。
2. src/ (Source Directory)
- 作用: 这是所有源代码和资源文件的根目录。Maven 默认从这里查找需要编译和打包的文件。
3. src/main/ (Main Source Directory)
- 作用: 存放项目的主代码 (生产代码) 和主资源。这些内容会被编译并打包到最终的可分发文件(JAR/WAR)中。
src/main/java/: 存放所有的 Java 源代码文件(.java)。目录结构必须与 Java 的包(package)结构一致。例如,com.example.myapp.MyClass类的文件路径应为src/main/java/com/example/myapp/MyClass.java。src/main/resources/: 存放主资源文件。这些文件在项目编译时会被复制到target/classes/目录下,并最终打包进 JAR/WAR 文件的根目录或BOOT-INF/classes/(Spring Boot)。因此,它们可以通过ClassPath被程序加载。- 常见文件: 配置文件(
application.properties,log4j2.xml)、国际化文件(messages.properties)、MyBatis 的Mapper.xml、静态资源(在 Spring Boot 中,static/和templates/通常放在这里)等。
- 常见文件: 配置文件(
src/main/webapp/: 仅适用于打包为 WAR 的传统 Web 项目。这是 Web 应用的根目录,包含 JSP 文件、HTML、CSS、JS 以及WEB-INF目录。WEB-INF目录下通常有web.xml(可选,Spring Boot 通常不需要)和lib(存放第三方 JAR,但 Maven 会自动管理,通常为空)。注意:对于 Spring Boot 的可执行 JAR 项目,这个目录不是必需的,静态资源和模板文件通常直接放在src/main/resources/下的static/和templates/目录中。
4. src/test/ (Test Source Directory)
- 作用: 存放项目的测试代码和测试资源。这些内容不会被打包到最终的生产 JAR/WAR 文件中,仅用于开发和构建时的测试。
src/test/java/: 存放所有的测试 Java 源代码文件(.java),如 JUnit 测试类。目录结构同样需要与包结构一致。src/test/resources/: 存放测试专用的资源文件。这些文件在测试编译时会被复制到target/test-classes/,并只在测试阶段的 classpath 中可用。- 常见文件: 测试专用的配置文件(
application-test.properties)、测试数据文件、H2 数据库的初始化脚本等。这使得你可以为测试环境配置不同的数据库连接、日志级别等,而不会影响生产配置。
- 常见文件: 测试专用的配置文件(
5. target/ (Build Output Directory)
- 作用: 这是 Maven 自动生成和管理的目录,存放所有构建过程的输出文件。你通常不应该手动修改或提交这个目录到版本控制系统 (如 Git)。
- 内容:
classes/: 编译src/main/java/后生成的.class文件。test-classes/: 编译src/test/java/后生成的.class文件。maven-archiver/:maven-jar-plugin等归档插件生成的文件。surefire-reports/:maven-surefire-plugin(执行测试的插件) 生成的测试报告(XML 和 TXT 格式)。my-project-1.0.0.jar: 执行mvn package后生成的最终 JAR 或 WAR 文件。- 其他: 可能还有
generated-sources/(插件生成的代码),dependency-cache/等。
- 重要性: 每次执行
mvn clean命令时,整个target/目录都会被删除,然后在下一次构建时重新生成。这保证了构建的干净和可重复性。
Spring Boot 项目 pom.xml 详解
这份 pom.xml 是使用 Spring Initializr 生成的 Spring Boot 项目的标准模板。它利用了 Maven 的核心特性,特别是 BOM (Bill of Materials) 模式来简化依赖管理。
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><!-- 1. 基本信息 --><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><!-- 2. 属性定义 --><properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version></properties><!-- 3. 依赖管理 (BOM) --><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><!-- 4. 项目依赖 --><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><!-- 5. 构建配置 --><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.example.demo.DemoApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>
</project>逐部分详解
1. 基本信息 (<modelVersion>, <groupId>, <artifactId>, <version>, <name>, <description>)
<modelVersion>4.0.0</modelVersion>: 这是固定的,表示使用的 POM 模型版本。<groupId>com.example</groupId>: 项目的组织 ID。通常使用公司或组织的反向域名。<artifactId>demo</artifactId>: 项目本身的名称。<version>0.0.1-SNAPSHOT</version>: 项目的版本号。-SNAPSHOT后缀表示这是一个开发中的快照版本,Maven 会定期检查远程仓库是否有更新。<name>demo</name>和<description>Demo project for Spring Boot</description>: 项目的可读名称和描述,用于文档生成。
2. 属性定义 (<properties>)
- 这里定义了可以在整个 POM 文件中复用的变量。
<java.version>17</java.version>: 指定项目使用的 Java 版本。这个属性通常会被 Spring Boot 的插件自动读取。<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>和<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>: 确保构建过程(编译)和报告生成使用 UTF-8 编码,避免中文乱码。<spring-boot.version>2.7.6</spring-boot.version>: 关键属性。集中定义了 Spring Boot 的版本号。这个变量 (${spring-boot.version}) 会在后面被多次引用,确保所有 Spring Boot 相关的组件使用统一的版本。
3. 依赖管理 (<dependencyManagement>) - BOM 的核心
- 这是这份配置的精髓所在。它使用了 BOM (Bill of Materials) 模式。
<dependencyManagement>: 这个元素本身不会引入任何依赖,它只负责声明依赖的版本。<dependency>:<groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId>: 这是 Spring Boot 官方提供的一个特殊的 POM 文件。<version>${spring-boot.version}</version>: 指定了这个 BOM 的版本。<type>pom</type>: 声明这是一个 POM 类型的依赖。<scope>import</scope>: 最关键的配置。import范围告诉 Maven,将spring-boot-dependencies这个 POM 文件中<dependencyManagement>部分定义的所有依赖及其版本导入到当前项目的<dependencyManagement>中。
- 作用:
spring-boot-dependenciesPOM 中已经预先定义了 Spring Boot 框架及其所有支持库(如 Spring Framework, Spring Data, Jackson, Tomcat, Hibernate Validator 等)的兼容版本。- 通过
import,你的项目就继承了这一整套经过测试、相互兼容的版本组合。 - 结果:你在
<dependencies>中引入 Spring Boot 的 Starter 时,无需再指定版本号,Maven 会自动从 BOM 中获取正确的版本。
4. 项目依赖 (<dependencies>)
- 这里声明了项目实际需要的依赖。
spring-boot-starter-web:- 作用:这是构建 Web 应用(尤其是 RESTful API)的核心 Starter。
- 包含内容:它会自动传递性地引入:
spring-web和spring-webmvc: Spring MVC 框架。spring-boot-starter: 核心 Starter,包含自动配置、日志等。spring-boot-starter-tomcat: 内嵌的 Tomcat 服务器。jackson-databind: JSON 序列化/反序列化。- ... (还有很多)
- 效果:引入它后,你就可以使用
@RestController,@RequestMapping等注解来开发 Web 服务,并且项目自带一个 Web 服务器,可以直接运行。
spring-boot-starter-actuator:- 作用:提供生产级别的监控和管理功能。
- 包含内容:引入后,会自动暴露一些 HTTP 端点(endpoints),如:
/actuator/health: 查看应用健康状况。/actuator/info: 查看应用信息。/actuator/metrics: 查看应用指标(内存、CPU、HTTP 请求等)。/actuator/shutdown: (需配置)关闭应用。
- 效果:极大地方便了应用的运维和监控。
spring-boot-starter-test:- 作用:提供测试支持。
- 范围:
<scope>test</scope>,表示它只在测试阶段有效,不会被打包到最终的应用中。 - 包含内容:它会自动引入:
junit-jupiter(JUnit 5)spring-test和spring-boot-test: Spring 测试支持。mockito-core: Mock 框架。assertj-core: 流式断言库。json-path: 用于 JSON 断言。
- 效果:你可以方便地编写单元测试和集成测试。
5. 构建配置 (<build>)
定义了项目的构建过程,主要是插件的配置。
maven-compiler-plugin:- 作用:Maven 的编译插件,负责将
.java文件编译成.class文件。 <version>3.8.1</version>: 指定插件版本。<configuration>:<source>17</source>: 设置编译源码的 Java 版本为 17。<target>17</target>: 设置生成的字节码兼容的 Java 版本为 17。<encoding>UTF-8</encoding>: 设置编译时的源文件编码。
- 注意:虽然
java.version属性通常会被 Spring Boot 插件识别,但显式配置编译插件可以确保万无一失。
- 作用:Maven 的编译插件,负责将
spring-boot-maven-plugin:- 作用:Spring Boot 的核心插件。它提供了几个关键功能:
repackage目标: 这是最主要的功能。它会将项目打包成一个可执行的 JAR/WAR (Executable JAR)。这个 JAR 不仅包含你自己的代码和依赖,还包含一个引导类加载器,使得你可以直接通过java -jar demo-0.0.1-SNAPSHOT.jar来运行应用,而无需外部的 Servlet 容器。- 创建
MANIFEST.MF: 在 JAR 的清单文件中写入Main-Class信息,指向 Spring Boot 的启动类。 - 集成到
package阶段: 通过<execution>配置,repackage目标被绑定到package阶段。这意味着当你执行mvn package时,插件会自动运行。
<version>${spring-boot.version}</version>: 使用之前定义的属性,确保插件版本与 Spring Boot 版本一致。<configuration>:<mainClass>com.example.demo.DemoApplication</mainClass>: 重要。显式指定应用的主启动类。虽然插件通常能自动找到带有@SpringBootApplication注解的类,但显式指定可以避免歧义。<skip>true</skip>: 这个配置有点特殊。<skip>true</skip>通常用于跳过某个插件的执行。在这里设置为true可能是一个错误,或者有特定目的(比如在某些 profile 下跳过 repackage)。在标准配置中,这行通常不存在或设置为false。如果设置为true,repackage目标将不会执行,最终生成的 JAR 将不可执行。建议检查是否需要移除或改为false。
<executions>:- 明确地将
repackage目标绑定到package阶段。<id>repackage</id>是执行的标识符。
- 明确地将
- 作用:Spring Boot 的核心插件。它提供了几个关键功能:
