普通项目打jar 依赖jar无法加载_坐标和依赖

本文详细介绍了Maven中的依赖管理,包括Maven坐标的组成(groupId, artifactId, version, packaging, classifier)及其作用,依赖配置中的scope如何控制类文件在不同classpath中的位置,以及依赖传递性、依赖范围的调解规则。此外,文章还讨论了可选依赖和排除传递的使用场景,最后总结了介入依赖调解的三种方式:重新声明依赖、使用可选依赖和排除传递。" 47612919,5145273,汉诺塔问题的递归解决方案,"['递归和分治', 'java', 'Hanoi']
摘要由CSDN通过智能技术生成

Maven坐标

Maven定义了这样一组规则:世界上任何一个构件都可以使用Maven坐标唯一标识,Maven坐标的元素包括groupId、artifactId、version、packaging、classifier。现在,只要我们提供正确的坐标元素,Maven就能找到对应的构件。比如说,当需要使用Java5平台上TestNG的5.8版本时,就告诉Maven:“groupId=org.testng;artifactId=testng;version=5.8;classifier=jdk1.5”,Maven就会从仓库中寻找相应的构件供我们使用。

  • groupId

    定义当前Maven项目隶属的实际项目。首先,Maven项目和实际项目不一定是一对一的关系。比如SpringFramework这一实际项目,其对应的Maven项目会有很多,如spring-core、spring-context等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupId不应该对应项目隶属的组织或公司。原因很简单,一个组织下会有很多实际项目,如果groupId只定义到组织级别,而后面我们会看到,artifactId只能定义Maven项目(模块),那么实际项目这个层将难以定义。

    groupId的表示方式与Java包名的表示方式类似,通常与域名反向一一对应。

  • artifactId

    该元素定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。在默认情况下,Maven生成的构件,其文件名会以artifactId作为开头,如nexus-indexer-2.0.0.jar,使用实际项目名称作为前缀之后,就能方便从一个lib文件夹中找到某个项目的一组构件

  • version

    该元素定义Maven项目当前所处的版本,如上例中nexus-indexer的版本是2.0.0。需要注意的是,Maven定义了一套完成的版本规范,以及快照(SNAPSHOT)的概念。对于maven中的版本管理,我们后面会有详细的介绍

  • packaging

    该元素定义Maven项目的打包方式。首先,打包方式通常与所生成构件的文件扩展名对应,如上例中packaging为jar,最终的文件名为nexus-indexer-2.0.0.jar,而使用war打包方式的Maven项目,最终生成的构件会有一个.war文件,不过这不是绝对的。其次,打包方式会影响到构建的生命周期,比如jar打包和war打包会使用不同的命令。最后,当不定义packaging的时候,Maven会使用默认值jar

  • classifier

    该元素用来帮助定义构建输出的一些附属构件。附属构件与主构件对应,如上例中的主构件是nexus-indexer-2.0.0.jar,该项目可能还会通过使用一些插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar这样一些附属构件,其包含了Java文档和源代码。这时候,javadoc和sources就是这两个附属构件的classifier。这样,附属构件也就拥有了自己唯一的坐标。还有一个关于classifier的典型例子是TestNG,TestNG的主构件是基于Java 1.4平台的,而它又提供了一个classifier为jdk5的附属构件。注意,不能直接定义项目的classifier,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成。

上述5个元素中,groupId、artifactId、version是必须定义的,packaging是可选的(默认为jar),而classifier是不能直接定义的

项目构件的文件名是与坐标相对应的,一般的规则为artifactId-version[-classifier].packaging,[-classifier]表示可选。比如上例nexus-indexer的主构件为nexus-indexer-2.0.0.jar,附属构件有nexus-indexer-2.0.0-javadoc.jar。这里还要强调的一点是,packaging并非一定与构件扩展名对应,比如packaging为maven-plugin的构件扩展名为jar。

此外,Maven仓库的布局也是基于Maven坐标,这一点会在介绍Maven仓库的时候详细解释。

依赖配置

依赖会有基本的groupId、artifactId和version等元素组成。其实一个依赖声明可以包含如下的一些元素:

<project>
    ...
    <dependencies>
        <dependency>
            <groupId>...groupId>
            <artifactId>...artifactId>
            <version>...version>
            <type>...type>
            <scope>...<scope>
            <optional>...optional>
            <exclusions>
                <exclusion>
                    ...
                exclusion>
                ...
            exclusions>
        dependency>
        ...
    dependencies>
    ...
project>

根元素project下的dependencies可以包含一个或者多个dependency元素,以声明一个或者多个项目依赖。每个依赖可以包含的元素有:

  • groupId、artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖。

  • type:依赖的类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必声明,其默认值为jar。

  • scope:依赖的范围

  • optional:标记依赖是否可选

  • exclusions:用来排除传递性依赖

依赖范围——scope

我们在上一篇文章中已经提到了maven的本质——为我们提供更加友好的使用jdk tools的操作视图,它帮我们代理了语言基本工具命令的使用,抽象出一套更加简单易懂的操作视图和代码的生命周期,让我们管理我们的源代码。

在java1.5之前,我们在使用jdk的时候要配置一系列classpath环境变量,这个classpath其实就是我们的java代码编译之后生成的字节码的根路径,是提供给jvm加载类的时候使用的;同时也是我们的放置依赖的地方,javac在编译代码进行静态校验的时候也会从这里读取类。

在java1.5及以后的版本中,jdk会自动把当前的目录作为classpath,所以就不用配置了。

两套classpath

maven抽象出了一个项目构建的生命周期,在使用maven进行项目构件的时候,maven帮我们维护了两套classpath,如下:

  • 主代码的classpath。

    在这一套classpath中包含两个部分

    • 编译主代码的时候的classpath,我们称之为main-compile-classpath

      这一个classpath其实就是我们编写代码的工作目录中的classpath,是java的编译器在进行编译时进行class查找的地方

    • 主代码运行时的classpath,我们称之为main-runtime-classpath

      这个classpath就是Java代码在运行的时候jvm加载class的classpath。

  • Maven在编译和执行测试的时候会使用另外一套classpath。

    其实test代码的classpath也是包含两部分的:

    • 编译test代码是所需的classpath,我们称之为test-complie-classpath

    • 运行test代码的时候jvm加载class文件所需的classpath,我们称之为test-runtime-classpath

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值