Maven基本使用(上)

Maven基本使用(上)

1、Maven环境

$ java -version
java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)
$ mvn -version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin
Java version: 1.8.0_77, vendor: Oracle Corporation
Java home: D:\OwnerSoftwareInstall\jdk\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos"
# 插件使用
$ mvn 插件名称:help

2、Maven Hello World

2.1 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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>hello-maven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>maven hello world</name>

</project>

2.2 主程序

package org.apache;

/**
 * @author zhangshixing
 */
public class HelloWorld {

    public String sayHello(){
        return "Hello Maven";
    }

    public static void main(String[] args) {
        System.out.println(new HelloWorld().sayHello());
    }
}

2.3 编译

$ mvn clean compile 
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] Compiling 1 source file to C:\Users\zhangshixing\Desktop\HelloMaven\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.100 s
[INFO] Finished at: 2023-10-02T07:42:02+08:00
[INFO] Final Memory: 13M/209M
[INFO] ------------------------------------------------------------------------

2.4 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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>hello-maven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>maven hello world</name>
    
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2.5 编写测试

package org.apache;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class HelloWorldTest {

    @Test
    public void testSayHello(){
        HelloWorld helloWorld = new HelloWorld();
        String result = helloWorld.sayHello();
        assertEquals("Hello Maven",result);
    }
}

2.6 编译测试

$ mvn clean test
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] Surefire report directory: C:\Users\zhangshixing\Desktop\HelloMaven\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.049 sec

Results :

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

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.701 s
[INFO] Finished at: 2023-10-02T08:00:56+08:00
[INFO] Final Memory: 15M/212M
[INFO] ------------------------------------------------------------------------

2.7 设置编译版本

<?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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>hello-maven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>maven hello world</name>
    
    <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.10.1</version>
                <configuration>
                    <source>1.8</source>
                    <source>1.8</source>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2.8 编译

$ mvn clean test
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] Surefire report directory: C:\Users\zhangshixing\Desktop\HelloMaven\target\surefire-reports

-------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.686 s
[INFO] Finished at: 2023-10-02T08:45:48+08:00                                                                                                      
[INFO] Final Memory: 15M/210M
[INFO] ------------------------------------------------------------------------

2.9 安装程序

$ mvn clean install
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] Surefire report directory: C:\Users\zhangshixing\Desktop\HelloMaven\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.048 sec

Results :

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

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO] Building jar: C:\Users\zhangshixing\Desktop\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ hello-maven ---
[INFO] Installing C:\Users\zhangshixing\Desktop\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar to D:\DecompressionSoftwareInstall\apache-maven-3.3.
9-bin\repository\org\example\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT.jar
[INFO] Installing C:\Users\zhangshixing\Desktop\HelloMaven\pom.xml to D:\DecompressionSoftwareInstall\apache-maven-3.3.9-bin\repository\org\example
\hello-maven\1.0-SNAPSHOT\hello-maven-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.797 s
[INFO] Finished at: 2023-10-02T08:48:54+08:00
[INFO] Final Memory: 17M/213M
[INFO] ------------------------------------------------------------------------

2.10 运行打包后的程序

到目前为止,还没有运行Hello World项目,不要忘了 HelloWorld类可是有一个main 方法的。默认打包生成的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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>hello-maven</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>maven hello world</name>
    
    <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.10.1</version>
                <configuration>
                    <source>1.8</source>
                    <source>1.8</source>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.apache.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

编译打包:

$ mvn clean package
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] Surefire report directory: C:\Users\zhangshixing\Desktop\HelloMaven\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.apache.HelloWorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.048 sec

Results :

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

[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-maven ---
[INFO] Building jar: C:\Users\zhangshixing\Desktop\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-shade-plugin:3.2.4:shade (default) @ hello-maven ---
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing C:\Users\zhangshixing\Desktop\HelloMaven\target\hello-maven-1.0-SNAPSHOT.jar with C:\Users\zhangshixing\Desktop\HelloMaven\target\
hello-maven-1.0-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.043 s
[INFO] Finished at: 2023-10-02T09:06:12+08:00
[INFO] Final Memory: 17M/209M
[INFO] ------------------------------------------------------------------------

查看 hello-maven-1.0-SNAPSHOT.jar 文件中 META-INF\MANIFEST.MF 文件的内容:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: zhangshixing
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_77
Main-Class: org.apache.HelloWorld

运行项目:

$ java -jar hello-maven-1.0-SNAPSHOT.jar
Hello Maven

3、使用Archetype生成项目骨架

# 交互式 
mvn archetype:generate
# 非交互式
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
......
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: basedir, Value: C:\Users\zhangshixing\Desktop\新建文件夹 (2)
[INFO] Parameter: package, Value: com.mycompany.app
[INFO] Parameter: groupId, Value: com.mycompany.app
[INFO] Parameter: artifactId, Value: myapp
[INFO] Parameter: packageName, Value: com.mycompany.app
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] project created from Old (1.x) Archetype in dir: C:\Users\zhangshixing\Desktop\新建文件夹 (2)\myapp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.394 s
[INFO] Finished at: 2023-10-02T09:22:59+08:00
[INFO] Final Memory: 18M/219M
[INFO] ------------------------------------------------------------------------
# 生成的目录结构
myapp/
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── mycompany
    │               └── app
    │                   └── App.java
    └── test
        └── java
            └── com
                └── mycompany
                    └── app
                        └── AppTest.java
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>myapp</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>myapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>
package com.mycompany.app;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}
package com.mycompany.app;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Unit test for simple App.
 */
public class AppTest 
    extends TestCase
{
    /**
     * Create the test case
     *
     * @param testName name of the test case
     */
    public AppTest( String testName )
    {
        super( testName );
    }

    /**
     * @return the suite of tests being tested
     */
    public static Test suite()
    {
        return new TestSuite( AppTest.class );
    }

    /**
     * Rigourous Test :-)
     */
    public void testApp()
    {
        assertTrue( true );
    }
}

4、坐标和依赖

4.1 坐标详解

Maven 坐标为各种构件引入了秩序,任何一个构件都必须明确定义自己的坐标,而一组 Maven 坐标是通过一些

元素定义的,它们是 groupld、artifactld、version、packaging、classifier。

<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</ersion>
<packaging>jar</packaging>

这是 nexus-indexer 的坐标定义,nexus-indexer 是一个对 Maven 仓库编纂索引并提供搜索功能的类库,它是

Nexus 项目的一个子模块。后面会详细介绍 Nexus。

上述代码片段中,其坐标分别为 groupId:org.sonatype.nexus、artifactId:nexus-indexer、version:2.0.0、

packaging:jar,没有 classifier。

下面详细解释一下各个坐标元素:

  • groupId:定义当前Maven项目隶属的实际项目。

  • artifactId:该元素定义实际项目中的一个Maven 项目(模块),推荐的做法是使用实际项目名称作为

    artifactId 的前缀。

  • version:该元素定义 Maven 项目当前所处的版本。

  • packaging:该元素定义 Maven 项目的打包方式,默认是jar打包方式。

  • classifier:该元素用来帮助定义构建输出的一些附属构件。

上述5个元素中,groupld,artifactld,version 是必须定义的,packaging 是可选的(默认为jar),而classifier是不

能直接定义的。同时,项目构件的文件名是与坐标相对应的,一般的规则为:

artifactld-version [-classifier].packaging[-classifier]表示可选。

这里还要强调的一点是,packaging并非一定与构件扩展名对应,比如 packaging 为 maven-plugin 的构件扩展名

为jar。

4.2 dependency元素介绍

<dependency>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <type></type>
    <optional></optional>
    <scope></scope>
    <classifier></classifier>
    <systemPath></systemPath>
    <exclusions></exclusions>
</dependency>

groupld、artifactld、version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven 根

据坐标才能找到需要的依赖。type 的默认值是 jar,classifier 的默认值是 null。

4.2.1 type依赖类型

依赖的类型,对应于项目坐标定义的 packaging。大部分情况下,该元素不必声明,其默认值为 jar。type 的值一

般有 jar、war、pom 等,声明引入的依赖的类型。

4.2.2 optional可选依赖

假设有这样一个依赖关系,项目A 依赖于项目B,项目B 依赖于项目X 和Y,B 对于X 和Y 的依赖都是可选依赖:

A->B、B->X(可选)、B->Y(可选)。根据传递性依赖的定义,如果所有这三个依赖的范围都是 compile,那么 X、Y

