Maven03-Maven使用入门

1、创建Maven项目的目录结构

  • 为maven-project01项目创建目录结构。首先创建一个名为maven-project01的文件夹,并在其下创建如下目录。

2、编写pom.xml

  • Maven项目的核心是pom.xml,就像Make的Makefile,Ant的build.xml一样。
  • POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建、声明项目依赖等。
<?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.mai.example</groupId>
    <artifactId>mavenproject01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>my-maven-project01</name>

</project>
  • pom.xml文档说明:
    • 第一行是XML头,指定了该xml文档的版本和编码方式。
    • 第二行是project元素,project是所有pom.xml的根元素,它声明了一些POM相关的命名空间及xad元素。虽然这些属性不是必须的,但使用这些属性能够让第三方工具(如IDE中的XML编辑器)帮助我们快速编辑POM。
    • 根元素下的第一个子元素是modelVersion,指定了当前POM模型的版本。对于Maven2和Maven3,它只能是4.0.0。
    • 这段代码中最重要的是groupId、artifactId和version。这三个元素定义了一个项目基本的坐标,在Maven中,任何的jar、pom或者war都是以基于这些基本的坐标进行区分的。
      • groupId定义了项目属于哪个组,这个组是项目所在的组织或公司。例如在googlecode上建立了一个名为myapp的项目,那么groupId就应该是com.googlecode.myapp。
      • artifactId定义了Maven项目在组中的唯一ID。
      • version指定了项目的版本,例如1.0.SNAPSHOT。SNAPSHOT意为快照,说明该项目还处于开发中,是不稳定的版本。
    • name元素声明了一个对于用户更为友好的项目名称,虽然这不是必须的,但还是推荐为每个POM声明name,以方便信息交流。
  • 没有任何Java代码,就可以定义一个Maven项目的POM,这体现了Maven的一大优点,它能让项目对象模型最大程度地与实际代码相独立,称之为解耦或者正交性。这在很大程度上避免了Java代码和POM代码的相互影响。比如当项目需要升级版本时,只需要修改POM,而不需要更改Java代码;而在POM稳定之后,日常的Java代码开发工作基本不涉及POM的修改。

3、编写主代码

  • 为了使项目结构保持清晰,主代码与测试代码应该分别位于独立的目录中。
    • 默认情况下,Maven主代码位于src\main\java目录。
    • 默认情况下,Maven测试代码位于src\test\java目录。
  • 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(如jar),而测试代码只在运行测试时用到,不会被打包

3.1、编写java代码

  • 遵循Maven的约定,在src\main\java目录下创建com\mai\example\mavenproject01\HelloWorld.java文件。
  • 这是一个简单的Java类,有一个sayHello()方法,返回一个String。同时这个类还有一个main方法,创建一个HelloWorld实例并调用sayHello()方法,并将结果输出到控制台。
package com.mai.example.mavenproject01;

public class HelloWorld {
        public String sayHello() {
                return "Hello World";
        }
        public static void main(String[] args) {
                System.out.println(new HelloWorld().sayHello());
        }
}
  • 关于该Java代码有两点需要注意。
    • 首先,在绝大多数情况下,应该把项目主代码放到src\main\java目录下(遵循Maven的约定),无须额外的配置,Maven会自动搜寻该目录找到项目主代码。
    • 其次,该Java类的包名是com.mai.example.mavenproject01,这与之前在POM中定义的groupId和artifactId相吻合。一般来说,项目中Java类的包都应该基于项目的groupId和artifactId,这样更加清晰,更加符合逻辑,也方便搜索构件或者Java类。

3.2、编译主代码

  • 使用Maven命令对项目进行编译,在项目根目录下执行命令mvn clean compile:
    • 为了简洁,一些不重要的信息用号略去了,Maven从中央仓库下载了一些东西到本地仓库中,供所有Maven项目使用
C:\...\maven-project01>mvn clean compile
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.mai.example:mavenproject01 >-------------------
[INFO] Building my-maven-project01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenproject01 ---
[INFO] Deleting C:\Users\hengha\Desktop\java-project\maven-project01\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.269 s
[INFO] Finished at: 2023-09-18T00:08:32+08:00
[INFO] ------------------------------------------------------------------------
  • clean会让Maven清理输出目录target/,compile会让Maven编译项目主代码,从输出中可以看到:
    • 首先执行了maven-clean-plugin:2.5:clean任务,删除target/目录。默认情况下,Maven构建的所有输出都在target/目录中。
    • 接着执行maven-resources-plugin:2.6:resources任务(未定义项目资源,暂且略过)。
    • 最后执行maven-compiler-plugin:3.1:compile任务,将项目主代码编译至target\classes目录(编译好的类为com\mai\example\mavenproject01\HelloWorld.Class)。
  • maven-clean-plugin:2.5:clean、maven-resources-plugin:2.6:resources和maven-compiler-plugin:3.1:compile对应Maven的插件及插件目标,比如maven-clean-plugin:2.5:clean是maven-clean-plugin:2.5插件的clean目标。

