您的位置:首页 > 其它

Maven中的核心概念

2016-12-29 11:33 239 查看
  我们最能感受到的Maven的好处应该是它的“自动化构建”与“管理依赖关系”两大功能,下面就看围绕这两大功能的Maven中的核心概念。

1.    项目目录

  Maven 使用约定优于配置的原则 。它要求在没有定制之前,所有的项目都有如下的主要目录结构:

  


  一个 maven 项目在默认情况下会产生 JAR 文件,另外 ,编译后 的 .classe文件 会放在 ${basedir}/target/classes 下面;JAR文件会放在${basedir}/target
下面。如下图所示:

  


2.    POM (Project Object Model)

  2.1  概念介绍

    一个项目所有的配置都放置在 POM 文件中:定义项目的类型、名字,管理依赖关系,定制插件的行为等等。比如说,你可以配置 compiler 插件让它使用 java1.5 来编译。

[html]
view plain
copy

print?





<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">  
   <modelVersion>4.0.0</modelVersion>   
  
   <groupId>com.mycompany.helloworld</groupId>   
   <artifactId>helloworld</artifactId>   
   <version>1.0-SNAPSHOT</version>   
   <packaging>jar</packaging>   
  
   <name>helloworld</name>   
   <url>http://maven.apache.org</url>   
  
   <properties>   
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>   
   </properties>   
  
   <dependencies>  
     <dependency>   
       <groupId>junit</groupId>   
       <artifactId>junit</artifactId>   
       <version>3.8.1</version>   
       <scope>test</scope>   
     </dependency>   
   </dependencies>   
  </project>      



<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"> <modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>helloworld</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>


    在 POM 中,groupId,artifactId, packaging, version 叫作 maven 坐标,它能唯一的确定一个构件。有了 maven 坐标,我们就可以用它来指定我们的项目所依赖的其他项目,插件,或者父项目。

    


    通常,大项目一般会分成几个子项目。在这种情况下,每个子项目就会有自己的 POM 文件,然后它们会有一个共同的父项目。这样只要构建父项目就能够构建所有的子项目了。子项目的 POM 会继承父项目的 POM。另外,所有的 POM都继承了一个 Super-POM。Super-POM 设置了一些默认值,比如在前面提到的默认的目录结构,默认的插件等等,它遵循了惯例优于配置的原则。如下图:

    


  2.2  Pom文件的继承与聚合

  继承

    开发中一般将公共的配置——依赖关系(包括公共的类库、插件、信息配置)放到一个父项目的pom文件,然后其它项目的pom文件,都继承该pom文件。继承的代码如下:

    


    这里需要注意,子pom文件不是一旦继承了父pom就会无条件地继承它所有的依赖关系,即插件、类库等。如果子pom想继承父pom的某个插件,只需要引入父pom中该插件的groupId与artifactId信息(不用写该插件其它的配置信息)即可。这样子pom是可以有选择性的继承它自己所需要的东西。

    


  聚合

    即大项目中一般会有一个空的Maven项目(只有pom文件,没有Java代码)作为父项目,该项目的Pom文件(Modules标签中)聚合了其它子项目的Pom文件,然后只要构建父项目就能够构建所有的子项目了。

    


3.    Maven 插件

       Maven的每个生命周期都有一个“插件”(目标)来保证。在前面,我们用了 mvn archetype:generate 命令来生成一个项目。那么这里的 archetype:generate 是什么意思呢?archetype是一个插件的名字,generate是目标(goal)的名字。这个命令的意思是告诉 maven 执行archetype 插件的 generate 目标。插件目标通常会写成
pluginId:goalId

  一个目标是一个工作单元,而插件则是一个或者多个目标的集合。比如说Jar插件,Compiler插件,Surefire插件等。从看名字就能知道,Jar插件包含建立Jar文件的目标, Compiler 插件包含编译源代码和单元测试代码的目标。Surefire
