java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > maven pom

史上最全maven中的pom详述

作者:TimelyRain_yt

pom是maven的基本工作单元,它是一个XML文件,其中包含有关项目的信息以及Maven用于构建项目的配置详细信息,本文给大家介绍maven中的pom详述,感兴趣的朋友一起看看吧

maven中的pom详述

什么是POM?

POM(Project Object Model)是maven的基本工作单元。它是一个 XML 文件,其中包含有关项目的信息以及 Maven 用于构建项目的配置详细信息。简单来说:POM(pom.xml)就是整个工程的项目规划书,它定义了项目的所有细节:需要什么材料(依赖)、由谁建造(开发者信息)、如何建造(构建配置)、以及项目的版本等

超级POM

超级 POM 是 Maven 的默认 POM。除非显式设置,否则所有 POM 都会扩展超级 POM,这意味着超级 POM 中指定的配置将为项目创建的 POM 继承。超级POM可以理解为MAVEN世界的宪法,所有maven项目都必须遵守。超级POM中定义了一些默认配置,下面列举几个:

默认目录结构

<!-- 源代码目录 -->
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
    <resource>
        <directory>src/main/resources</directory>
    </resource>
</resources>
<!-- 测试代码目录 -->  
<testSourceDirectory>src/test/java</testSourceDirectory>
<testResources>
    <testResource>
        <directory>src/test/resources</directory>
    </testResource>
</testResources>
<!-- 输出目录 -->
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>

这就是为什么所有 Maven 项目都长得一样的原因

默认仓库配置

<repositories>
    <repository>
        <id>central</id>
        <name>Central Repository</name>
        <url>https://repo.maven.apache.org/maven2</url>
    </repository>
</repositories>

所有依赖默认都从 Maven 中央仓库下载。

默认插件配置及默认插件版本管理

构建阶段默认插件作用
compilemaven-compiler-plugin编译源代码
testmaven-surefire-plugin运行单元测试
packagemaven-jar-plugin打包成 JAR 文件
installmaven-install-plugin安装到本地仓库

对不同构建阶段绑定了不同的插件。

默认打包配置

<!-- 默认打包方式就是 JAR -->
<packaging>jar</packaging>

最小的 POM

POM 用三坐标(groupId、artifactId、version)的方式唯一标识一个项目。可以理解成项目的身份证。如:

<project> <!-- 说:这是个项目 -->
  <modelVersion>4.0.0</modelVersion> <!-- 说:用第4版规则 -->
  <groupId>com.mycompany.app</groupId> <!-- 姓:公司/组织名 -->
  <artifactId>my-app</artifactId> <!-- 名:项目具体叫啥 -->
  <version>1</version> <!-- 排行:这是第几个版本 -->
</project>

POM核心元素

一个标准的 POM 文件包含以下核心元素:

坐标(Coordinates) - 项目的唯一标识

这三个元素(groupId, artifactId, version)合称为GAV,是 Maven 世界的唯一身份证。

依赖管理(Dependencies)

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
        <optional>false</optional>
        <exclusions>
            <exclusion>
                <groupId>org.hamcrest</groupId>
                <artifactId>hamcrest-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
<project>
  <groupId>com.example</groupId>
  <artifactId>project-A</artifactId>
  <version>1.0.0</version>
  ...
  <dependencies>
    <!-- 可选依赖:MySQL驱动 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.28</version>
      <optional>true</optional>
    </dependency>
    <!-- 可选依赖:PostgreSQL驱动 -->
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>42.3.6</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
</project>

现在,有另一个项目project-B依赖了project-A:

<project>
  <groupId>com.example</groupId>
  <artifactId>project-B</artifactId>
  <version>1.0.0</version>
  ...
  <dependencies>
    <dependency>
      <groupId>com.example</groupId>
      <artifactId>project-A</artifactId>
      <version>1.0.0</version>
    </dependency>
  </dependencies>
</project>

那么,project-B不会自动传递依赖MySQL和PostgreSQL驱动。如果project-B需要用到MySQL,那么它必须在自己的POM中显式声明MySQL驱动。

父 POM 与继承(Parent)

用于从父 POM 继承配置,实现统一管理。类似于JAVA中的继承。

