文章

Maven 的使用

Maven 官方指南:https://maven.apache.org/guides/getting-started/index.html

Maven 环境配置

1.从官网下载 Maven

2.创建本地仓库地址

在 Maven 文件夹中,创建一个 repository 文件夹,用来当本地仓库。(推荐做法,非必须)

3.修改配置文件(conf/settings.xml)添加本地仓库地址

1
<localRepository>F:\apache-maven-3.8.4\repository</localRepository>

4.修改配置文件(conf/settings.xml)可添加多个远程仓库地址

1
2
3
4
5
6
<mirror>
  <id>aliyunmaven</id>
  <mirrorOf>*</mirrorOf>
  <name>阿里云公共仓库</name>
  <url>https://maven.aliyun.com/repository/public</url>
</mirror>

5.配置环境变量

Windows PowerShell 终端:

1
2
3
4
5
6
7
# 设置 MAVEN_HOME 环境变量
[System.Environment]::SetEnvironmentVariable('MAVEN_HOME', 'F:\Java\apache-maven-3.8.4', [System.EnvironmentVariableTarget]::Machine)

# 将 %MAVEN_HOME%\bin 添加到 Path 环境变量
$oldPath = [System.Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine)
$newPath = "$oldPath;%MAVEN_HOME%\bin"
[System.Environment]::SetEnvironmentVariable('Path', $newPath, [System.EnvironmentVariableTarget]::Machine)

Linux/Mac Command 终端:

1
2
3
echo 'export MAVEN_HOME=/path/to/apache-maven-3.8.4' >> ~/.zshrc
echo 'export PATH=$MAVEN_HOME/bin:$PATH' >> ~/.zshrc
source ~/.zshrc

6.最后,在 IDEA 中设置 Maven 主路径、配置文件及本地仓库地址即可

pom.xml 配置文件

POM 是指项目对象模型。 pom.xml 就是每个 maven 项目的配置文件,用以描述项目的各种信息。 pom.xml 基本文件结构如下:

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
<project>
    <modelVersion></modelVersion>     <!-- modelVersion 指定 pom.xml 符合哪个版本-->
    <groupId></groupId>               <!-- groupId 组织标识,定义了项目属于哪个组-->
    <artifactId></artifactId>         <!-- artifactId 工件id 项目名称,定义当前Maven项目在组中唯⼀的id-->
    <version></version>               <!-- version 当前项目的版本号-->
    <!-- 一般 jar 包被识别为 groupId:artifactId:version 的形式。-->

    <!-- 项目属性设置-->
    <properties>
        <project.build.sourceEncoding></project.build.sourceEncoding>
        <maven.compiler.source></maven.compiler.source>
        <maven.compiler.target></maven.compiler.target>
    </properties>

    <!-- 项目依赖管理-->
    <dependencies>
        <dependency>
            <groupId></groupId>
            <artifactId></artifactId>
            <version></version>
            <!-- 添加排除项,一般在依赖冲突的情况下添加-->
            <exclusions>
                <exclusion>
                    <groupId></groupId>
                    <artifactId></artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <!-- 项目构建配置-->
    <build>
        <!-- 构建过程支持使用各类的插件完成构建-->
        <plugins>
            <plugin>
                <groupId></groupId>
                <artifactId></artifactId>
                <version></version>
                <configuration>
                    <source></source>
                    <target></target>
                    <compilerArgs></compilerArgs>
                </configuration>
            </plugin>
        </plugins>

        <!-- 在特定情况下,打包资源文件时使用,一般不用 -->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

项目的属性设置 <properties> … </properties> 标签中的内容,定义之后就可以直接使用 %{标签名} 来调用。

使用示例如下:

1
2
3
4
5
6
7
8
9
10
<properties>
    <revision>1.0.0</revision>         <!-- 用于自动化版本管理,结合 CI/CD 工具生成动态版本号 -->
    <changelist>-SNAPSHOT</changelist> <!-- 用于区分开发版本和发布版本,生产环境留空,开发环境设置为-SNAPSHOT -->
</properties>

<dependency>
    <groupId>com.example</groupId>
    <artifactId>my-artifact</artifactId>
    <version>${revision}${changelist}</version>
</dependency>

Lifecycle 生命周期

  1. clean
    清空当前编译好的 class 文件

  2. validate
    验证项目是否正确,并且所有必要信息都可用

  3. compile
    将 java 编译成 class 文件(编译项目的源代码)

  4. test
    使用合适的单元测试框架运行测试 , 测试代码不会被打包或部署(执行测试用例)

  5. package
    将编译后的代码打包成可分发的格式,比如 jar

  6. verify
    运行任何检查以验证包是否有效并符合质量标准

  7. install
    将打包后的 jar 包放入本地仓库,供本地其他 maven 项目使用

  8. site
    生成项目站点文档

  9. deploy
    将 jar 包上传至中央仓库(将最终包复制到远程仓库,供其他开发人员和 maven 项目使用)

Plugins 插件

Maven 提供了很多且强大的插件。官网地址:https://maven.apache.org/plugins/index.html

Apache Maven Shade Plugin

使用 maven-shade-plugin 插件,对 maven 项目中包含的各种依赖打包成单个 jar 包程序(Uber-JAR)。