就是A 的 compile 范围传递性依赖。然而,由于这里X、Y 是可选依赖,依赖将不会得以传递。换句话说, X、Y

将不会对A有任何影响。

假如 B 是一个持久层隔离工具包,它支持多种数据库,包括 MySQL、PostgreSQL 等,在构建这个工具包的时

候,需要这两种数据库的驱动程序,但在使用这个工具包的时候,只会依赖一种数据库。

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.xiaoshan.mvnbook</groupId> 
	<artifactId>project-b</artifactId>
	<version>1.0.0</version>
	<dependencies>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId> 
			<version>5.1.10</version>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>8.4-701.jdbc3</version>
			<optional>true</optional>
		</dependency>
	</dependencies>
</project>

上述 XML代码片段中,使用<optional>元素表示 mysql-connector-javapostgresql 这两个依赖为可选

依赖,它们只会对当前项目B产生影响,当其他项目依赖于B的时候,这两个依赖不会被传递。因此,当项目A依赖

于项目B的时候,如果其实际使用基于MySQL数据库,那么在项目A中就需要显式地声明 mysgl-connector-java

这一依赖。

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.xiaoshan.mvnbook</groupId>
	<artifactId>project-a</artifactId>
	<version>1.0.0</version>
	<dependencies>
		<dependency>
			<groupId>com.xiaoshan.mvnbook</groupId>
			<artifactId>project-b</artifactId>
			<version>1.0.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.10</version>
		</dependency>
	</dependencies>
</project>
4.2.3 scope依赖范围

Maven 有以下几种依赖范围:

  • compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的 Maven 依赖,对于

    编译、测试、运行三种 classpath 都有效。典型的例子是 spring-core,在编译、测试和运行的时候都需要使

    用该依赖。

  • test:测试依赖范围。使用此依赖范围的 Maven 依赖,只对于测试classpath 有效,在编译主代码或者运行

    项目的使用时将无法使用此类依赖。典型的例子是 JUnit,它只有在编译测试代码及运行测试的时候才需要。

  • provided:已提供依赖范围。使用此依赖范围的 Maven 依赖,对于编译和测试 class-path 有效,但在运行

    时无效。典型的例子是 servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经

    提供,就不需要 Maven 重复地引入一遍。

  • runtime:运行时依赖范围。使用此依赖范围的 Maven依赖,对于测试和运行 class-path 有效,但在编译主

    代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试

    或者运行项目的时候才需要实现上述接口的具体JDBC驱动。

  • system:系统依赖范围。该依赖与三种 classpath 的关系,和provided 依赖范围完全一致。但是,使用

    system 范围的依赖时必须通过 systemPath 元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven

    仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。systemPath 元素可

    以引用环境变量。

  • import(Maven 2.0.9及以上):导入依赖范围。该依赖范围不会对三种 classpath 产生实际的影响。

上述除 import 以外的各种依赖范围与三种 classpath 的关系如下表所示。

依赖范围(Scope)对于编译classpath有效对于测试classpath有效对于运行时classpath有效例子
compile✔️✔️✔️spring-core
test-✔️-Junit
provided✔️✔️-servlet-api
runtime-✔️✔️JDBC驱动
system✔️✔️-本地的 maven仓库之外的类库文件
4.2.4 exclusions依赖排除

依赖排除,就是有时候引入某一个依赖的时候,该依赖下有 jar 包冲突,可以排除掉,不引用该 jar。

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.xiaoshan.mvnbook</groupId>
	<artifactId>project-a</artifactId>
	<version>1.0.0</version>
	<dependencies>
		<dependency>
			<groupId>com.xiaoshan.mvnbook</groupId>
			<artifactId>project-b</artifactId>
			<version>1.0.0</version>
			<exclusions>
				<exclusion>
					<groupId>com.xiaoshan.mvnbook</groupId>
					<artifactId>project-c</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>com.xiaoshan.mvnbook</groupId>
			<artifactId>project-c</artifactId>
			<version>1.1.0</version>
		</dependency>
	</dependencies>
</project>           
4.2.5 systemPath

当 maven 依赖本地而非 repository 中的 jar 包,sytemPath 指明本地 jar 包路径。

