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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
//用来排除传递依赖性
<exclusion>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>所引依赖的包版本</version>
<type>依赖的类型,对应于项目中的packing,默认是jar类型的依赖</type>
<optional>true</optional>//标记为是否为可选依赖
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>system</scope>//表示依赖的范围
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</project>
2. 依赖范围(scope)的几个种类
- compile(编译范围):compile是默认的范围;如果没有提供一个范围,那该依赖的范围就是编译范围。编译范围依赖在所有的classpath 中可用,同时它们也会被打包。对于编译,测试,运行三个状态都有效。
- provided(JDK或者容器已经提供的范围):provided 依赖只有在当JDK 或者一个容器已提供该依赖之后才使用。例如,如果你开发了一个web 应用,你可能在编译 classpath 中需要可用的Servlet API 来编译一个servlet,但是你不会想要在打包好的WAR 中包含这个Servlet API;这个Servlet API JAR 由你的应用服务器或者servlet 容器提供。已提供范围的依赖在编译classpath (不是运行时)可用。它们不是传递性的,也不会被打包。对于编译和测试时有效,但运行时无效。
- test(测试范围): test范围依赖在一般的编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。
- runtime(运行时有效):runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。对测试和运行时有效,编译时无效。
- system(系统依赖): system范围依赖与provided 类似,但是你必须显式的提供一个对于本地系统中JAR 文件的路径。这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven 也不会在仓库中去寻找它。如果你将一个依赖范围设置成系统范围,你必须同时提供一个 systemPath 元素。注意该范围是不推荐使用的(你应该一直尽量去从公共或定制的 Maven 仓库中引用依赖)。而且system必须显示的指定依赖文件,通过
<systemPath>
来进行指定,是与本机绑定的,所以基本很少用到。 - import仅支持在
<dependencyManagement>
中的类型依赖项上。它表示要在指定的POM<dependencyManagement>
部分中用有效的依赖关系列表替换依赖关系。该scope类型的依赖项实际上不会参与限制依赖项的可传递性。
3. Scope依赖的传递性
A ——> B ——> C:表示项目A依赖于项目B的同时项目B依赖于项目C,此时的项目A与项目C的关系如下:
第一列A与B的依赖,第一行B与C的依赖 | compile | provided | runtime | test |
---|---|---|---|---|
compile | compile | runtime | ||
provided | provided | provided | provided | |
runtime | runtime | runtime | ||
test | test | test |
结论:
- 当B对C的依赖的scope是test或者provided,则A不依赖C。
- 当B对C的依赖是scope是runtime或者compile,则A依赖C。
- 传递依赖的scope的规则:如果A对B的依赖是compile,那么A对C的依赖和B对C的依赖相同,否则和A对B的依赖保持一致。
4.Scope中import的使用
该类型只在dependencyManagement内使用生效,它可以用来管理模块依赖,也就是针对包含了一系列子依赖的模块导入到当前项目中进行管理使用,而不是把需要用到的依赖一个一个的加入到项目中进行管理,可以理解为多继承模式。
比如在一些场景中:我们只是想单纯加入springboot模块的依赖,而不想将springboot作为父模块引入项目中,此时就可以使用import来处理。
一般我们将Springboot作为父模块引入到项目中:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
一个项目中一般只能有一个父依赖模块,可实际开发中会定义自己的父模块,这样就会出现冲突,这种情况下我们可以使用import来将springboot作为依赖模块导入自己的项目中。
<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.demo</groupId>
<artifactId>MyService</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<description>demo springboot</description>
<inceptionYear>2019</inceptionYear>
<organization>
<name>calm_encode</name>
<url>http://baidu.com</url>
</organization>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<modules>
<module>service</module>
<module>common</module>
<module>util</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 注入组件定义的第三方依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.9.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
......
</dependencies>
</dependencyManagement>
<!-- 远程仓库配置 -->
<distributionManagement>
<repository>
<id>releases</id>
<url>http://ali/nexus/content/repositories/releases</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<url>http://ali/nexus/content/repositories/snapshots/nexus/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--使用-Dloader.path需要在打包的时候增加<layout>ZIP</layout>,不指定的话-Dloader.path不生效-->
<layout>ZIP</layout>
<!-- 指定该jar包启动时的主类[建议] -->
<mainClass>com.common.util.CommonUtilsApplication</mainClass>
<!--<includes>-->
<!--<!–依赖jar不打进项目jar包中–>-->
<!--<include>-->
<!--<groupId>nothing</groupId>-->
<!--<artifactId>nothing</artifactId>-->
<!--</include>-->
<!--</includes>-->
<!--配置的 classifier 表示可执行 jar 的名字,配置了这个之后,在插件执行 repackage 命令时,
就不会给 mvn package 所打成的 jar 重命名了,这样就可以被其他项目引用了,classifier命名的为可执行jar-->
<!--<classifier>myexec</classifier>-->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- 剔除spring-boot打包的org和BOOT-INF文件夹(用于子模块打包) -->
<!--<skip>true</skip>-->
<source>1.8</source>
<target>1.8</target>
<!--<encoding>UTF-8</encoding>-->
</configuration>
</plugin>
<!--拷贝依赖到jar外面的lib目录-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${plugin.assembly.version}</version>
<configuration>
<finalName>myservice</finalName>
<descriptor>deploy/assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
上述就可以将springboot模块作为依赖导入到项目中,然后就可以继承自己的父模块了,如果要加入其它类似springboot这样的模块的话就和加入springboot一样,这样就可以使模块管理看起来更简洁了,也实现了多继承的效果。
5. 补充在maven中经常会使用的<optional>true</optional>参数
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
参数解释:<optional>true</optional>的作用是让依赖只被当前项目使用,而不会在模块间进行传递依赖。