Maven中引用Jar的作用范围

导出依赖的范围

https://maven.apache.org/plugins/maven-dependency-plugin/copy-dependencies-mojo.html

mvn dependency:copy-dependencies 这个命令默认会复制 compile 和 runtime scope 的依赖Jar包。

具体来说,默认情况下该命令会复制以下范围的依赖:

  • compile:编译依赖,参与项目的编译,并打包。
  • runtime:运行时依赖,参与项目运行,但不打包。
  • system:系统依赖,通过systemPath指定。

不会复制以下范围的依赖:

  • test:测试依赖,只参与测试相关的代码。
  • provided:已提供依赖,Expected to be provided by JDK or container。

通过-scope参数,可以控制复制指定范围的依赖,

例如只复制compile范围:

导出指定范围

1
mvn dependency:copy-dependencies -DincludeScope=compile

排除指定范围

1
mvn dependency:copy-dependencies -DexcludeScope=provided

不能同时使用-DincludeScope-DexcludeScope

以下写法是不生效的:

1
mvn dependency:copy-dependencies -DincludeScope=compile -DexcludeScope=provided

默认会将jar包放在项目中的target下的dependency目录下面

includeScope

  • runtime 包含 runtime and compile dependencies,
  • compile 包含 compile, provided, and system dependencies,
  • test 包含 all dependencies (相当于default),
  • provided 包含 provided dependencies,
  • system 包含 system dependencies.

excludeScope

  • runtime 不包含 runtime and compile dependencies,
  • compile 不包含 compile, provided, and system dependencies,
  • test 不包含 所有 dependencies, 那么这并不是一个合理的选择:它将失败,您可能想要配置 includeScope = compile
  • provided 不包含 provided dependencies,
  • system 不包含 system dependencies.

打包范围

清理并打包

1
mvn clean package

依次执行:cleanresourcescompiletestResourcestestCompiletestjar(打包)

打包说明

https://www.psvmc.cn/article/2015-04-22-maven-jar-project.html

默认打包的范围是runtime

会包含 runtimecompile 的依赖。

不包含providedsystem

引用Jar范围 scope

compile

不声明scope元素的情况下的默认值

compile表示被依赖包需要参与当前项目的编译,包括后续的测试,运行周期也参与其中,是一个比较强的依赖;

打包的时候通常需要包含进去。

provided

provided 类型的scope只会在项目的编译测试阶段起作用;可以认为在目标容器中已经提供了这个依赖,无需在提供,但是在编写代码或者编译时可能会用到这个依赖;

依赖不会被打入到项目jar包中

说到provided,这里就要说到<dependency>下的子标签<optional> ,如果一个依赖的<optional> 设置为true,则该依赖在打包的时候不会被打进jar包,同时不会通过依赖传递传递到依赖该项目的工程;例如:x依赖B,B由依赖于A(x->B->A),则A中设置<optional>true的依赖不会被传递到x中。

这两者的区别在于:

  • <optional>true 表示某个依赖可选,该依赖是否使用都不会影响服务运行;
  • provided<scope>在目标容器中已经提供了这个依赖,无需在提供

runtime

runtimecompile比较相似,区别在于runtime 跳过了编译阶段,打包的时候通常需要包含进去。

test

  • 一般的编译和运行时都不需要
  • 只有在测试编译和测试运行阶段可用
  • 不会被打包到项目jar包中
  • 同时如果项目A依赖于项目B,项目B中的test作用域下的依赖不会被继承。

system

表示使用本地系统路径下的jar包,需要和一个systemPath一起使用,如下:

1
2
3
4
5
6
7
8
<!--引用-->
<dependency>
<groupId>xxxx</groupId>
<artifactId>xxx</artifactId>
<systemPath>${basedir}/lib/xxxxx.jar</systemPath>
<scope>system</scope>
<version>1.4.12</version>
</dependency>

import

import只能在pom文件的<dependencyManagement>

中使用,从而引入其他的pom文件中引入依赖,如:在Spring boot 项目的POM文件中,我们可以通过在POM文件中继承 Spring-boot-starter-parent来引用Srping boot默认依赖的jar包,如下:

1
2
3
4
5
6
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.BUILD-SNAPSHOT</version>
</parent>

但是,通过上面的parent继承的方法,只能继承一个 spring-boot-start-parent。实际开发中,用户很可能需要继承自己公司的标准parent配置,这个时候可以使用 scope=import 来实现多继承。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.1.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

通过上面方式,就可以获取spring-boot-dependencies.2.0.1.BUILD-SNAPSHOT.pom文件中dependencyManagement配置的jar包依赖。如果要继承多个,可以在dependencyManagement中添加,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.1.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

项目实战问题

导出的Jar和打包的Jar不一致

为了加载一些Maven中没有的Jar,所以Jar放在项目下,并且设置范围为system,并在打包的时候设置范围中添加system

这样打包可以了,但是导出依赖的时候,不能和打包的相同。

  • runtime 包含 runtime and compile dependencies。
  • compile 包含 compile, provided, and system dependencies。

我们想要导出的是runtimecompile 以及system的依赖,但是没有办法。

打包方法可参见:

https://www.psvmc.cn/article/2015-04-22-maven-jar-project.html

这时POM中的配置

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
<!--连接Oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/libs/ojdbc6.jar</systemPath>
</dependency>
<!--连接SQL Server-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/libs/sqljdbc4-4.0.jar</systemPath>
</dependency>
<!--操作Mysql-->
<dependency>
<groupId>cn.psvmc</groupId>
<artifactId>mysql8</artifactId>
<version>1.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/libs/mysql8-1.1.jar</systemPath>
</dependency>

<dependency>
<groupId>com.yxkj</groupId>
<artifactId>yxdp-algorithm</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/libs/yxdp-algorithm-1.0.0.jar</systemPath>
</dependency>

为了保证打包和导出的依赖完全一致,所以只能把这些Jar都安装到Maven中了。

1
2
3
4
5
6
7
mvn install:install-file -Dfile="D:\Jars\Bigdata\ojdbc6.jar" -DgroupId="com.oracle" -DartifactId="ojdbc6" -Dversion="11.2.0.3" -Dpackaging=jar

mvn install:install-file -Dfile="D:\Jars\Bigdata\sqljdbc4-4.0.jar" -DgroupId="com.microsoft.sqlserver" -DartifactId="sqljdbc4" -Dversion="4.0" -Dpackaging=jar

mvn install:install-file -Dfile="D:\Jars\Bigdata\mysql8-1.1.jar" -DgroupId="cn.psvmc" -DartifactId="mysql8" -Dversion="1.1" -Dpackaging=jar

mvn install:install-file -Dfile="D:\Jars\Bigdata\yxdp-algorithm-1.0.0.jar" -DgroupId="com.yxkj" -DartifactId="yxdp-algorithm" -Dversion="1.0.0" -Dpackaging=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
<!--连接Oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!--连接SQL Server-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.0</version>
</dependency>
<!--操作Mysql-->
<dependency>
<groupId>cn.psvmc</groupId>
<artifactId>mysql8</artifactId>
<version>1.1</version>
</dependency>

<dependency>
<groupId>com.yxkj</groupId>
<artifactId>yxdp-algorithm</artifactId>
<version>1.0.0</version>
</dependency>

项目下的Jar也可以删除了。

打包配置中的system范围也可以删除了。

即:assembly.xml中的下面的配置可以删了。

1
2
3
4
5
6
7
<!-- 增加scope类型为system的配置 -->
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>system</scope>
</dependencySet>

导出使用

1
2
mvn clean
mvn dependency:copy-dependencies -DincludeScope=runtime

这样导出的Jar就和打包中的Jar完全一致了。