<dependency>
    <groupId>javax.sql</groupId>
    <artifactId>jdbc-stdext</artifactId>
    <version>2.0</version>
    <scope>system</scope>
    <systemPath>${java.home)/lib/rt.jar</systemPath>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.5</version>
    <scope>system</scope>
    <systemPath>${basedir}/WebContent/WEB-INF/lib/hamcrest-core-1.3.jar</systemPath>
</dependency>
4.2.6 classifier

Classifier 可能是最容易被忽略的 Maven 特性,但它确实非常重要,我们也需要它来帮助规划坐标。设想这样一

个情况,有一个jar项目,就说是 dog-cli-1.0.jar 吧,运行它用户就能在命令行上画一只小狗出来。现在用户的要

求是希望你能提供一个zip包,里面不仅包含这个可运行的jar,还得包含源代码和文档,换句话说,这是比较正式

的分发包。这个文件名应该是怎样的呢? dog-cli-1.0.zip? 不够清楚,仅仅从扩展名很难分辨什么是 Maven 默认生

成的构件,什么是额外配置生成分发包。如果能是dog-cli-1.0-dist.zip就最好了。这里的dist就是classifier,默认

Maven只生成一个构件,我们称之为主构件,那当我们希望Maven生成其他附属构件的时候,就能用上

classifier。常见的classifier还有如dog-cli-1.0-sources.jar表示源码包,dog-cli-1.0-javadoc.jar表示JavaDoc包等

等。

classifier 它表示在相同版本下针对不同的环境或者jdk使用的jar,如果配置了这个元素,则会将这个元素名在加在

最后来查找相应的jar。

<!-- 上面的例子 -->
<classifier>sources</classifier>
<classifier>javadoc</classifier>
<!-- 给相同的version,构建不同的环境使用依赖 -->
<classifier>jdk17</classifier>
<classifier>jdk18</classifier>

4.3 依赖传递

scope元素的值会对这种传递依赖会有影响。

假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对于C是第二直接依赖,而A对于C是传递性依赖,

而第一直接依赖的scope和第二直接依赖的scope决定了传递依赖的范围,即决定了A对于C的scope的值。

下面我们用表格来列一下这种依赖的效果,表格最左边一列表示第一直接依赖(即A->B的scope的值),而表格中的

第一行表示第二直接依赖(即B->C的scope的值),行列交叉的值显示的是A对于C最后产生的依赖效果。

compiletestprovidedruntime
compilecompile--runtime
testtest--test
providedprovided-providedprovided
runtimeruntime--runtime

解释一下:

比如A->B的scope是compile,而B->C的scope是test,那么按照上面表格中,对应第2行第3列的值-,那么A对于C

是没有依赖的,A对C的依赖没有从B->C传递过来,所以A中是无法使用C的

比如A->B的scope是compile,而B->C的scope是runtime,那么按照上面表格中,对应第2行第5列的值为

runtime,那么A对于C是的依赖范围是runtime,表示A只有在运行的时候C才会被添加到A的classpath中,即对A

进行运行打包的时候,C会被打包到A的包中

大家仔细看一下,上面的表格是有规律的,当B->C依赖是compile的时候(表中第2列),那么A->C的依赖范围和

A->B的sope是一样的;当B->C的依赖是test时(表中第3列),那么B->C的依赖无法传递给A;当B->C的依赖是

provided(表第4列),只传递A->C的scope为provided的情况,其他情况B->C的依赖无法传递给A;当B->C的依

赖是runtime(表第5列),那么C按照B->C的scope传递给A。

4.4 优化依赖

在软件开发过程中,程序员会通过重构等方式不断地优化自己的代码,使其变得更简洁、更灵活。同理,程序员

也应该能够对Maven 项目的依赖了然于胸,并对其进行优化, 如去除多余的依赖,显式地声明某些必要的依赖。

本文前面的内容已经介绍到: Maven 会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个

依赖的范围,对于一些依赖冲突,也能进行调节,以确保任何一个构件只有唯一的版本在依赖中存在。在这些工作

之后,最后得到的那些依赖被称为已解析依赖(Resolved Dependency)。 可以运行如下的命令查看当前项目的已

解析依赖:

$ mvn dependency:list

在项目中执行该命令,结果如下所示:

$ mvn dependency:list
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ hello-maven ---
[INFO]
[INFO] The following files have been resolved:
[INFO]    junit:junit:jar:4.13.2:test
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:test
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.730 s
[INFO] Finished at: 2023-10-03T10:39:23+08:00
[INFO] Final Memory: 13M/245M
[INFO] ------------------------------------------------------------------------

