3-maven学习-学习创建maven的依赖属性

一、什么是依赖属性

在por.xml配置中会添加所需要引入的jar包,前面已经知道,jar包有三要素:必须写

  • groupId:公司或组织的id

  • artifactId:一个项目或者是项目中的一个模块的id

  • version:版本号

但其实还有scope属性,这个代表依赖程度,比如有些jar包只需要在测试时使用,打包成项目时不需要这个jar包,就可以设置为test等级,这样可以减少今后打包部署项目时的所占容量

二、依赖范围

标签的位置:dependencies/dependency/scope

标签的可选值:compile/test/provided

①compile和test对比

main目录(空间) test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
test 无效 有效 有效 无效

②compile和provided对比

main目录(空间) test目录(空间) 开发过程(时间) 部署到服务器(时间)
compile 有效 有效 有效 有效
provided 有效 有效 有效 无效

③结论

compile:通常使用的第三方框架的jar包这样在项目实际运行时真正要用到的jar包都是以compile范围进行依赖的。比如SSM框架所需jar包。

test:测试过程中使用的jar包,以test范围依赖进来。比如junit。

provided:在开发过程中需要用到的“服务器上的jar包”通常以provided范围依赖进来。比如servlet-api、jsp-api。而这个范围的jar包之所以不参与部署、不放进war包,就是避免和服务器上已有的同类jar包产生冲突,同时减轻服务器的负担。说白了就是:“服务器上已经有了,你就别带啦!”

三、测试scope不同属性的依赖范围

①验证test范围对main目录无效

测试方式:在主体程序中导入org.junit.Test这个注解,然后执行编译。

具体操作:在pro01-maven-java\src\main\java\com\kevin\maven目录下修改Calculator.java

package com.kevin.maven;
​
import org.junit.Test;
​
public class Calculator {
    
    public int sum(int i, int j){
        return i + j;
    }
    
}

执行Maven编译命令:

[ERROR] /D:/maven-workspace/space201026/pro01-maven-java/src/main/java/com/kevin/maven/Calculator.java:[3,17] 程序包org.junit不存在

②验证test和provided范围不参与服务器部署

其实就是验证:通过compile范围依赖的jar包会放入war包,通过test范围依赖的jar包不会放入war包。

  
    
      junit
      junit
      4.11
      test
    
	
		javax.servlet
		javax.servlet-api
		4.0.1
		provided
	
	
		com.atguigu
		pro01-maven-java
		1.0-SNAPSHOT
		provided
	
  

执行compile packge,找到打包的项目并解压,进入webapp->WEBINF->lib->看看有没有上面三个包,可以发现在打包时,test和provided属性的都是不打进包的

③验证provided范围对测试程序有效

测试方式是在pro02-maven-web的测试程序中加入servlet-api.jar包中的类。

修改:pro02-maven-web\src\test\java\com\kevin\maven\CalculatorTest.java

package com.kevin.maven;
​
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
​
import org.junit.Test;
import com.kevin.maven.Calculator;
​
// 静态导入的效果是将Assert类中的静态资源导入当前类
// 这样一来,在当前类中就可以直接使用Assert类中的静态资源,不需要写类名
import static org.junit.Assert.*;
​
public class CalculatorTest{
    
    @Test
    public void testSum(){
        
        // 1.创建Calculator对象
        Calculator calculator = new Calculator();
        
        // 2.调用Calculator对象的方法,获取到程序运行实际的结果
        int actualResult = calculator.sum(5, 3);
        
        // 3.声明一个变量,表示程序运行期待的结果
        int expectedResult = 8;
        
        // 4.使用断言来判断实际结果和期待结果是否一致
        // 如果一致:测试通过,不会抛出异常
        // 如果不一致:抛出异常,测试失败
        assertEquals(expectedResult, actualResult);
        
    }
    
}

然后运行Maven的编译命令:mvn compile

然后看到编译成功。

④查看当前Web工程所依赖的jar包的列表

