maven之依赖管理

走慢一点点 走慢一点点     2022-12-06     176

关键词:

最简单的依赖

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.huang.test</groupId>
    <artifactId>mavenTest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

     <dependencies>
        <dependency>
            <groupId>junit</groupId>  
            <artifactId>junit</artifactId>  
            <version>4.4</version>
            <!--不声明依赖范围scope,默认是compile-->              
            <scope>test</scope>
       </dependency>
    </dependencies>

</project>

在Maven中需要使用在dependencies中定义一个或者多个dependency元素,来声明项目的一个或者多个依赖。 每个依赖元素dependency包括:

groupId 依赖的坐标
artifactId 依赖的坐标
version 依赖的坐标
scope 依赖范围
exclusions 用来排除传递性依赖
type 依赖的类型,对应项目坐标定义的packaging,默认为jar
classifier 用来帮助定义构件输出的一些附属构件
systemPath 表示该依赖项在当前系统的绝对路径

依赖是使用Maven坐标来定位的,而Maven坐标主要由GAV(groupId, artifactId, version)构成。因此,使用任何一个依赖之间,你都需要知道它的Maven坐标。

依赖范围(scope )

compile(默认):编译范围的依赖,它在编译和打包的时候都会把该依赖打包进去
provided:在编译和测试范围有效,最后生成war包时不会打包进去。
runtime:运行时依赖,编译的时候不依赖。
system:系统依赖范围
import:导入依赖范围

依赖范围 与 classpath的关系

例一:对于Junit,一般来说你只有在运行测试的时候需要它,也就是说,它对于src/main/java的classpath没什么意义,并且,将Junit的jar文件打入最终的发布包也不是好事,这无谓的增加了发布包的大小。 其实我们应该这样做:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.4</version>
  <scope>test</test>
</dependency>

于是,junit对于主源码classpath不可用,对于测试源码classpath可用,不会被打包。

例二:在开发javaee应用的时候我们一定会用到servlet-api,它对于主源码和测试源码都是必要的,因为我们的代码中会引入servlet-api的包。但是,在打包的时候,将其放入WAR包就会有问题,因为web容器会提供servlet-api,如果我们再将其打包就会造成依赖冲突,解决方案如下:

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>servlet-api</artifactId>
  <version>2.4</version>
  <scope>provided</scope>
</dependency>

将依赖范围设置成provided,就意味着该依赖对于主源码classpath,以及测试classpath可用,但不会被打包。这正是servlet-api所需要的。

分类器(classifer)

GAV是Maven坐标最基本最重要的组成部分,但GAV不是全部。还有一个元素叫做分类器(classifier),90%的情况你不会用到它,但有些时候,分类器非常不可或缺。 举个简单的例子,当我们需要依赖TestNG的时候,简单的声明GAV会出错,因为TestNG强制需要你提供分类器,以区别jdk14和jdk15,我们需要这样声明对TestNG的依赖:

<dependency>
  <groupId>org.testng</groupId>
  <artifactId>testng</artifactId>
  <version>5.7</version>
  <classifier>jdk15</classifier>
</dependency>

你会注意到maven下载了一个名为testng-5.7-jdk15.jar的文件。其命名模式实际上是--.。
理解了这个模式以后,你就会发现很多文件其实都是默认构件的分类器扩展,如 myapp-1.0-test.jar, myapp-1.0-sources.jar。
分类器还有一个非常有用的用途是:我们可以用它来声明对test构件的依赖,比如,我们在一个核心模块的src/test/java中声明了一些基础类,然后我们发现这些测试基础类对于很多其它模块的测试类都有用。没有分类器,我们是没有办法去依赖src/test/java中的内容的,因为这些内容不会被打包到主构件中,它们单独的被打包成一个模式为--test.jar的文件。 我们可以使用分类器来依赖这样的test构件:

<dependency>
  <groupId>org.myorg.myapp</groupId>
  <artifactId>core</artifactId>
  <version>$project.version</version>
  <classifier>test</classifier>
</dependency>

依赖传递性的冲突问题

参考文章:http://www.cnblogs.com/meet/p/6417496.html