插件的话,则是运行单元测试。

  看到这里,估计你能明白了,mvn本身不会做太多的事情,它不知道怎么样编译或者怎么样打包。它把构建的任务交给插件去做。插件定义了常用的构建逻辑,能够被重复利用。这样做的好处是,一旦插件有了更新,那么所有的 maven 用户都能得到更新。

  Maven的插件服务非常强大,比如你想打包源代码为rar压缩格式,比如你想执行sql命令,等等,只需要找到相应的Maven插件,配置好即可使用,如下图:

  


4.    Maven 生命周期

  在前面,我们用的第二个命令是:mvn package。这里的 package 是一个maven的生命周期阶段 (lifecyclephase )。生命周期指项目的构建过程,它包含了一系列的有序的阶段 (phase),而一个阶段就是构建过程中的一个步骤。

  那么生命周期阶段和上面说的插件目标之间是什么关系呢?插件目标可以绑定到生命周期阶段上。一个生命周期阶段可以绑定多个插件目标。当 maven 在构建过程中逐步的通过每个阶段时,会执行该阶段所有的插件目标。

  maven 能支持不同的生命周期,但是最常用的是默认的Maven生命周期 (default Mavenlifecycle )。

  Maven有3套生命周期,clean、compile、site,在配置插件的时候一般都要配置插件的执行时机(即Maven的某一个生命周期),如下图:

  


  这里不一 一介绍生命周期,只介绍几个常用的:

  Clean

    pre-clean:执行一些需要在clean之前完成的工作

    clean:移除所有上一次构建生成的文件(清除Target文件夹)

    post-clean:执行一些需要在clean之后立刻完成的工作

  Compile

         process-resources:复制并处理资源文件至目标目录,准备打包

         compile:编译项目源代码

         process-test-resources:复制并处理资源文件至目标测试目录

         test-compile:编译测试源代码

         test:使用合适的单元测试框架运行测试,这些测试代码不会被打包或部署。

         package:接受编译好的代码,打包成可发布的个格式,如jar

         install:将包安装至本地仓库,以让其它项目依赖

         deploy:将最终的包复制到远程仓库,以让其它开发人员与项目共享。

  Site

    pre-site:执行一些需要在生成站点文当前完成的工作。

    site:生成项目的站点文档。

    post-site:执行一些需要在生成站点文档之后完成的工作,并未部署做准备。

    site-deploy:将生成的站点文档部署到服务器上。

5.    Maven 依赖管理

  5.1  概念介绍

    之前我们说过,maven 坐标能够确定一个项目。换句话说,我们可以用它来解决依赖关系。在 POM 中,依赖关系是在 dependencies部分中定义的。在上面的 POM 例子中,我们用 dependencies 定义了对于 junit 的依赖:

[html]
view plain
copy

print?





<dependencies>   
    <dependency>   
      <groupId>junit</groupId>   
      <artifactId>junit</artifactId>   
      <version>3.8.1</version>   
      <scope>test</scope>   
    </dependency>   
  </dependencies>   