mvn dependency:list

[INFO] The following files have been resolved:

[INFO] org.hamcrest:hamcrest-core:jar:1.3:test

[INFO] javax.servlet:javax.servlet-api:jar:3.1.0:provided

[INFO] com.kevin.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile

[INFO] junit:junit:jar:4.12:test

说明:javax.servlet:javax.servlet-api:jar:3.1.0:provided格式显示的是一个jar包的坐标信息。格式是:

groupId:artifactId:打包方式:version:依赖的范围

这样的格式虽然和我们XML配置文件中坐标的格式不同,但是本质上还是坐标信息,大家需要能够认识这样的格式,将来从Maven命令的日志或错误信息中看到这样格式的信息,就能够识别出来这是坐标。进而根据坐标到Maven仓库找到对应的jar包,用这样的方式解决我们遇到的报错的情况。

⑤以树形结构查看当前Web工程的依赖信息

mvn dependency:tree

[INFO] com.atguigu.maven:pro02-maven-web:war:1.0-SNAPSHOT

[INFO] +- junit:junit:jar:4.12:test

[INFO] | - org.hamcrest:hamcrest-core:jar:1.3:test

[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided

[INFO] - com.kevin.maven:pro01-maven-java:jar:1.0-SNAPSHOT:compile

我们在pom.xml中并没有依赖hamcrest-core,但是它却被加入了我们依赖的列表。原因是:junit依赖了hamcrest-core,然后基于依赖的传递性,hamcrest-core被传递到我们的工程了。

四、依赖的传递性

①概念

A依赖B,B依赖C,那么在A没有配置对C的依赖的情况下,A里面能不能直接使用C?

②传递的原则

在A依赖B,B依赖C的前提下,C是否能够传递到A,取决于B依赖C时使用的依赖范围。

  • B依赖C时使用compile范围:可以传递
  • B依赖C时使用test或provided范围:不能传递,所以需要这样的jar包时,就必须在需要的地方明确配置依赖才可以。

五、依赖的排除

当A依赖B,B依赖C而且C可以传递到A的时候,但是A不想要C,需要在A里面把C排除掉。而往往这种情况都是为了避免jar包之间的冲突。

3-maven学习-学习创建maven的依赖属性_第1张图片

 

所以配置依赖的排除其实就是阻止某些jar包的传递。因为这样的jar包传递过来会和其他jar包冲突。


    com.atguigu.maven
    pro01-maven-java
    1.0-SNAPSHOT
    compile

    
    
        
        
            
            commons-logging
            commons-logging
        
    

六、maven项目的继承

1、继承的概念

Maven工程之间,A工程继承B工程

  • B工程:父工程
  • A工程:子工程

本质上是A工程的pom.xml中的配置继承了B工程中pom.xml的配置。

2、作用

在父工程中统一管理项目中的依赖信息,具体来说是管理依赖信息的版本。

3、举例

在一个工程中依赖多个Spring的jar包

[INFO] +- org.springframework:spring-core:jar:4.0.0.RELEASE:compile [INFO] | - commons-logging:commons-logging:jar:1.1.1:compile [INFO] +- org.springframework:spring-beans:jar:4.0.0.RELEASE:compile [INFO] +- org.springframework:spring-context:jar:4.0.0.RELEASE:compile [INFO] +- org.springframework:spring-expression:jar:4.0.0.RELEASE:compile [INFO] +- org.springframework:spring-aop:jar:4.0.0.RELEASE:compile [INFO] | - aopalliance:aopalliance:jar:1.0:compile

使用Spring时要求所有Spring自己的jar包版本必须一致。为了能够对这些jar包的版本进行统一管理,我们使用继承这个机制,将所有版本信息统一在父工程中进行管理。

4、操作

①创建父工程

创建的过程和前面创建pro01-maven-java一样。

工程名称:pro03-maven-parent

工程创建好之后,要修改它的打包方式:

  com.atguigu.maven
  pro03-maven-parent
  1.0-SNAPSHOT
  pom

只有打包方式为pom的Maven工程能够管理其他Maven工程。

②创建模块工程

模块工程类似于IDEA中的module,所以需要进入pro03-maven-parent工程的根目录,然后运行mvn archetype:generate命令来创建模块工程。

假设,我们创建三个模块工程:

3-maven学习-学习创建maven的依赖属性_第2张图片

 

③查看被添加新内容的父工程pom.xml

下面modules和module标签是聚合功能的配置

  
    pro04-maven-module
    pro05-maven-module
    pro06-maven-module

 

④解读子工程的pom.xml



    
    com.atguigu.maven
    pro03-maven-parent
    1.0-SNAPSHOT



pro04-maven-module

 

⑤在父工程中配置依赖的统一管理(必须在dependency Management标签下)




    
        
            org.springframework
            spring-core
            4.0.0.RELEASE
        
        
            org.springframework
            spring-beans
            4.0.0.RELEASE
        
        
            org.springframework
            spring-context
            4.0.0.RELEASE
        
        
            org.springframework
            spring-expression
            4.0.0.RELEASE
        
        
            org.springframework
            spring-aop
            4.0.0.RELEASE
        
    

 

⑥子工程中引用那些被父工程管理的依赖

关键点:省略版本号





    
        org.springframework
        spring-core
    
    
        org.springframework
        spring-beans
    
    
        org.springframework
        spring-context
    
    
        org.springframework
        spring-expression
    
    
        org.springframework
        spring-aop
    

 

⑦在父工程中升级依赖信息的版本


……
            
                org.springframework
                spring-beans
                4.1.4.RELEASE
            
……

然后在子工程中运行mvn dependency:list,效果如下:

[INFO] org.springframework:spring-aop:jar:4.1.4.RELEASE:compile [INFO] org.springframework:spring-core:jar:4.1.4.RELEASE:compile [INFO] org.springframework:spring-context:jar:4.1.4.RELEASE:compile [INFO] org.springframework:spring-beans:jar:4.1.4.RELEASE:compile [INFO] org.springframework:spring-expression:jar:4.1.4.RELEASE:compile

 

 

⑧在父工程中声明自定义属性 



    UTF-8
    
    
    4.3.6.RELEASE

在需要的地方使用${}的形式来引用自定义的属性名:

            
                org.springframework
                spring-core
                ${atguigu.spring.version}
            

真正实现“一处修改,处处生效”。

5、实际意义

编写一套符合要求、开发各种功能都能正常工作的依赖组合并不容易。如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间。为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来。

3-maven学习-学习创建maven的依赖属性_第3张图片 

 

如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目、子系统各取所需即可。

七、聚合本身的含义

1、含义

部分组成整体

2、Maven中的聚合

使用一个“总工程”将各个“模块工程”汇集起来,作为一个整体对应完整的项目。

  • 项目:整体
  • 模块:部分

概念的对应关系:

从继承关系角度来看:

  • 父工程
  • 子工程

从聚合关系角度来看:

  • 总工程
  • 模块工程

3、好处

  • 一键执行Maven命令:很多构建命令都可以在“总工程”中一键执行。

    以mvn install命令为例:Maven要求有父工程时先安装父工程;有依赖的工程时,先安装依赖的工程。我们自己考虑这些规则会很麻烦。但是工程聚合之后,在总工程执行mvn install可以一键完成安装,而且会自动按照正确的顺序执行。

  • 配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然。

4、聚合的配置

在总工程中配置modules即可:

      
        pro04-maven-module
        pro05-maven-module
        pro06-maven-module
    

5、依赖循环问题

如果A工程依赖B工程,B工程依赖C工程,C工程又反过来依赖A工程,那么在执行构建操作时会报下面的错误:

[ERROR] [ERROR] The projects in the reactor contain a cyclic reference:

这个错误的含义是:循环引用。

你可能感兴趣的:(maven学习,maven,学习)