4、编写测试代码

4.1、引入JUnit依赖

  • 在Java中,由KentBeck和ErichGamma建立的JUnit是事实上的单元测试标准。要使用JUnit,首先要添加一个JUnit依赖,修改项目的pom.xml:
<?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.mai.example</groupId>
    <artifactId>mavenproject01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>my-maven-project01</name>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
  • 在pom.xml中添加了dependencies元素,该元素下可以包含多个dependency元素以声明项目的多个依赖。在Maven之前,可以去JUnit的官方网站下载,有了Maven,mvn会自动访问Mavne的中央仓库(https://repo1.maven.org/maven2/)。
  • scope元素是定义依赖的作用范围,若作用范围为test则表示该依赖只对测试有效。换句话说,测试代码中的import JUnit代码是没有问题的,但是如果在主代码中用import JUnit代码,就会造成编译错误。如果不声明依赖范围,那么默认值就是compile,表示该依赖对主代码和测试代码都有效。

4.2、编写测试代码

  • 配置了测试依赖后,就可以编写测试类了
  • 测试主代码HelloWorld类的sayHello()方法,就是检查其返回值是否为"Hello World"。
  • 遵循Maven的约定,在src\test\java目录下创建com\mai\example\mavenproject01\HelloWorldTest.java文件。
    • 首先初始化了一个要测试的HelloWorld实例,接着执行该实例的sayHello()方法并保存结果到result变量中,最后使用JUnit框架的Assert类检查结果是否为我们期望的"Hello World"。
package com.mai.example.mavenproject01;
import org.junit.Assert;
import org.junit.Test;
public class HelloWorldTest {
        @Test
        public void testSayHello() {
                HelloWorld helloWorld = new HelloWorld();
                String result = helloWorld.sayHello();
                Assert.assertEquals("Hello World", result);
        }
}
  • 单元测试一般包含三个步骤
    • (1)准备测试类及数据。
    • (2)执行要测试的行为。
    • (3)检查结果。
  • 在JUnit3中,约定所有需要执行测试的方法都以@Test开头。在JUnit4中,但仍然遵循这一约定。

4.3、进行测试

  • 使用Maven命令对项目进行测试,在项目根目录下执行命令mvn clean test:
    • Maven从中央仓库下载了junit-4.12.jar等文件到本地仓库中,供所有Maven项目使用。
C:\...\maven-project01>mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.mai.example:mavenproject01 >-------------------
[INFO] Building my-maven-project01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-surefire-plugin/2.12.4/maven-surefire-plugin-2.12.4.pom
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-surefire-plugin/2.12.4/maven-surefire-plugin-2.12.4.jar
Downloading from central: https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.jar
...
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenproject01 ---
[INFO] Deleting C:\Users\hengha\Desktop\java-project\maven-project01\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenproject01 ---
[INFO] Surefire report directory: C:\Users\hengha\Desktop\java-project\maven-project01\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mai.example.mavenproject01.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.086 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  42.468 s
[INFO] Finished at: 2023-09-18T01:23:52+08:00
[INFO] ------------------------------------------------------------------------
  • 从输出中可以看到:
    • 执行maven-compiler-plugin:3.1:testCompile任务对测试代码进行编译后,会在target\test-classes下生成了二进制文件。
    • 接着maven-surefire-plugin:2.12.4:test任务执行测试,surefire是Maven中负责执行测试的插件,这里它运行测试用例HelloWorldTest,并且输出测试报告,显示一共运行了多少测试,失败了多少,出错了多少,跳过了多少。
  • 在Maven执行测试(test)之前,它会先自动执行项目主资源处理、主代码编译、测试资源处理、测试代码编译等工作,这是Maven生命周期的一个特性

5、打包和安装

  • 将项目进行编译、测试之后,下一个重要步骤就是打包(package)。该pom.xml中没有指定打包类型,使用默认打包类型jar。

5.1、打包

  • 使用Maven命令对项目进行打包,在项目根目录下执行命令mvn clean package:
C:\...\maven-project01>mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.mai.example:mavenproject01 >-------------------
[INFO] Building my-maven-project01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenproject01 ---
[INFO] Deleting C:\Users\hengha\Desktop\java-project\maven-project01\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenproject01 ---
[INFO] Surefire report directory: C:\Users\hengha\Desktop\java-project\maven-project01\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mai.example.mavenproject01.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.168 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ mavenproject01 ---
[INFO] Building jar: C:\Users\hengha\Desktop\java-project\maven-project01\target\mavenproject01-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.006 s
[INFO] Finished at: 2023-09-18T02:01:16+08:00
[INFO] ------------------------------------------------------------------------
  • 从输出中可以看到:
    • maven-jar-plugin:2.4:jar任务负责打包,实际上就是jar插件的jar目标将项目主代码打包成一个名为mavenproject01-1.0-SNAPSHOT.jar的文件。该文件也位于target\日录中,它是根据artifactId-version.jar规则进行命名的,如有需要,还可以使用finalName来自定义该文件的名称
  • 如果有需要的话,就可以复制这个jar文件到其他项目的Classpath中从而使用HelloWorld类。

5.2、安装

  • 如何才能让其他的Maven项目直接引用这个jar呢?还需要一个安装的步骤,即使用Maven命令在项目根目录下执行命令mvn clean install:
C:\...\maven-project01>mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] -------------------< com.mai.example:mavenproject01 >-------------------
[INFO] Building my-maven-project01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenproject01 ---
[INFO] Deleting C:\Users\hengha\Desktop\java-project\maven-project01\target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenproject01 ---
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenproject01 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to C:\Users\hengha\Desktop\java-project\maven-project01\target\test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenproject01 ---
[INFO] Surefire report directory: C:\Users\hengha\Desktop\java-project\maven-project01\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.mai.example.mavenproject01.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.112 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ mavenproject01 ---
[INFO] Building jar: C:\Users\hengha\Desktop\java-project\maven-project01\target\mavenproject01-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ mavenproject01 ---
[INFO] Installing C:\Users\hengha\Desktop\java-project\maven-project01\target\mavenproject01-1.0-SNAPSHOT.jar to D:\maven-repo\com\mai\example\mavenproject01\1.0-SNAPSHOT\mavenproject01-1.0-SNAPSHOT.jar
[INFO] Installing C:\Users\hengha\Desktop\java-project\maven-project01\pom.xml to D:\maven-repo\com\mai\example\mavenproject01\1.0-SNAPSHOT\mavenproject01-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.472 s
[INFO] Finished at: 2023-09-18T02:10:10+08:00
[INFO] ------------------------------------------------------------------------
  • 从输出中可以看到:
    • maven-install-plugin:2.4:install任务将项目输出的jar安装到了Maven本地仓库中。只有将mavenproject01-1.0-SNAPSHOT.jar的构件安装到本地仓库之后,其他Maven项目才能使用它

