您当前的位置: 首页 >  maven

Dongguo丶

暂无认证

  • 0浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Maven的几个核心概念

Dongguo丶 发布时间:2018-04-06 15:51:50 ,浏览量:0

Maven的几个核心概念 POM(Project Object Model)

一个项目所有的配置都放在POM文件中:定义项目的类型、名字、管理依赖关系,定制插件的行为等等。看下我自己写的小demo中pom中配置如下:

com.dodonew
springmvc
1.0-SNAPSHOT
war
springmvc
http://maven.apache.org

org.slf4j jcl-over-slf4j 1.7.21 ch.qos.logback logback-classic 1.1.7

在POM中,groupId、artifactId、packaging、version叫做maven坐标,它能唯一的确定一个项目。有了maven坐标,我们就可以用它来指定我们的项目所依赖的其他项目、插件、或者父项目。我写的demo很简单,但是比较大的项目一般会分成几个子项目,在这种情况下,每个子项目就会有自己的POM文件,它们会有一个共同的父项目。这样只要构建父项目就能够构建所有的子项目了。同时子项目的POM会继承父项目的POM。关于多个子项目具体怎么操作,在文章后面会有回答的。

Maven插件

Maven常用的插件比如compiler插件、surefire插件、jar插件。比如说jar插件包含建立jar文件的目标,compiler插件包含编译源代码和单元测试代码的目标,surefire插件则是运行单元测试的目标。为什么需要这些插件呢?因为maven本身不会做太多的事情,它不知道怎么样编译或者怎么样打包。它把构建的任务交给插件去做。插件定义了常用的构建逻辑,能够被重复利用。这样做的好处是,一旦插件有了更新,那么所有maven用户都能得到更新。

Maven生命周期

生命周期指项目的构建过程,它包含了一系列的有序的阶段,而一个阶段就是构建过程中的一个步骤,比如package阶段、compiler阶段等。那么生命周期阶段和上面说的插件目标之间是什么关系呢?插件目标可以绑定到生命周期阶段上,一个生命周期可以绑定多个插件目标。当maven在构建过程中逐步的通过每个阶段时,会执行该阶段所有的插件目标。目前生命周期阶段有clean、vavidate、compiler、test、package、verify、install、site、deploy阶段。

Maven依赖管理

我们能够通过maven坐标确定一个项目,换句话说,我们可以用它来解决依赖关系。在POM中,依赖关系是在dependencies部分中定义的。比如对slf4j库和logback库的依赖关系如下:


    
    
        org.slf4j
        jcl-over-slf4j
        1.7.21
    
    
        ch.qos.logback
        logback-classic
        1.1.7
    

这个依赖关系是比较简单的,但是实际开发中我们会有复杂多的依赖关系,因为被依赖的jar文件会有自己的依赖关系,那么我们是不是也得把间接依赖的jar文件也都定义在POM中呢?答案是不需要,因为maven提供了传递依赖的特性,会把依赖的jar文件它所依赖的库也自动添加进来。比如spring-webmvc库,这个库自己又依赖spring-core、spring-beans、spring-web、spring-expression、spring-context,因为依赖传递性,我们在使用spring-webmvc的时候,只需要声明对spring-webmvc的依赖关系即可,其他的库会自动帮你引入的。之所以能实现依赖传递性关键就在于下载spring-webmvc库,同时也下载了pom文件,在pom文件定义了这个库需要的依赖关系。

scope决定了依赖关系的适用范围,比如junit的scope是test,那么它只会在执行compiler:testCompile和surefire:test目标的时候才会被加载到classpath中,在执行compiler:compile目标时是拿不到junit的。换句话说就是在maven哪个生命周期中起作用了。scope的默认值是compile,即任何时候都会被包含在classpath中,在打包的时候也会被包括进去。

Maven库

我们所依赖的库是从maven默认的远程库 (http://repo.maven.org/maven2) 下载的,这个是公有的库。有时公司自己封装了一些私有库,这个时候我们就可以搭建自己的私有库了。本地库是指maven下载了插件或者jar文件后存放在本地机器上的拷贝。在Mac上,它的位置在~/.m2/repository。当maven查找需要的jar文件时,它会先在本地库中查找,只有在找不到的情况下,才会去远程库中找的。由于maven默认的远程库服务器在国外,国内访问的时候比较慢,建议替换成阿里云的镜像,仓库地址如下:

http://maven.aliyun.com/nexus/content/groups/public/
Maven多模块项目POM注意的事项 denpendencyManagement

在项目开发过程中,有时一个项目下面包含了几个子模块,在多模块的情况,POM的配置应该要注意写什么呢?我们通过一个例子来说明下。有这样一个工程,里面有A模块、B模块和C模块,A模块需要引入junit和log4j库,配置如下:


    junit
    junit
    3.8.2
  
  
    log4j
    log4j
    1.2.9
  

此时B模块也需要引入这两个库,配置如下:


    junit
    junit
    4.8.2
    test
  
  
    log4j
    log4j
    1.2.16
  

会发现A模块和B模块对junit和log4j库依赖的版本是不同的,出现这种情况是十分危险的,因为依赖不同版本的库可能会造成很多未知的风险。怎么解决不同模块之间对同一个库的依赖版本一样呢?Maven提供了优雅的解决办法,使用继承机制以及dependencyManagement元素来解决这个问题。如果你在父模块中配置dependencies,那么所有的子模块都自动继承,不仅达到了依赖一致的目的,还省了大段的代码,但这样来做会存在问题的。比如B模块需要spring-aop模块,但是C模块不需要spring-aop模块,如果用dependencies在父类中统一配置,C模块中也会包含有spring-aop模块,不符合我们的要求。但是用dependencyManagement就没有这样的问题。dependencyManagement只会影响现有依赖的配置,但不会引入依赖。这样我们在父模块中的配置可以更改如下所示:



    
        
            junit
            junit
            4.12
            test
        
        
            log4j
            log4j
            1.2.17
        
    

这段配置不会给任何子模块引入依赖,如果某个子模块需要junit和log4j,只需要这样配置即可:


    
        junit
        junit
    
    
        log4j
        log4j
    

在多模块Maven项目中,使用dependencyManagement能够有效地帮我们维护依赖一致性。

pluginManagement

上面介绍了在多模块中对依赖库的管理,接下来介绍下对插件的管理。与dependencyManagement类似,我们可以使用pluginManagement元素管理插件。一个常见的用法就是我们希望项目所有模块的使用compiler插件的时候,都是用java1.7,以及指定Java源文件编码为UTF-8,这时可以在父模块的POM中如下配置pluginManagement:


      
        
              
                org.apache.maven.plugins
                maven-compiler-plugin
                2.3.2
                
                  1.5
                  1.5
                  UTF-8
                
              
        
      

这段配置会被应用到所有子模块的compiler插件中,因为Maven内置了与compiler插件与生命周期的绑定,因此子模块不需要任何maven-compiler-plugin的配置了。

Maven常用的几个插件

Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成。下面说几个常用的插件:

maven-compiler-plugin(编译插件)

用来编译Java代码,在对Java代码进行编译的时候,可以指定使用哪个JDK的版本来进行编译,配置如下所示:


       org.apache.maven.plugins
      maven-compiler-plugin
      3.6.0
      
          1.7 
         1.7 
      

maven-resources-plugin(资源插件)

Maven区别对待Java代码和资源文件,maven-resources-plugin则用来处理资源文件。默认的主资源文件目录是src/main/resources,很多时候会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现,配置如下所示:


    org.apache.maven.plugins
    maven-resources-plugin
    2.5
    
        
            compile 
        
    

maven-surefire-plugin(测试插件)

Maven2/3中用于执行测试的插件不是maven-test-plugin,而是maven-surefire-plugin,其实在大部分情况下,只要你的测试类遵循通用的命令约定(以Test结尾,以TestCase结尾、或者Test开头),就几乎不用知晓该插件的存在。但是当你想要跳过测试、排除某些测试类、或者使用一些TestNG特性的时候,就要用到了maven-surefire-plugin的一些配置选项了,配置如下所示:


    org.apache.maven.plugins
    maven-surefire-plugin
    2.14
    
        true 
    

maven-clean-plugin(清除插件)

主要作用就是清理构建目录下的全部内容,有些项目,构建时需要清理构建目录以外的文件,比如指定的库文件,这时候就需要配置来实现了,配置如下所示:


    org.apache.maven.plugins
    maven-clean-plugin
    3.0.0
    
        
        
        
        false
        
            
                
                ${basedir}/logs
                
                false
               
        
    

maven-war-plugin(打包插件)

主要作用就是用来打包的,在打包的时候经常需要排除一些文件,就需要对warSourceExcludes进行配置了,配置如下所示:


    maven-war-plugin
    2.0.2
    
        WEB-INF/lib/**
    
总结

Maven是一个项目管理和自动化构建工具,项目遵循约定优于配置,这也是maven项目的一大特色。另外,maven本质上是一个插件框架,它的核心不执行任何具体的构建工作,全部都交给插件去执行,maven插件是与maven生命周期绑定在一起的。理解这些重要的核心点,对于maven的使用会有很大的帮助。

参考文章

Maven入门介绍

http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-1-406235-zhs.html

http://www.oracle.com/technetwork/cn/community/java/apache-maven-getting-started-2-405568-zhs.html

https://maven.apache.org/what-is-maven.html

Maven常用插件

http://www.infoq.com/cn/news/2011/04/xxb-maven-7-plugin

http://www.infoq.com/cn/news/2011/05/xxb-maven-8-plugin

关注
打赏
1638062488
查看更多评论
立即登录/注册

微信扫码登录

0.0387s