注意点:

  1. 父POM的packaging必须是pom。
  2. 子POM通过元素指定父POM,其中groupId、artifactId、version必须与父POM的坐标一致。
  3. relativePath:指定查找父POM的相对路径。默认值是…/pom.xml,即先从本地文件系统查找,如果没找到,再从仓库查找。
  4. 如果设置为空,则表示不从相对路径查找,直接从仓库查找。
  5. 继承的内容:父POM中定义的依赖、插件、属性、依赖管理、插件管理等都可以被继承。

总的来说:

relativePath规则:

设置方式策略适用场景
<relativePath/></font>
空标签
1. 去本地仓库找 2. 去远程仓库找父POM是知名框架(Spring Boot)
<relativePath>../pom.xml</relativePath></font>1. 去…/pom.xml找 2. 找不到再去仓库父POM在本地项目里

示例1:

子pom文件:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
    <relativePath/>
</parent>
<artifactId>my-app</artifactId>
<!-- 只写了自己的名字,其他都没写 -->

实际生效的配置:

<!-- 自动获得老爸的配置 -->
<properties>
    <java.version>11</java.version>           <!-- Java 11 -->
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 自动获得依赖版本管理 -->
<dependencyManagement>
    <!-- Spring Boot 2.7.0 兼容的所有版本 -->
    <spring.version>5.3.20</spring.version>
    <jackson.version>2.13.3</jackson.version>
    <!-- ... -->
</dependencyManagement>
<!-- 自动获得插件配置 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

项目聚合(Modules)

目的:用于将多个模块/子项目聚合在一起,以便一次性构建整个项目

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany</groupId>
  <artifactId>my-app-aggregator</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>   <!-- 必须为pom -->
  <modules>
    <module>core-module</module>   <!-- 相对路径,表示聚合项目目录下的core-module目录 -->
    <module>service-module</module>
    <module>web-module</module>
  </modules>
</project>

这通常用在父 POM(其 packaging 为 pom)中。聚合项目本身可以没有源码,它只是作为一个构建的入口。在聚合项目目录下执行mvn命令,Maven会根据模块间的依赖关系自动确定构建顺序,依次构建每个模块。

聚合和继承经常结合使用:聚合项目同时作为父项目,提供统一的配置管理。这种情况下,聚合项目的pom.xml中既有也有等配置。

示例:

<project>
    <modelVersion>4.0.0</modelVersion>
    <!-- 聚合项目的身份证 -->
    <groupId>com.mycompany</groupId>
    <artifactId>ecommerce-platform</artifactId>
    <version>1.0.0</version>
    <!-- 关键:打包方式必须是pom -->
    <packaging>pom</packaging>
    <!-- 聚合的核心:列出所有小弟 -->
    <modules>
        <module>user-service</module>      <!-- 用户服务模块 -->
        <module>product-service</module>   <!-- 商品服务模块 -->
        <module>order-service</module>     <!-- 订单服务模块 -->
        <module>common</module>            <!-- 公共模块 -->
    </modules>
    <!-- 注意:聚合项目可以同时是父项目 -->
    <properties>
        <java.version>11</java.version>
        <spring-boot.version>2.7.0</spring-boot.version>
    </properties>
    <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>
</project>
<!-- user-service/pom.xml -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <!-- 既可以认父(继承),又可以被聚合 -->
    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>ecommerce-platform</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <!-- 自己的身份证 -->
    <artifactId>user-service</artifactId>
    <packaging>jar</packaging>  <!-- 子模块通常是jar或war -->
    <dependencies>
        <!-- 依赖common模块 -->
        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 其他业务依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

不使用聚合:

# 要跑4次命令,还要注意构建顺序!
cd common && mvn clean install
cd ../user-service && mvn clean install  
cd ../product-service && mvn clean install
cd ../order-service && mvn clean install

使用后:

# 在聚合项目根目录,一次搞定!
cd ecommerce-platform
mvn clean install
# Maven自动处理:
# 1. 分析模块依赖关系(common → user-service → ...)
# 2. 按正确顺序构建
# 3. 一次性输出所有结果
platform/
├── pom.xml(聚合所有微服务)
├── gateway/(网关服务)
├── user-service/(用户服务)
├── order-service/(订单服务)
└── product-service/(商品服务)

属性(Properties)

用于定义变量,方便统一管理和复用,常见在父POM中定义公共属性。

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <spring.version>5.3.20</spring.version>
</properties>
<!-- 在依赖中使用属性 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>

属性的常见用法:

<properties>
    <!-- 默认开发环境配置 -->
    <env>dev</env>
    <server.port>8080</server.port>
    <database.url>jdbc:mysql://localhost:3306/dev</database.url>
</properties>
<profiles>
    <profile>
        <id>prod</id>
        <properties>
            <!-- 生产环境覆盖默认值 -->
            <env>prod</env>
            <server.port>80</server.port>
            <database.url>jdbc:mysql://prod-server:3306/prod</database.url>
        </properties>
    </profile>
</profiles>

构建配置(Build)

用于配置构建过程中的插件和行为。

构建配置可以包含两个主要部分:

此外,构建配置还包括:

一般为:

<build>
    <!-- 1. 源代码目录(可以改默认位置) -->
    <sourceDirectory>src/main/java</sourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>
    <!-- 2. 资源文件处理 -->
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering> <!-- 是否替换占位符 -->
        </resource>
    </resources>
    <!-- 3. 插件管理(父POM中用) -->
    <pluginManagement>
        <plugins>
            <!-- 定义插件版本和基础配置 -->
        </plugins>
    </pluginManagement>
    <!-- 4. 实际使用的插件 -->
    <plugins>
        <!-- 具体配置每个插件 -->
    </plugins>
    <!-- 5. 扩展(自定义组件) -->
    <extensions>
        <!-- 扩展Maven核心功能 -->
    </extensions>
</build>
<build>
    <plugins>
        <!-- Spring Boot打包插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.7.0</version>
            <configuration>
                <mainClass>com.mycompany.app.Application</mainClass>
              <!-- lombok只在编译时起作用,已经变成class了,不需要再打jar包依赖了 -->
                <excludes>
                    <exclude>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                    </exclude>
                </excludes>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal> <!-- 生成可执行JAR -->
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
<!-- 在父POM中统一管理插件版本 -->
<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
<!-- 在子POM中引用,不需要写版本 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <!-- 版本从父POM继承 -->
        </plugin>
    </plugins>
</build>
<profiles>
    <profile>
        <id>production</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <skipTests>true</skipTests> <!-- 生产环境跳过测试 -->
                    </configuration>
                </plugin>
            </plugins>
            <resources>
                <resource>
                    <directory>src/main/resources-prod</directory>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    </profile>
</profiles>

依赖管理(DependencyManagement)

: 只是一个声明,它并不实际引入依赖。它主要用于统一管理子模块或项目的依赖版本。子模块需要显式声明依赖,但可以省略 version。如:

示例1:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <!-- 不需要写版本,版本由父POM统一管理 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

示例2:

<!-- 直接使用Spring Boot定义的所有版本 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.7.0</version>
            <type>pom</type>
            <scope>import</scope>  <!-- 关键:导入整个版本表 -->
        </dependency>
    </dependencies>
</dependencyManagement>
<!-- 现在所有Spring Boot相关的依赖都不用写版本了 -->
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- 自动使用2.7.0对应的版本 -->
    </dependency>
</dependencies>

关键标签:合并另一个POM的依赖管理。类似于继承别人的dependencyManagement一样。

当父POM中配置了,子模块继承的是依赖的管理规则(主要是版本信息),而不是依赖本身。这带来了几个显著优势:

Profile

Profile 允许为不同的环境(如开发、测试、生产)定义不同的配置。它能够覆盖 POM 中的默认配置。

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <db.url>jdbc:mysql://localhost:3306/dev</db.url>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault> <!-- 默认激活 -->
        </activation>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <db.url>jdbc:mysql://prod-server:3306/prod</db.url>
        </properties>
    </profile>
</profiles>
# 用命令激活
mvn clean install -P prod

一个相对完整的POM

<?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
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 坐标 -->
    <groupId>com.example</groupId>
    <artifactId>my-webapp</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>My Web Application</name>
    <!-- 父POM -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>
    <!-- 属性 -->
    <properties>
        <java.version>11</java.version>
        <junit.version>5.8.2</junit.version>
    </properties>
    <!-- 依赖管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- 可以在这里管理非Spring Boot管理的依赖 -->
        </dependencies>
    </dependencyManagement>
    <!-- 依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!-- 构建配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <!-- 多环境配置 -->
    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <activatedProperties>prod</activatedProperties>
            </properties>
        </profile>
    </profiles>
</project>

到此这篇关于史上最全maven中的pom详述的文章就介绍到这了,更多相关maven pom内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文