<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
<
ee0b
/dependency>
</dependencies>


    我们依赖的类库,我们都可以到Maven的中央仓库去找,例如下图找hibernate的核心包:mvnrepository.com/search.html?query=hibernate
    


    上面的例子很简单,但是实际开发中我们会有复杂得多的依赖关系,因为被依赖的 jar 文件会有自己的依赖关系。那么我们是不是需要把那些间接依赖的 jar 文件也都定义在POM中呢?答案是不需要,因为 maven 提供了传递依赖的特性。
    所谓传递依赖是指 maven 会检查被依赖的 jar 文件,把它的依赖关系纳入最终解决的依赖关系链中。针对上面的 junit 依赖关系,如果你看一下 maven 的本地库你会发现 maven 不但下载了 junit-3.8.1.jar,还下载了它的 POM 文件。这样 maven 就能检查 junit 的依赖关系,把它所需要的依赖也包括进来。
    在 POM 的 dependencies 部分中,scope 决定了依赖关系的适用范围。我们还可以指定scope 为 provided,意思是 JDK 或者容器会提供所需的jar文件。比如说在做web应用开发的时候,我们在编译的时候需要servlet API jar 文件,但是在打包的时候不需要把这个 jar文件打在 WAR 中,因为servlet容器或者应用服务器会提供的。
    scope 的默认值是 compile,即任何时候都会被包含在 classpath 中,在打包的时候也会被包括进去。

  5.2  依赖的范围(scope)

    有如下几种:

    test:

      指测试范围有效,编译和打包时都不使用该依赖。

    compile:(为默认值)

      编译范围有效,编译和运行(打包)时都会将依赖存进去

    provided:

      测试、编译范围都有效,最后生成war包时不会加入,例如:servlet-api,编译的时候需要该文件,但是在打包的时候不需要把这个 jar 文件打在 WAR 中,因为servlet容器或者应用服务器会提供的。打进去会出现冲突。

    runtime:

          编译时不依赖,运行(打包)时依赖

    


  5.3  依赖的传递(间接依赖)

    首先,依赖是可以传递的

    


    当依赖层级相同的时候,相同的东西,会采用,近者优先。当依赖层级不同时,层级(最短)近的优先。

    


  5.4  排除依赖

    当依赖包发生冲突时,我们可以用exclusion标签排除依赖

    


6.     Maven仓 库

  6.1  概念介绍

    主要介绍3种仓库,本地仓库、私服(Nexus)、中央仓库。3者的关系如下图所示:

    


    首先,Maven本身自带一个本地仓库;然后它又为全世界的Java开发者提供了一个免费的“中央仓库”,在其中几乎可以找到任何流行的开源类库;由于中央仓库是在外网中的,如果没有私服(Nexus),本地仓库就会频繁地与中央仓库即互联网打交道,这样效率很低,所以在两者之间衍生出了一个“私服——Nexus”,私服存在于局域网中,这样本地仓库就不用频繁地与外网中的中央仓库交互,所以效率就会大大提高。

  6.2  修改本地仓库

    本地仓库的位置默认为:${user.home}/.m2/repository。例如下图:

    


    修改本地仓库位置的步骤如下:

    新建本地工厂的文件夹,如我建在,与Maven同目录下:

    


    将F:\maven\apache-maven-3.2.3\conf文件夹下的Settings.xml文件夹拷贝到上面新建的本地工厂的同级目录位置

    


    修改本地工厂同目录下的Settings.xml文件中的内容,设置本地仓库的位置为,上面新建的仓库的目录

    


    到此完成。

  6.3  中央仓库的位置

    中央仓库的位置在如下目录中:

    ${MAVEAN_HOME}\lib\maven-model-builder.jar\org\apache\maven\mode\pom.xml中,如下图:

    


    Nexus的安装与介绍在后面的文章中介绍。

7.    总结

    Maven提倡“约定优于配置”,它的项目的目录结构,测试方法的命名等都有一定的要求。

    Maven是基于Pom的,一个Maven项目所有的配置都放置在 POM 文件中:定义项目的类型、名字,管理依赖关系,定制插件的行为等等。Pom文件之间还可以继承、聚合等。

    Maven很强大,很大一方面是它的插件服务非常强大,Maven本身基本不怎么做事,它基本是调用一些插件来做事。Maven有3套生命周期,clean、compile、site,而每个生命周期中的每个步骤都有一个目标插件来支持。配置每个插件时也都会指明插件的运行时机(即Maven生命周期中的某个步骤)。

    Maven自带强大的依赖管理系统,配置了某个依赖,确定了某个构件的坐标,Maven就能帮我们自动下载构件。

    Maven本身自带一个本地仓库;然后它又为全世界的Java开发者提供了一个免费的“中央仓库”,为了解决本地仓库频繁与中央仓库(存在于外网中)交互,导致效率低的问题,又衍生出了私有仓库,即私服(Nexus)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: