Apache Maven

Apache Maven

Maven Introduction

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.

Maven’s main functions

  • manage project dependencies
  • build project artifacts

Maven’s Mechanism

Dependency

Dependency Management

Dependency management is one of Maven’s most powerful features. It allows developers to declare the libraries their project depends on, and Maven will automatically download these libraries and their dependencies from remote repositories.

In a Maven project, dependencies are declared in the pom.xml file. Together, the combination of groupId, artifactId, and version forms a unique coordinate that Maven uses to locate, download, and manage dependencies. This coordinate system is critical for resolving dependencies during the build process and ensuring that the correct versions of libraries are used in the project.

  • groupId: represents the organization or company that produces the project. It typically follows a reverse domain name convention to ensure uniqueness across the entire Maven ecosystem.
  • artifactId: identifies the specific project or module within the scope of the groupId. It is akin to the project’s name and should be unique within the groupId.
  • version: indicates the release version of the artifact. It follows semantic versioning rules and is crucial for dependency management.
1
2
3
4
5
6
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.13.2</version>
  <scope>test</scope>
</dependency>

POM

POM (Project Object Model) is the core configuration file used by Maven to manage a project. It is an XML file that contains information about the project, its dependencies, and other settings.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?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">
    <!-- Project Information -->
    <!-- Define the coordinates of the project. -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- Specifies the type of the package to be built (e.g., jar, war, ear). -->
    <packaging>jar</packaging>

    <!-- Project Description -->
    <!-- Provide human-readable information about the project. -->
    <name>My Java Application</name>
    <description>This is a simple Java application using Maven.</description>
    <url>http://example.com/my-app</url>

    <!-- Repositories -->
    <!-- Defines repositories where Maven looks for dependencies. -->
    <repositories>
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
        </repository>
    </repositories>

    <!-- ⭐Dependencies -->
    <!-- <dependencies>: Lists the project's direct dependencies. -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.15</version>
        </dependency>
    </dependencies>

    <!-- Build Settings -->
    <!-- <build>: Contains configuration for the build process. -->
    <!-- <plugins>: Configures Maven plugins that extend Maven's functionality, such as compiling the code or creating a JAR file. -->
    <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.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Maven enforces a standardized directory layout for several key reasons, which contribute significantly to the efficiency, maintainability, and consistency of projects managed by Maven.

Convention Over Configuration
Configuration Over Code

Project Structure

JAR(Java ARchive) project structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.
├── pom.xml                  # Maven project configuration file
├── src
   ├── main
      ├── java            # Java source code
         └── com.example # Package structure for classes
      ├── resources       # Resource files (like properties, XML)
         └── config.properties # Example resource file
   └── test                # Test source code and resources
       ├── java            # Test Java source code
          └── com.example # Package structure for test classes
       └── resources       # Test resources
└── target                  # Built output goes here
    ├── classes             # Compiled .class files
    └── my-library.jar      # Final JAR file after build

WAR(Web ARchive) project structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.
├── pom.xml                  # Maven project configuration file
├── src
   ├── main
      ├── java            # Java source code
         └── com.example # Package structure for classes
      ├── resources       # Resource files (like properties, XML)
      └── webapp          # Web application content
          ├── WEB-INF     # Web application metadata and private files
             ├── classes # Compiled .class files
             ├── lib     # JAR files (dependencies)
             └── web.xml # Deployment descriptor
          ├── index.jsp   # Main entry point for the web app
          ├── static      # Static resources (CSS, JavaScript, images)
             ├── css
             ├── js
             └── img
          └── META-INF    # Metadata information
   └── test                # Test source code and resources
└── target                  # Built output goes here, including the .war file
    └── classes             # Compiled test classes

Dependency Scope

Maven uses dependency scopes to control how dependencies are included during different stages of the build process. The most common scopes include:

  • compile
    This is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.
  • provided
    This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
  • runtime
    This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
  • test
    This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. This scope is not transitive.
  • system
    This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
  • import (only available in Maven 2.0.9 or later)
    This scope is only supported on a dependency of type pom in the section. It indicates the dependency to be replaced with the effective list of dependencies in the specified POM’s section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
scopevalid rangetransitiveexample
compileallspring-core
providedcompile, testservlet-api
runtimeruntime, testJDBC
testtestJUnit
systemcompile, test

Transitive Dependency

A transitive dependency occurs when a project directly depends on another project, which in turn depends on a third project. Maven manages these transitive dependencies automatically, ensuring that all required libraries are available during the build process.

Exclude Dependencies

Maven allows you to exclude dependencies from a project by adding them to the <exclusions> tag in the <dependency> tag. This can be useful when you want to use a different version of a dependency than the one specified in the parent project.

Maven Lifecycle

The Maven lifecycle is a series of phases that define the order in which tasks are executed. The most commonly used lifecycle is the default lifecycle, which includes the following phases:

  • validate Validates that the project is correct and all necessary information is available.
  • compile Compiles the source code of the project.
  • test Runs tests for the project.
  • package Takes the compiled code and packages it in its distributable format, such as a JAR.
  • integrationtest: Processes and deploys the package if necessary into an environment where integration tests can be run.
  • verify Runs any checks to verify the package is valid and meets quality criteria.
  • install Installs the package into the local repository, for use as a dependency in other projects locally.
  • deploy Copies the final package to the remote repository for sharing with other developers and projects.

Maven Advanced

Multi-module Project

Maven 的分模块设计(Multi-module Project)是一种组织大型项目的常用方式,将一个复杂的项目拆分为多个相互依赖的子模块,每个模块都作为一个独立的 Maven 项目进行管理。通过这种设计,项目的代码结构清晰、模块化程度高,有利于代码复用、依赖管理和开发效率的提升。

Concepts

  • 父项目(Parent Project):
    • 父项目是一个顶层的 Maven 项目,通常只包含一个 pom.xml 文件,没有实际的代码。它定义了所有子模块的公共配置(如依赖管理、插件配置等)。
    • 父项目的 pom.xml 文件中包含对子模块的引用,同时可以定义整个项目的版本、依赖管理和构建过程。
  • 子模块(Submodules):
    • 每个子模块是父项目的一个部分,也是一个独立的 Maven 项目,拥有自己的 pom.xml 文件。
    • 子模块可以是服务、库或工具,每个模块负责特定的功能,彼此通过依赖关系进行互操作。
    • 子模块通过 modules 元素定义在父项目中,并且它们通常共享父项目中定义的依赖和插件。

Maven 继承与聚合是 Maven 项目管理中两个核心的概念,特别是在处理多模块(multi-module)项目时非常重要。它们帮助我们组织、共享和管理多个相关项目的配置和依赖。

  • 继承是子项目从父项目中获取公共配置,主要用于代码复用和依赖管理

  • 聚合是通过一个父项目统一构建多个子模块,主要用于多模块项目的整体管理,父项目方便快速构建(无需根据依赖关系手动构建,直接在聚合工程上构建即可)。

  • 作用:聚合用于快速构建项目;继承用于简化依赖配置、统一管理依赖

  • 相同点:聚合与继承的pom.xml文件打包方式均为 pom ,可以将两种关系制作到同一个 pom 文件中;聚合与继承均属于设计型模块,并无实际的模块内容

  • 不同点:聚合是在聚合工程中配置关系,聚合可以感知到参与聚合的模块有哪些;继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

Maven Inheritance

Maven 的继承机制允许一个项目继承另一个项目的配置。这使得多个相关项目可以共享相同的构建配置、依赖管理、插件等,减少重复的配置,提高代码的维护性。

继承特点

  • 父项目与子项目:子项目(子模块)可以继承父项目中的配置,一个子项目只能继承一个父项目
  • 层级关系:Maven 使用继承树的方式组织项目,子项目的 pom.xml 文件通过标签来声明其父项目
  • 继承的元素:子项目可以继承父项目中的依赖管理(dependencyManagement)、构建插件、版本控制、属性等。若父子工程者己置了同一个依赖的不同版本,子工程会以自身的 pom.xml 为准(类似于 override)