依赖传递性冲突问题解决办法总结
1、通过调整dependency的顺序来解决:哪个依赖的顺序在前面就依赖哪个
2、自己添加一个dependeny来解决:因为该路径是最小的。
3、通过exclusions元素排除不想要的传递性依赖

依赖管理(dependencyManagement)

实际的项目中,会有一大把的Maven模块,而且你往往发现这些模块有很多依赖是完全相同的,A模块有个对spring的依赖,B模块也有,它们的依赖配置一模一样,同样的groupId, artifactId, version,或者还有exclusions, classifer。细心的分会发现这是一种重复,重复就意味着潜在的问题,Maven提供的dependencyManagement就是用来消除这种重复的。
正确的做法是:
1. 在父模块中使用dependencyManagement配置依赖
2. 在子模块中使用dependencies添加依赖
dependencyManagement实际上不会真正引入任何依赖,dependencies才会。但是,当父模块中配置了某个依赖之后,子模块只需使用简单groupId和artifactId就能自动继承相应的父模块依赖配置。 这里是一个来自于《Maven权威指南》的例子: 父模块中如此声明:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook</groupId>
  <artifactId>a-parent</artifactId>
  <version>1.0.0</version>
  ...
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.2</version>
      </dependency>
      ...
    <dependencies>
  </dependencyManagement>

子模块中如此声明:

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.sonatype.mavenbook</groupId>
    <artifactId>a-parent</artifactId>
    <version>1.0.0</version>
  </parent>
  <artifactId>project-a</artifactId>
  ...
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
  </dependencies>
</project>

项目实战中导入依赖的一些原则

例如有一下工程,使用taotao-manage聚合将所有的子工程

子工程之间的依赖关系
taotao-manage-web -> taotao-manage-service -> taotao-manage-mapper -> taotao-manage-pojo

导入依赖的原则:

1、所有工程都需要的依赖应该在聚合工程(taotao-manage)中导入。
比如:

2、在使用依赖的最底层导入。
比如,mybatis的依赖不需要在 taotao-manage-pojo中导入,只需要在taotao-manage-mapper中导入:

3、运行时所需要的依赖在web工程中导入。
比如,以下依赖只需要在taotao-manage-web的pom文件中导入:

ssm实战——秒杀系统之创建项目管理依赖设计数据库

...、测试代码资源(配置文件)3:在pom.xml添加SSM框架所需依赖包:<projectxmlns="http://maven.apache.org/P 查看详情

java学习日记之maven

...,一组标准集合,一个项目周期(ProjectLifecycle),一个依赖管理系统(DependencyManagementSystem),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标的逻辑  二、下载安装    1.官网:https://ma 查看详情

maven之maven简介及安装

1.maven:行内,专家。基于java的项目构建功能,依赖管理,项目信息管理,Maven是一个项目构建工具。2.构建:指日常开发中经常完成的除了编码外的一些动作。如:清理,编译,测试,运行,报告,部署等动作。3.构建工具:构建... 查看详情

maven之可视化项目依赖(visualizingdependencies)

maven之可视化项目依赖(Visualizingdependencies) 项目中经常要查看项目中所依赖的其它lib,现在流行的工具sts(SpringToolSuite),或者IntelliJIDEA 都提供了可视化界面。例如sts: maven也提供了一个dependencyplugin,可以命令行... 查看详情

项目构建工具之maven01

Maven是一个项目管理工具,可以对Java项目进行构建、依赖管理。Maven也可被用于构建和管理各种项目,例如C#,Ruby,Scala和其他语言编写的项目。Maven曾是Jakarta项目的子项目,现为由Apache软件基金会主持的独立Apache项目。Nexus:nex... 查看详情

android知识要点整理(18)----gradle之依赖管理(代码片段)

Gradle在依赖管理方面非常出色,要添加依赖有多种方式,每种方式都特别方便。接下来就讲一讲以依赖管理方面的要点。1.仓库(Repositories)仓库可以看作文件的集合,它可以用来提供依赖源。Gradle支持3种类型的仓... 查看详情

插件依赖的Maven依赖管理

】插件依赖的Maven依赖管理【英文标题】:Mavendependencymanagementforplugindependencies【发布时间】:2012-06-3013:07:03【问题描述】:最近,我遇到了以下问题:当我为我的项目设置依赖项管理时,我有child-pom使用带有依赖项的插件,我希... 查看详情

