热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

大话Maven系列笔记(二)——Maven依赖(重点)

第二章、Maven依赖(重点)maven管理依赖也就是jar包牛逼之处是不用我们自己下载,会从一些地方自动下载maven远程仓库: https:mvnrepository.com 

第二章、Maven依赖(重点)

maven管理依赖也就是jar包牛逼之处是不用我们自己下载,会从一些地方自动下载

maven远程仓库:   https://mvnrepository.com/ 

maven远程仓库:   https://maven.aliyun.com/mvn/search 

maven工程中我们依靠在pom.xml文件进行配置完成jar包管理工作(依赖)

 

在工程中引入某个jar包,只需要在 pom.xml 中引入jar包的坐标,比如引入log4j的依赖:



junit
junit
4.7
test

 Maven 通过 groupId 、 artifactId 与 version 三个向量来定位Maven仓库其jar包所在的位置,并把对应的jar包引入到工程中来。

 

jar包会自动下载,流程如下

 


1、依赖的范围

classpath就是编译好的 class字节码文件所在的路径,类加载器( classloader )就是去对应的classpath 中加在class二进制文件。

普通java项目

META-INF中有个文件,有以下内容,告诉jvm执行的时候去哪个类里找main方法。

普通的java工程类路径就是最外层的目录。

1 Manifest-Version: 1.0

2 Main-Class: com.xinzhi.HelloUser

 

 web项目

src 目录下的配置文件会和class文件一样,自动copy到应用的 WEB-INF/classes 目录下 ,所以普通jar包 的类路径就是根路径,没有资源,如果有配置文件也放在src 目录下,他会同步打包在类路径下。 所以web项目的classpath是 WEB-INF/classes

 

maven项目

maven工程会将 src/main/java 和 src/main/resources 目录下的文件全部打包在classpath 中。运行时他们两个的文件夹下的文件会被放在一个文件夹下。

maven 项目不同的阶段引入到classpath中的依赖是不同的,例如:

①编译时 ,maven 会将与编译相关的依赖引入classpath中

②测试时 ,maven会将测试相关的的依赖引入到classpath中

③运行时 ,maven会将与运行相关的依赖引入classpath中

而依赖范围就是用来控制依赖于这三种classpath的关系。

 

依赖范围:使用scope标签表示依赖的范围。

依赖范围表示: 这个依赖(jar和里面类)在项目构建的哪个阶段起作用。

依赖范围scope :

compile:默认, 参与构建项目的所有阶段

test:测试,在测试阶段使用, 比如执行mvn test会使用junit 。

provided: 提供者。 项目在部署到服务器时,不需要提供这个依赖的jar , 而是由服务器提供这个依赖的jar包,典型的是servlet 和jsp 依赖

 

 


1.1、编译依赖范围(compile)

该范围就是默认依赖范围,此依赖范围对于编译、测试、运行三种classpath都有效,举个简单的例子,假如项目中有 fastjson 的依赖,那么 fastjson不管是在编译,测试,还是运行都会被用到,因此 fastjson必须是编译范围(构件默认的是编译范围,所以依赖范围是编译范围的无须显示指定)


com.alibaba
fastjson
1.2.68

 


1.2、测试依赖范围(test)

使用此依赖范围的依赖,只对测试classpath有效,在编译主代码和项目运行时,都将无法使用该依赖, 最典型的例子就是 Junit, 构件在测试时才需要,所以它的依赖范围是测试,因此它的依赖范围需要显示指定为test,当然不显示指定依赖范围也不会报错,但是该依赖会被加入到编译和运行classpath中,造成不必要的浪费 。


junit
junit
4.7

test

 

1.3、已提供依赖范围(provided)

使用该依赖范围的maven依赖,只对编译和测试的classpath有效,对运行的classpath无效,典型的例子就是servlet-api , 编译和测试该项目的时候需要该依赖,但是在运行时,web容器已经提供的该依赖,所以运行时就不再需要此依赖,如果不显示指定该依赖范围,并且容器依赖的版本和maven依赖的版本不一致的话,可能会引起版本冲突,造成不良影响。


javax.servlet
javax.servlet-api
4.0.1
provided

 

1.4、运行时依赖范围(runtime)

使用该依赖范围的maven依赖,只对测试和运行的classpath有效,对编译的classpath无效,典型例子就是JDBC 的驱动实现,项目主代码编译的时候只需要JDK 提供的JDBC 接口,只有在测试和运行的时候才需要实现上述接口的具体JDBC 驱动。


mysql
mysql-connector-java
5.1.25
runtime

 


2、依赖的传递

jar其实也是别人写的工程,他也会依赖其他的jar包,传递性让我们可以不关心所依赖的jar他依赖了其他哪些jar ,只要我们添加了依赖,他会自动将他所依赖的jar统统依赖进来。

我们只需依赖A.jar ,其他的会自动传递进来。

依赖传递的原则:

最短路径优先原则:如果A依赖于B,B依赖于C ,在B和C 中同时有log4j的依赖,并且这两个版本不一致,那么A会根据最短路径原则,在A中会传递过来B的log4j版本。

 

 

 路径相同先声明原则:如果工程同时依赖于B和A ,B和C没有依赖关系,并且都有D的依赖,且版本不一致,那么会引入在pom.xml中先声明依赖的log4j版本

 

 


com.xinzi
B
1.5.3


com.xinzhi
A
1.12.2

因为B优先声明,所以会使用B中引入的D.jar。

 

不同范围的依赖的传递性

A依赖B,B依赖C,A能否使用C呢?要看B依赖C的范围是不是compile ,只有compile范围的依赖是可以传递的

 


3、依赖的排除