可继承的 POM 元素有

  • groupId:项目组 ID,项目坐标的核心元素。
  • version:项目版本,项目坐标的核心因素。
  • description:项目的描述信息。
  • organization:项目的组织信息。
  • inceptionYear:项目的创始年份。
  • url:项目的 URL 地址。
  • developers:项目的开发者信息。
  • contributors:项目的贡献者信息。
  • distributionManagement:项目的部署配置。
  • issueManagement:项目的缺陷跟踪系统信息。
  • ciManagement:项目的持续集成系统信息。
  • scm:项目的版本控制系统。
  • malilingLists:项目的邮件列表信息。
  • properties:自定义的 Maven 属性。
  • dependencies:项目的依赖配置。
  • dependencyManagement:项目的依赖管理配置。
  • repositories:项目的仓库配置。
  • build:包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等。
  • reporting:包括项目的报告输出目录配置、报告插件配置等。

<dependencyManagement><dependencies> 的区别是什么?
<dependencies> 是直接依赖,在父工程配置了依赖,子工程会直接继承下来。
<dependencyManagement> 是统一管理依赖版本,不会直接依赖,还需要在子工程中引入所需依赖(无需指定版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?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.thr</groupId>
    <artifactId>Parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <!-- 集中定义依赖版本号 -->
    <properties>
        <spring.version>5.2.6.RELEASE</spring.version>
        <junit.version>4.11</junit.version>
    </properties>

    <!-- 版本锁定,当子模块中有需要并且自行添加了具体依赖后才有效,
    它仅仅是起到锁定作用,不下载依赖包 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>

            <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project

Maven Aggregation

聚合指的是通过一个父项目管理多个子模块,使它们可以作为一个整体来构建。父项目负责定义和管理所有子模块,并且当我们在父项目中执行构建命令时,所有子模块都会一起构建。例如一辆汽车是由轮胎、发动机、底盘、电器设备等等聚合而成

聚合特点

  • 父项目和模块列表:聚合项目的父项目通过 <modules>元素定义其包含的所有子模块。
  • 模块的独立构建:虽然子模块可以独立构建,但通过父项目的聚合,多个模块可以一次性全部构建或安装。
  • 适用于多模块项目:聚合适用于大型项目,能够将多个模块组织在一个项目下,同时共享相同的构建过程。

Application Scenarios

大型企业项目:随着项目的扩展,代码量和复杂性增加,通过模块化设计可以让项目的各个部分保持清晰。
微服务架构:每个微服务可以作为一个模块进行管理,各个模块间可以通过接口和依赖进行交互。
插件开发:多个模块的项目中可以有一个核心模块,其他模块可以作为插件扩展核心功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>aggregator-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <!-- 聚合的子模块 -->
    <modules>
        <module>module1</module>
        <module>module2</module>
    </modules>
</project

Private Repository

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题。

项目版本:

  • RELEASE(发行版本):功能趋于稳定、当前更新停止,可以用于发行的版本,存储在私服中的 RELEASE 仓库中。
  • SNAPSHOT(快照版本):功能不稳定、尚处于开发中的版本,即快照版本,存储在私服的 SNAPSHOT 仓库中。

访问私服步骤

  1. 填入私服的访问用户名/密码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    FILE:settings.xml
    <server>
        <id>maven-releases</id>
        <username>admin</username>
        <password>admin</password>
    </server>
    <server>
        <id>maven-snapshots</id>
        <username>admin</username>
        <password>admin</password>
    </server>
  2. IDEA 的 maven 工程的 pom 文件中配置上传(发布)地址
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <distributionManagement>
        <repository>
            <id>maven-releases</id>
            <url>http://192.168.150.101:8081/repository/maven-releases/</url>
        </repository>
        <snapshotRepository>
            <id>maven-snapshots</id>
            <url>http://192.168.150.101:8081/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>
  3. 设置私服依赖下载的仓库组地址( settings.xml 中的 mirrors、profiles 中配置)
    1
    2
    3
    4
    5
    <mirror>
        <id>maven-public</id>
        <mirrorOf>*</mirrorOf>
        <url>http://192.168.150.101:8081/repository/maven-public/</url>
    </mirror>

Ref

Maven 工具学习(七)—-Maven 的继承与聚合
黑马程序员 JavaWeb

作者

Jiaxing Gao

发布于

2024-07-18

更新于

2024-11-23

许可协议

评论

}