上面显示了所有的已解析依赖,同时,每个依赖的范围也得以明确标示。 在此基础上,还能进一步了解已解析依

赖的信息。将直接在当前项目POM 声明的依赖定义为顶层依赖,而这些顶层依赖的依赖则定义为第二层依赖,以

此类推,有第三、第四层依赖。当这些依赖经 Maven 解析后,就会构成一个依赖树,通过这棵依赖树就能很清楚

地看到某个依赖是通过哪条传递路径引入的。可以运行如下命令查看当前项目的依赖树:

$ mvn dependency:tree

在项目中执行该命令,效果如下所示:

$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ hello-maven ---
[INFO] org.example:hello-maven:jar:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:4.13.2:test
[INFO]    \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.748 s
[INFO] Finished at: 2023-10-03T10:40:36+08:00
[INFO] Final Memory: 13M/245M
[INFO] ------------------------------------------------------------------------

使用 dependency:listdependeney:tree 可以帮助我们详细了解项目中所有依赖的具体 信息,在此基础

上,还有 dependency:analyze 工具可以帮助分析当前项目的依赖。

现在再运行如下命令:

$ mvn dependency:analyze

结果如下所示:

$ mvn dependency:analyze
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building maven hello world 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
......
[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ hello-maven ---
[INFO] No dependency problems found
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.470 s
[INFO] Finished at: 2023-10-03T10:41:57+08:00
[INFO] Final Memory: 18M/214M
[INFO] ------------------------------------------------------------------------

该结果中重要的是两个部分。首先是Used undeclared dependencies, 意指项目中使用到的,但是没有显式声

明的依赖。 这种依赖意味着潜在的风险,当前项目直接在使用它们,例如有很多相关的Java import 声明,而这种

依赖是通过直接依赖传递进来的,当升级直接依赖的时候,相关传递性依赖的版本也可能发生变化,这种变化不易

察觉,但是有可能导致当前项目出错。例如由于接口的改变,当前项目中的相关代码无法编译。这种隐藏的、潜在

的威胁一旦出现,就往往需要耗费大量的时间来查明真相。因此, 显式声明任何项目中直接用到的依赖。

结果中还有一个重要的部分是 Unused declared dependencies, 意指项目中未使用的,但 显式声明的依赖,需

要注意的是, 对于这样一类依赖, 我们不应该简单地直接删除其声明,而是应该仔细分析。由于

dependeney:analyze 只会分析编译主代码和测试代码需要用到的依赖, 一些执行测试和运行时需要的依赖它就发

现不了。 当然,有时候确实能通过该信息找到一些没用的依赖,但一定要小心测试。

5、仓库搜索服务

使用 Maven 进行日常开发的时候,一个常见的问题就是如何寻找需要的依赖,我们可能只知道需要使用类库的项

目名称,但添加 Maven 依赖要求提供确切的 Maven 坐标。这时,就可以使用仓库搜索服务来根据关键字得到

Maven 坐标。本节介绍几个常用的、功能强大的公共 Maven 仓库搜索服务。

5.1 Sonatype Nexus

地址 :http://repository.sonatype.org/

Nexus 是当前最流行的开源 Maven 仓库管理软件,这里要介绍的是 Sonatype 架设的一个公共 Nexus 仓库实

例。

Nexus 提供了关键字搜索、类名搜索、坐标搜索、校验和搜索等功能。搜索后,页面清晰地列出了结果构件的坐

标及所属仓库。用户可以直接下载相应构件,还可以直接复制已经根据坐标自动生成的XML 依赖声明。

5.2 MVNrepository

地址:http://mvnrepository.com/

MVNrepository 的界面比较清新,它提供了基于关键字的搜索、依赖声明代码片段、构件下载、依赖与被依赖关

系信息、构件所含包信息等功能。 MVNrepository 还能提供一个简单的图表,显示某个构件各版本间的大小变

化。

5.3 其它

https://repo1.maven.org/maven2/
http://maven.aliyun.com/nexus/content/groups/public/
http://repository.jboss.org/nexus/content/groups/public
https://search.maven.org/
https://repo.maven.apache.org/maven2
  • 22
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值