maven之transitivedependencies(默认树的先序遍历算法处理依赖冲突)

maven之Transitivedependencies(默认树的先序遍历算法处理依赖冲突)OneofMaven‘smajorcontributionsisthewayitdealsandmanagesnotonlydirect dependencies,butalsotransitiveones.   你项目中的依赖,不管是直接依赖还是间接/传递依赖,ma 查看详情

maven依赖管理

...坐标能够确定一个项目。换句话说,我们可以用它来解决依赖关系。在POM中,依赖关系是在dependencies部分中定义的。在上面的POM例子中,我们用dependencies定义了对于junit的依赖:[html]viewplaincopyprint?<dependencies>   &nbs... 查看详情

清理 Maven 依赖管理

】清理Maven依赖管理【英文标题】:CleanupMavendependencymanagement【发布时间】:2011-09-1100:07:40【问题描述】:在一个大型Maven2项目中,使用依赖管理来确保在整个系统中只使用一个版本的依赖是很好的。这使系统保持一致。但是当... 查看详情

maven基础-03-笔记(代码片段)

Maven基础-03-笔记Maven依赖管理、Maven生命周期与插件1、Maven依赖管理1.1依赖配置与依赖传递1.2依赖范围2、Maven生命周期与插件2.1生命周期2.2插件Maven依赖管理、Maven生命周期与插件1、Maven依赖管理1.1依赖配置与依赖传递依赖是指在... 查看详情

maven基础-03-笔记(代码片段)

Maven基础-03-笔记Maven依赖管理、Maven生命周期与插件1、Maven依赖管理1.1依赖配置与依赖传递1.2依赖范围2、Maven生命周期与插件2.1生命周期2.2插件Maven依赖管理、Maven生命周期与插件1、Maven依赖管理1.1依赖配置与依赖传递依赖是指在... 查看详情

使用依赖管理访问 Maven 属性

】使用依赖管理访问Maven属性【英文标题】:Accessmavenpropertyusingdependencymanagement【发布时间】:2018-11-1420:32:23【问题描述】:我正在使用maven的依赖管理将POM导入到我的项目Y中,如下所示:<dependencyManagement><dependencies><d... 查看详情

Maven 或 Ivy 用于管理 Ant 的依赖关系?

】Maven或Ivy用于管理Ant的依赖关系?【英文标题】:MavenorIvyforManagingDependenciesfromAnt?【发布时间】:2010-09-2401:05:08【问题描述】:我想知道从ant管理项目依赖项的最佳方法。MavenAnt任务和Ivy的优缺点是什么?【问题讨论】:【参考... 查看详情

依赖管理中的依赖与 Maven 版本插件中的依赖

】依赖管理中的依赖与Maven版本插件中的依赖【英文标题】:DependenciesinDependencyManagementvsDependenciesinMavenversionsplugin【发布时间】:2015-10-1315:24:42【问题描述】:当我使用Mavenversions:display-dependency-updates检查依赖项更新时,我得到两... 查看详情

Maven 依赖管理版本在传递依赖中被忽略

】Maven依赖管理版本在传递依赖中被忽略【英文标题】:MavendependencyManagementversionignoredintransitivedependencies【发布时间】:2015-04-0311:29:40【问题描述】:尽管我有一个指定版本18的部分,但Maven正在传递地引入guava版本16。快速总结... 查看详情

Maven 依赖管理版本在传递依赖中被忽略

】Maven依赖管理版本在传递依赖中被忽略【英文标题】:MavendependencyManagementversionignoredintransitivedependencies【发布时间】:2015-04-0311:29:40【问题描述】:尽管我有一个指定版本18的部分,但Maven正在传递地引入guava版本16。快速总结... 查看详情

android知识要点整理(18)----gradle之依赖管理(代码片段)

Gradle在依赖管理方面非常出色,要添加依赖有多种方式,每种方式都特别方便。接下来就讲一讲以依赖管理方面的要点。1.仓库(Repositories)仓库可以看作文件的集合,它可以用来提供依赖源。Gradle支持3种类型的仓... 查看详情