Maven实用技术点总结

时间:2022-04-08 18:18:45

1.用域Scope
Maven在引入依赖时,常见有compile,test,provided,runtime,system,import,import和其他的作用机制不同,稍后讲。
Maven有三套classpath,编译classpath,测试classpath,运行classpath,实质就是不同作用域依赖在编译,测试和运行时是否会发挥作用。
编译classpath:能否让项目顺利通过编译,不报错
测试classpath:在测试时依赖是否能被引用
运行classpath:依赖是否会被打包进项目
Scope值不同,依赖对于以上三套classpath的作用流程也不同。
使用形式:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

Maven实用技术点总结

.
2.传递性依赖
如果引入的Jar包里又引用了其他Jar,则mave会自动为当前想项目引入第三方Jar,这就是传递性依赖的实质。如果多个Jar引用了同一个Jar的不同版本,那么以哪个Jar为实际的引入?
Maven有两个依据原则:路径最近原则和声明优先原则。
路径最近原则:当A>B>C1,D>C2时,从A>C的路径比D>C的路径长,所以实际引入C2
声明优先原则:当A>C1,D>C2时,按照A和D在Pom.xml内的声明顺序来决定引入C1还是C2

Maven依赖冲突报NoDefaultMethodException,ClassNotFoundException等的原因:
很可能是传递性依赖出现问题,A>B>C1,E>C2,两个C的版本不一致,按照传递性依赖
的调解原则,E所指定的C2依赖会被采用,此时就变成A>B>C2,这时A在运行时就可能报异常。
解决方法:要么升级A的版本使其兼容新的C2;要么让E排除引入C2,使用的形式使E在引入,
使用方法如下

<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>${spring-session.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</exclusion>
</exclusions>
</dependency>

3.可从父模块继承 的Pom元素

Maven实用技术点总结

4多模块下正确设置子模块的relativePath

<parent>
<artifactId>project</artifactId>
<groupId>com.bob</groupId>
<version>1.0-SNAPSHOT</version>
<!-- 正确设置父级Pom的位置,默认值为上一层目录下 -->
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>project-root</artifactId>
<packaging>jar</packaging>

子模块需要正确设置父模块的关联路径,这样才能正确的从父Pom里继承相关的配置信息,当项目构建时,会检索信息,若未指定,默认值是../pom.xml,也就是在上一级目录下的pom.xml文件。根据这个相对地址从项目目录内寻找父Pom,如果没找到则去本地仓库寻找。

若父Pom不在上一级目录,也就是父模块不处理子模块的上一层,那么需要显式的指定< relativePath>的值。
比如父模块和子模块处于同一级目录下,则需要设置为

<relativePath>../project/pom.xml<relativePath>

这样构建项目时才能正确的引用到父Pom的相关配置。

5.使用< properties>元素统一依赖版本

在父模块中定义properties元素,内部定义了一些属性元素

 <properties>
<junit.version>4.12</junit.version>
</properties>

子模块中引用这些元素,这样能统一多个引用处的依赖版本

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

6.依赖管理: dependencyManagement
1.在Maven中dependencyManagement的作用其实相当于一个对所依赖jar包进行版本管理的管理器。

2.pom.xml文件中,jar的版本判断的两种途径
1:如果dependencies里的dependency自己没有声明version元素,那么maven就
会倒dependencyManagement里面去找有没有对该artifactId和groupId进行过版本声明,如果有,就继承它,如果没就会报错,告诉你必须为dependency声明一个version
2:如果dependencies中的dependency声明了version,那么无论dependencyManagement中有无对该jar的version声明,都以dependency里的version为准。

//只是对版本进行管理,不会实际引入jar  
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.7</version>
</dependency>
</dependencies>
</dependencyManagement>

//子模块使用时不需要再指定version,统一使用父模块的版本定义,会实际下载jar包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>

7.Import作用于的使用方式:

import scope只能在元素内使用,是作为依赖管理的一部分。

假设A项目的Pom文件如下:

<groupId>com.bob</groupId>
<artifactId>A</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>

项目B Import A,Pom配置如下:

<groupId>com.bob</groupId>
<artifactId>B</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bob</groupId>
<artifactId>A</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
</dependencies>

此时在B项目内会传递性引入javax.servlet-api这个包,同时定义的gson依赖会使用A项目内定义的版本
但是定义的spring-jdbc不会起作用,因为spring-framework-bom是定义在A内,也就是说Import元素不支持间接传递,也就是说A属于B的Import元素,但是A的Import元素不会对B发生作用

通过Import能传递性引入指定项目的< dependencies>元素,同时能得到其< dependencyManagement>元素的版本配置,
但其Import元素不会被引入,这样也降低了Import的复杂性。继承< parent>能够得到Import元素的配置

Import一般作用于< packaging>pom< packaging>的配置文件,用于实现多个引入形式,
实现多继承,继承多个Pom的< dependencies>,< dependencyManagement>

8.资源过滤
实现多套环境下配置信息的切换。

定义配置信息:

    <profiles>
<profile>
<id>dev</id>
<activation>
//默认此配置激活,此种激活方式同一时间只能激活一份配置
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.username>project</db.username>
<db.password>123456</db.password>
</properties>
</profile>
<profile>
<id>run</id>
<properties>
<db.username>demo</db.username>
<db.password>abcdef</db.password>
</properties>
</profile>
</profiles>

开启资源过滤及替换功能:

    <build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>