6、生成可执行jar包

  • 默认打包生成的jar是不能够直接运行的,因为带有main方法的类信息不会添加到manifest中(打开jar文件中的META-INF/MANIFEST.MF文件,无法看到Main-Class)。为了生成可执行的jar文件,需要借助maven-shade-plugin,配置该插件如下:
<?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.mai.example</groupId>
    <artifactId>mavenproject01</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>my-maven-project01</name>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation = "org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.mai.example.mavenproject01.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
  • 在pom.xml中将mainClass配置为com.mai.example.mavenproject01.HelloWorld,在进行打包时会将该信息放到MANIFEST中。
  • 执行mvn clean install后,在target\目录中,可以看到mavenproject01-1.0-SNAPSHOT.jar和original-mavenproject01-1.0-SNAPSHOT.jar,前者是带有Main-Class信息的可运行jar,后者是原始的jar,打开mavenproject01-1.0-SNAPSHOT.jar的META-INF/MANIFEST.MF,可以看到它包含这样一行信息:
    • Main-Class: com.mai.example.mavenproject01.HelloWorld
  • 在项目根目录下执行该jar包
C:\...\maven-project01>java -jar target\mavenproject01-1.0-SNAPSHOT.jar
Hello World

7、使用Archetype生成项目骨架

  • 在Maven项目中约定:在项目的根目录中放置pom.xml,在src/main/java目录中放置项目的主代码,在sre/test/java中放置项目的测试代码。我们称这些基本的目录结构和pom.xml文件内容称为项目的骨架,并且可以使用Maven提供的Archetype快速创建出项目骨架。
//创建java工程
mvn archetype:generate -DgroupId=com.mai.example  -DartifactId=maven-java01 -Dversion=1.0-SNAPSHOT \
    -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

//创建web工程
mvn archetype:generate -DgroupId=com.mai.example  -DartifactId=maven-web01 -Dversion=1.0-SNAPSHOT \
    -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
  • mvn archetype:generate命令实际上是在使用maven-archetype-plugin插件,
    • 在Maven 2中这是不安全的,因为该命令没有指定Archetype插件的版本,于是Maven会自动去下载最新的版本进而可能得到不稳定的SNAPSHOT版本,导致运行失败。
    • 在Maven 3中这是安全的,因为即使没有指定版本,Maven也只会自动下载最新的稳定版本。

1

#                                                                                                                         #
posted @ 2023-09-18 03:07  麦恒  阅读(17)  评论(0编辑  收藏  举报