不同版本的jar选一个会导致一个问题,1.3.2版本高,A.jar可能用到了高版本的一些新的方法,此时因为某些原因系统选择了低版本,就会导致A.jar报错,无法运行。那么就要想办法把低版本排除掉,一般高版本会兼容低版本

结合上个例子,我们想把低版本的D.jar排除了,就可以这样做,这样系统就只能依赖高版本



com.xinzi
B
1.5.3




com.xinzhi
D





com.xinzhi
A
1.12.2

 


4、聚合和继承


4.1、继承

应用场景:

此时有两个maven项目 : Maven_Parent使用4.0版本的junit,Maven_Son使用3.8版本的junit, 由于junit是test范围的开发包,所以无法依赖不会被传递,那么就会分散在各个项目模块中,这就可能导致版本不统一的问题.

解决的思路:

将junit依赖版本统一提到"父"版本中,在子工程中不指定版本,以父工程中统一设定版本为准,同时也便于修改.

 

4.1.1、创建一个Maven工程作为父工程,打包的方式为pom(聚合模块(父模块)的打包方式必须为pom,否则无法完成构建)


4.0.0


com.mt.sec
Maven_Parent
0.0.1-SNAPSHOT

pom





junit
junit
4.10
test







../Maven_son


 

4.1.2、创建一个Maven工程作为子工程,下面是创建好的原始pom.xml



4.0.0

com.mt.sec
Maven_Son
0.0.1-SNAPSHOT




junit
junit
4.10
test



 

4.1.3、在子工程中添加对父工程的引用


com.mt.sec
Maven_Parent
0.0.1-SNAPSHOT

../Maven_Parent/pom.xml

 

4.1.4、将子工程的坐标与父工程坐标中重复的内容删除。此时子项目和父项目的groupId和version坐标是一样的,所以可以删除掉重复的坐标


com.mt.sec
Maven_Parent
0.0.1-SNAPSHOT

pom

com.mt.sec
Maven_Son
0.0.1-SNAPSHOT

 

4.1.5、在父工程中统一声明junit的依赖。在子工程中删除junit的版本





junit
junit
4.10
test






junit
junit
4.10
test

此时只需要修改父项目的 junit 版本,其他子项目junit依赖版本也会跟着修改

 

经过以上步骤,最终子工程的pom.xml文件修改为




com.mt.sec
Maven_Parent
0.0.1-SNAPSHOT

../Maven_Parent/pom.xml


4.0.0

Maven_Son>




junit
junit
test




 

4.2、聚合

配置继承之后执行安装命令时要先安装父工程,否则会出现安装错误,那么如果每个都需要一个一个的安装,会非常的麻烦。聚合的作用就是一键安装各个模块工程,一般情况下会在父工程中定义聚合,聚合模块(父模块)的打包方式必须为pom,否则无法完成构建

在 Parent项目中定义聚合




../Maven_son

在定义聚合工程中进行maven安装命令

 

 此时maven会根据项目的继承关系,依次安装模块项目

 

可以被继承的POM元素如下:

groupId :项目组ID,项目坐标的核心元素

version :项目版本,项目坐标的核心因素

properties :自定义的Maven属性; 一般用于统一制定各个依赖的版本号

dependencies :项目的依赖配置; 公共的依赖

dependencyManagement :项目的依赖管理配置

repositories :项目的仓库配置

build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等

 

一些对项目的描述 :

description:项目的描述信息

organization:项目的组织信息

inceptionYear:项目的创始年份

url:项目的URL地址

developers:项目的开发者信息

contributors:项目的贡献者信息

distributionManagement:项目的部署配置

issueManagement:项目的缺陷跟踪系统信息

ciManagement:项目的持续集成系统信息

scm:项目的版本控制系统

malilingLists:项目的邮件列表信息

reporting:包括项目的报告输出目录配置、报告插件配置等



推荐阅读
  • 本文详细解析了Java类加载系统的父子委托机制。在Java程序中,.java源代码文件编译后会生成对应的.class字节码文件,这些字节码文件需要通过类加载器(ClassLoader)进行加载。ClassLoader采用双亲委派模型,确保类的加载过程既高效又安全,避免了类的重复加载和潜在的安全风险。该机制在Java虚拟机中扮演着至关重要的角色,确保了类加载的一致性和可靠性。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 深入浅出 webpack 系列(二):实现 PostCSS 代码的编译与优化
    在前一篇文章中,我们探讨了如何通过基础配置使 Webpack 完成 ES6 代码的编译。本文将深入讲解如何利用 Webpack 实现 PostCSS 代码的编译与优化,包括配置相关插件和加载器,以提升开发效率和代码质量。我们将详细介绍每个步骤,并提供实用示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • Eclipse中解决JDK源码断点调试失效的问题 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • Java测试服务器调试指南详细介绍了如何进行远程调试,并深入解析了Java Xdebug参数的使用方法。本文首先概述了Java内置的调试功能,重点介绍了JDB这一类似于GDB的强大调试工具。通过实例演示,读者可以掌握在测试环境中高效调试Java应用程序的技巧,包括配置远程调试环境和优化调试参数,以提高开发效率和代码质量。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • Python与Java编程语言的主要差异分析:常见疑问解答
    本文对Python与Java编程语言的主要差异进行了深入分析,重点探讨了以下几个方面:1. Python在中文社区的资源相对较少;2. Python的面向对象编程更加简洁直接;3. Java拥有更为丰富的类库支持;4. Java在企业级应用中的广泛使用。通过对比这两种语言的特点,为开发者提供了选择时的参考依据。 ... [详细]
author-avatar
手机用户2502868585
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有