参考官方提供的使用案例:https://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html

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
<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.6.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <minimizeJar>true</minimizeJar>
              <shadedArtifactAttached>true</shadedArtifactAttached>
              <shadedClassifierName>shaded</shadedClassifierName>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <mainClass>org.example.Main</mainClass>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Apache Maven Assembly Plugin

maven-assembly-plugin 是一个更通用的打包插件,它可以创建多种格式的分发包,如 ZIP、TAR、JAR、WAR 等。它也可以将项目依赖打包到一个 JAR 文件中,但它的重点是创建复杂的分发包。

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
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.3.0</version>
    <configuration>
        <archive>
            <manifest>
                <mainClass>org.example.Main</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <!-- jar 携带依赖 -->
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <formats>
            <format>jar</format>
            <format>zip</format>
        </formats>
        <outputDirectory>${project.build.directory}</outputDirectory>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <appendAssemblyId>true</appendAssemblyId>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Apache Maven Dependency Plugin

使用 maven-dependency-plugin 插件,可以将项目中的依赖的 jar 包和 source 源码保存到指定的目录。

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
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.6.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/dependency-lib</outputDirectory>
            </configuration>
        </execution>
        <execution>
            <id>src-dependencies</id>
            <phase>package</phase>
            <goals>
                <!-- use copy-dependencies instead if you don't want to explode the sources -->
                <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
                <classifier>sources</classifier>
                <outputDirectory>${project.build.directory}/dependency-source</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

Apache Maven JAR Plugin

使用 maven-jar-plugin 插件,配置 jar 包中 MANIFEST.MF 内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <archive>
            <!-- 配置生成的 jar 包中,是否包含 pom.xml 和 pom.properties 这两个文件 -->
            <addMavenDescriptor>false</addMavenDescriptor>
            <manifest>
                <!-- 是否要把第三方 jar 文件名,放到 MANIFEST.MF 的 Class-Path 属性中 -->
                <addClasspath>true</addClasspath>
                <!-- 为 Class-Path 属性值添加一个前缀,依赖 jar 包放置到该目录即可 -->
                <classpathPrefix>lib/</classpathPrefix>
                <!-- 指定 MANIFEST.MF 中 Main-Class 属性值-->
                <mainClass>org.example.Main</mainClass>
            </manifest>
            <!-- 手动添加 MANIFEST.MF 配置中的属性值 -->
            <manifestEntries>
                <Custom>value</Custom>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

Apache Maven Resources Plugin

默认情况 maven 只打包 src/main/resource 下的资源文件,使用 maven-resources-plugin 插件可以将其它位置的资源文件也打包进 jar 包中。

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
<!-- 把源代码中的 xml 文件,打包到相应位置 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.3.1</version>
    <executions>
        <execution>
            <id>copy-xmls</id>
            <phase>process-sources</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${basedir}/target/classes</outputDirectory>
                <resources>
                    <resource>
                        <directory>${basedir}/src/main/java</directory>
                        <includes>
                            <include>**/*.xml</include>
                        </includes>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

多模块项目配置

项目结构:

1
2
3
4
5
6
7
8
9
10
11
12
parent-project
│   pom.xml   # 父 POM 文件
│
├───module-a
│       pom.xml
│       src
│       ...
│
├───module-b
        pom.xml
        src
        ...

使用 ${revision} 管理多模块版本。

父项目 pom.xml 配置:

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?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.github.h0ny</groupId>
    <artifactId>payload-generator-parent</artifactId>
    <version>${revision}</version>
    <packaging>pom</packaging>

    <name>JPG - java payload generator</name>
    <description>暂无描述</description>
    <url>https://github.com/h0ny/payload-generator/</url>

    <modules>
        <module>payload-generator-core</module>
        <module>payload-generator-memshell</module>
        <module>payload-generator-ysoserial</module>
    </modules>

    <properties>
        <revision>1.0.0</revision>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <hutool.version>5.8.32</hutool.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-core</artifactId>
                <version>${hutool.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <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>
                <!-- Create sources.jar -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.3.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>3.0.0-M1</version>
                <configuration>
                    <autoVersionSubmodules>true</autoVersionSubmodules>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

子项目 pom.xml 配置:

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
<?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>

    <parent>
        <groupId>com.github.h0ny</groupId>
        <artifactId>payload-generator-parent</artifactId>
        <version>${revision}</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.github.h0ny</groupId>
            <artifactId>payload-generator-core</artifactId>
            <version>${revision}</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
        </dependency>
    </dependencies>

    <artifactId>payload-generator-memshell</artifactId>
    <packaging>jar</packaging>

</project>

父模块中的 <dependencyManagement></dependencyManagement> 是为了方便管理子模块中的依赖版本,在父模块中定义后并不会自动在子模块中导入该模块,子模块中任然需要手动 dependencies 导入,只是不需要指定版本了。

而如果在父亲模块中使用 <dependencies></dependencies> 直接导入依赖,则所有子模块会自动导入该依赖。

本文由作者按照 CC BY 4.0 进行授权

© h0ny. 保留部分权利。

本站由 Jekyll 生成,采用 Chirpy 主题。