文章目录
①. Maven的依赖范围
- ①. maven的依赖范围包括:compile、provide、runtime、test、system
- compile:编译范围的依赖会用在编译,测试,运行,由于运行时需要,所以编译范围的依赖会被打包(会被打包)
- test:test范围依赖在编译和运行时都不需要,只在测试编译和测试运行时需要。例如:Junit。由于运行时不需要,所以test范围依赖不会被打包(不会打包)
- provide:provide依赖只有当jdk或者一个容器已提供该依赖之后才使用。provide依赖在编译和测试时需要,在运行时不需要。例如:servletapi被Tomcat容器提供了(不会打包)
- runtime:runtime依赖在运行和测试系统时需要,但在编译时不需要。例如:jdbc的驱动包。由于运行时需要,所以runtime范围的依赖会被打包(会打包)
- system:system范围依赖与provide类似,但是必须显示的提供一个对于本地系统中jar文件的路径。一般不推荐使用
- ②. 图解
- ③. 代码中展示:
<!--导入mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--runtime表示编译器不使用它,运行期使用它-->
<scope>runtime</scope>
<version>8.0.17</version>
</dependency>
<!--导入servlet相关依赖,request不报错-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<!--provided的意思是编译时使用它,运行时不使用-->
<scope>provided</scope>
</dependency>
<--jsp-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--system 编译测试有用、不会运行打成jar-->
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<scope>system</scope>
<optional>true</optional>
<version>${java.version}</version>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
- 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
②. Maven的常用设置
①. 全局变量
- ①. 在Maven的pom.xml文件中,properties用于定义全局变量,POM中通过${property_name}的形式引用变量的值。定义全局变量:
<properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
- 1
- 2
- 3
- ②. 引用全局变量:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
②. Maven系统采用的变量
<properties>
<!--源码编译jdk版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<!--运行代码的jdk版本-->
<maven.compiler.target>1.8</maven.compiler.target>
<!--项目构建使用的编码,避免中文乱码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--生成报告的编码-->
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
③. 指定资源位置
-
①. src/main/java和src/test/java这两个目录中的所有*.java文件会分别在comile和test-comiple阶段被编译,编译结果分别放到了target/classes和targe/test-classes目录中,但是这两个目录中的其他文件都会被忽略掉,如果需要把src目录下的文件包放到target/classes目录,作为输出的jar一部分。需要指定资源文件位置。以下内容放到buid标签中
-
②. IDEA中图解(默认情况下)
在classes中没有A.txt文件出现
- ③. 需求一:想要A.txt出现在classes中
在pom.xml添加如下内容,然后重新打包即可
<build>
<resources>
<resource>
<!--所在的目录-->
<directory>src/main/java</directory>
<includes>
<!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.txt</include>
</includes>
<!--filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
</build>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- ④. 需求二:
在xml中配置如下配置:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.MF</include>
<include>**/*.XML</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<!--资源文件的路径,默认位于${basedir}/src/main/resources/目录下-->
<directory>src/main/resources</directory>
<!--一组文件名的匹配模式,被匹配的资源文件将被构建过程处理-->
<includes>
<include>**/*</include>
<include>*</include>
</includes>
<!--filtering默认false,true表示通过参数对资源文件中的${key}
在编译时进行动态变更。替换源可紧-Dkey和pom中的<properties>值
或<filters>中指定的properties文件-->
<filtering>true</filtering>
</resource>
</resources>
</build>
- 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
④. Maven默认属性
${basedir} 项目根目录
${version}表示项目版本;
${project.basedir}同${basedir};
${project.version}表示项目版本,与${version}相同;
${project.build.directory} 构建目录,缺省为target
${project.build.sourceEncoding}表示主源码的编码格式;
${project.build.sourceDirectory}表示主源码路径;
${project.build.finalName}表示输出文件名称;
${project.build.outputDirectory} 构建过程输出目录,缺省为target/classes
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
输出结果为:
test=${pro.name}
# F:\\mavenTest\\A 项目根目录
basedir=${basedir}
basedir2=${project.basedir}
# version=1.0-SNAPSHOT
version=${version}
# project.build.directory=F:\\mavenTest\\A\\target 构建目录,缺省为target
project.build.directory=${project.build.directory}
# project.build.sourceDirectory=F:\\mavenTest\\A\\src\\main\\java
# 表示主源码的编码格式
project.build.sourceDirectory=${project.build.sourceDirectory}
# project.build.finalName=A-1.0-SNAPSHOT 表示输出文件名称
project.build.finalName=${project.build.finalName}
# project.build.outputDirectory=F:\\mavenTest\\A\\target\\classes
# 构建过程输出目录,缺省为target/classes
project.build.outputDirectory=${project.build.outputDirectory}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
③. Maven项目依赖、依赖冲突
①. 什么是依赖传递
- ①.在maven中,依赖是可以传递的,假设存在三个项目,分别是项目A,项目B以及项目C。假设C依赖B,B依赖A,那么我们可以根据maven项目依赖的特征不难推出项目C也依赖A
- ②.通过上面的图可以看到,我们的web项目直接依赖了spring-webmvc,而spring-webmvc依赖了sping-aop、spring-beans等。最终的结果就是在我们的web项目中间接依赖了spring-aop、spring-beans等
②. 什么是依赖冲突
- ①. 加入如下坐标
由于spring-webmvc中依赖了spring-core,而spring-core中依赖了commons-logging(1.1.3),而我们又引入了commons-loging1.2,就造成了冲突
- ②. 根据路径近者优先原则,我们项目中引入的commons-logging为1.2
④. 如何解决依赖冲突
①. 使用maven提供的依赖调解原则
-
①. 依赖调节原则 —
第一声明者优先原则
(在 pom 文件中定义依赖,以先声明的依赖为准。其实就是根据坐标导入的顺序来确定最终使用哪个传递过来的依赖)
结论:通过上图可以看到,spring-aop和spring-webmvc都传递过来了spring-beans,但是因为spring-aop在前面,所以最终使用的spring-beans是由spring-aop传递过来的,而spring-webmvc传递过来的spring-beans则被忽略了
-
②.
根据路径近者优先原则,
我们项目中引入的commons-logging为1.2
-
③. 如果在同一个pom中引入了两个相同的jar包,以引入的最后一个为准
如下的配置引入的是1.2
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
②. 可选依赖optional
- ①. 新建项目A(类似于mysql)、B(类似于oracle),项目C(类似于业务层,引入A、B工程),项目D(类似于逻辑工程,引入了C)
C项目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"> <parent> <artifactId>mavenTest</artifactId> <groupId>com.xiaozhi</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>C<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependencies</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.xiaozhi<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>A<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.0-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token comment"><!-- optional=true,依赖不会传递,该项目依赖A 之后依赖该项目的项目如果想要使用A,需要重新引入 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>optional</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>optional</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>groupId</span><span class="token punctuation">></span></span>com.xiaozhi<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>groupId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>artifactId</span><span class="token punctuation">></span></span>B<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>artifactId</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>version</span><span class="token punctuation">></span></span>1.0-SNAPSHOT<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>version</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>optional</span><span class="token punctuation">></span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>optional</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependency</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>dependencies</span><span class="token punctuation">></span></span>
</project>
- 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
- ②. 画个图说明问题:
- 由于projectC使用到了两个来自projectA的类(OptionalFeatureAClass)和projectB的类(OptionalFeatureBClass).如果projectC没有依赖packageA和packageB,那么编译将会失败。
- projectD依赖projectC,但是对于projectD来说,类(OptionalFeatureAClass)和类(OptionalFeatureBClass)是可选的特性,所以为了让最终的war/ejbpackage不包含不必要的依赖,使用optional声明当前依赖是可选的,默认情况下也不会被其他项目继承(好比Java中的final类,不能被其他类继承一样)
- ③. 如果projectD确实需要用到projectC中的OptionalFeatureAClass怎么办呢?
那我们就需要在projectD的pom.xml中显式的添加声明projectA依赖,继续看下图ProjectD需要用到ProjectA的OptionalFeatureAClass,那么需要在ProjectD的pom.xml文件中显式的添加对ProjectA的依赖
- ④. 到这也就很好理解为什么Maven为什么要设计optional关键字了,假设一个关于数据库持久化的项目(ProjectC),为了适配更多类型的数据库持久化设计,比如Mysql持久化设计(ProjectA)和Oracle持久化设计(ProjectB),当我们的项目(ProjectD)要用的ProjectC的持久化设计,不可能既引入mysql驱动又引入oracle驱动吧,所以我们要显式的指定一个,就是这个道理了
③. 排除依赖
- 可以使用exclusions标签将传递过来的依赖排除出去
④. 版本锁定[ 掌握 ]
-
①. 采用直接锁定版本的方法确定依赖jar包的版本,版本锁定后则不考虑依赖的声明顺序或依赖的
路径,以锁定的版本为准添加到工程中,此方法在企业开发中经常使用 -
②. 版本锁定的使用方式:
- 在dependencyManagement标签中锁定依赖的版本
- 在dependencies标签中声明需要导入的maven坐标
④. 分模块构建maven工程
①. 分模块构建maven工程分析
- ①. 不管是下面那种拆分方式,通常都会提供一个父工程,将一些公共的代码和配置提取到父工程中进行统一管理和配置
- 按照业务模块进行拆分,每个模块拆分成一个maven工程,例如将一个项目分为用户模块、订单模块、购物车模块等,每个模块都对应一个maven工程
- 按照层进行拆分,例如持久层、业务层、表现层等,每个层对应就是一个maven工程
- ②. 图解
②. maven工程的继承
-
①. 在Java语言中,类之间是可以继承的,通过继承,子类就可以引用父类中非private的属性和方法。同样,在maven工程之间也可以继承,子工程继承父工程后,就可以使用在父工程中引入的依赖。继承的目的是为了消除重复代码
-
②. 被继承的maven工程通常被称为父工程,
父工程的打包方式必须为pom
,所以我们区分某个maven工程是否为父工程就要看这个工程的打包方式是否为pom -
③. 继承其他maven父工程的通常称为子工程,在pom.xml文件中通过parent标签进行父工程的继承
③. maven工程的聚合
-
①. 在maven工程的pom.xml文件中可以使用
<modules>
标签将其他maven工程聚合到一起,聚合的目的是为了进行统一操作 -
②. 例如拆分后的maven工程有多个,如果要进行打包,就需要针对每个工程分别执行打包命令,操作起来非常繁琐。这时就可以使用modules标签将这些工程统一聚合到maven工程中,需要打包的时候,只需要在此工程中执行一次打包命令,其下被聚合的工程就都会被打包了