Maven基础

一、概述

Maven是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。

1、Maven功能

Maven 能够帮助开发者完成以下工作:

  • 构建
  • 文档生成
  • 报告
  • 依赖
  • SCMs
  • 发布
  • 分发
  • 邮件列表

2、约定配置

Maven 提倡使用一个共同的标准目录结构,Maven 使用约定优于配置的原则,大家尽可能的遵守这样的目录结构。如下所示:

目录 目的
${basedir} 存放pom.xml和所有的子目录
${basedir}/src/main/java 项目的java源代码
${basedir}/src/main/resources. 项目的资源,比如说property文件,springmvc.xml.
${basedir}/src/test/java 项目的测试类,比如说Junit代码
${basedir}/src/test/resources 测试用的资源
${basedir}/src/main/webapp/WEB-INF web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target 打包输出目录
${basedir}/target/classes 编译输出目录
${basedir}/target/test-classes 测试编译输出目录
Test.java Maven只会自动运行符合该命名规则的测试类
~/.m2/repository Maven默认的本地仓库目录位置

3、Maven 特点

  • 项目设置遵循统一的规则。

  • 任意工程中共享。

  • 依赖管理包括自动更新。

  • 一个庞大且不断增长的库。

  • 可扩展,能够轻松编写 Java 或脚本语言的插件。

  • 只需很少或不需要额外配置即可即时访问新功能。

  • 基于模型的构建 − Maven能够将任意数量的项目构建到预定义的输出类型中,如 JAR,WAR 或基于项目元数据的分发,而不需要在大多数情况下执行任何脚本。

  • 项目信息的一致性站点 − 使用与构建过程相同的元数据,Maven 能够生成一个网站或PDF,包括您要添加的任何文档,并添加到关于项目开发状态的标准报告中。

  • 发布管理和发布单独的输出 − Maven 将不需要额外的配置,就可以与源代码管理系统(如 Subversion 或 Git)集成,并可以基于某个标签管理项目的发布。它也可以将其发布到分发位置供其他项目使用。Maven 能够发布单独的输出,如 JAR,包含其他依赖和文档的归档,或者作为源代码发布。

  • 向后兼容性 − 您可以很轻松的从旧版本 Maven 的多个模块移植到 Maven 3 中。

  • 子项目使用父项目依赖时,正常情况子项目应该继承父项目依赖,无需使用版本号,

  • 并行构建 − 编译的速度能普遍提高20 - 50 %。

  • 更好的错误报告 − Maven 改进了错误报告,它为您提供了 Maven wiki 页面的链接,您可以点击链接查看错误的完整描述。

二、POM详解

POM(Project Object Model, 项目对象模型)是Maven工程的基本工作单元,是一个XML文件, 包含了项目的基本信息, 用于描述项目如何构建、声明项目依赖等。执行任务或目标时, Maven会从项目中寻找POM。它读取POM,获取所需的配置信息,然后执行目标。

POM中可以指定以下配置:

  • 项目依赖
  • 插件
  • 执行目标
  • 项目构建Profile
  • 版本信息
  • 项目开发者列表
  • 相关邮件列表等信息
    等等。

2.1、POM文件格式

POM文件的格式由Maven的XSD文件定义, 如[maven-4.0.0.xsd](http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd):



    
    
        
        good-java
        
        org.example
        
        1.0-SNAPSHOT
        
        
    
    
    4.0.0
    
    org.example
    
    good-java-spring
    
    jar
    
    1.0-SNAPSHOT
    
    good-java-spring
    
    http://www.baidu.com/dipper
    
    项目描述信息

    
    
        8
    

    
    
        
        
    

    
    
        
        jira
        
        http://jira.baidu.com/dipper
    

    
    
        
        ci
        
        http://127.0.0.1:8080/
        
        
            
            
                
                mail
                
                true
                
                true
                
                false
                
                false
                
                
test 2021 Demo [email protected] [email protected] [email protected] http:/hi.baidu.com/test/demo/dev/ dipper skyeye [email protected] Project Manager Architect demo http://hi.baidu.com/dipper No -5 none [email protected] http://www.baidu.com/none none Apache 2 http://www.baidu.com/dipper/LICENSE-2.0.txt repo A business-friendly OSS license scm:svn:http://svn.baidu.com/dipper/maven/dipper/dipper-maven2-trunk(dao-trunk) scm:svn:http://svn.baidu.com/dipper/maven/dipper/dao-trunk http://svn.baidu.com/dipper demo http://www.baidu.com/dipper prod true Windows XP Windows x86 5.1.2600 mavenVersion 2.0.3 /usr/local/test /usr/local/test /src/main/java /src/main/java /src/test/java /target /target/test org.example good-java-annotation 1.0-SNAPSHOT test-compile config true /profile/${profile.id} * *.bak /target ${artifactId} /profile/${profile.id} org.apache.maven.plugins maven-compiler-plugin 3.8.1 true default compile true test org.apache.maven.plugins maven-compiler-plugin 3.8.1 true org.apache.maven.plugins maven-compiler-plugin 3.8.1 true default compile true test org.apache.maven.plugins maven-compiler-plugin 3.8.1 true ../good-java-example true always warn default default http://192.168.1.169:9999/repository/ default org.apache.maven maven-artifact 3.8.1 jar test spring-core org.springframework true true /site org.apache.maven.plugins maven-compiler-plugin 3.8.1 true default true 1 true maven2 maven2 file://${basedir}/target/deploy default true maven2 maven2 Snapshot Repository scp://svn.baidu.com/dipper:/usr/local/maven-snapshot default dipper-site business api website scp://svn.baidu.com/dipper:/var/www/localhost/dipper-web none

2.2、POM 重要标签简介

  • project.parent: 父项目的坐标。
  • project.groupId: 项目的全球唯一标识符。
  • project.artifactId: 项目的标识符, 它和groupId一起唯一标识一个项目
  • project.version: 项目的版本号, 它和groupId、artifactId一起构成项目的三元组, 代表项目唯一的一个版本。
  • project.packaging: 项目的构建类型, 默认包括jar、war、ear、pom等, 但不是全部, 通过其他插件还可以构建其他的构建类型, 比如tar等等。
    -project.properties: 可以自定义元素, 在其他的元素中进行应用, 本质上是一个声明变量的地方, 比如jdk版本号之类的。
  • project.profiles: 针对项目不同运行环境声明不同的构建方式, 如果被激活, 会修改项目的构建方式。比如开发时一般会区分为dev、test、prod等环境,不同的环境之间默认一般会隔离,所以它的资源的加载方式都不一样, 就需要用profile分别定义, 用到哪个环境, 就激活哪个环境。它主要会影响project中默认定义的buildrepositoriespluginRepositoriesdependencyManagementdistributionManagementdependencies等元素。
  • project.build: 构建项目需要的信息, 主要包含构建项目的源文件路径、目标目录、资源文件目录、构建扩展、资源文件包含列表、插件列表、构建目标等等。
  • project.modules: 模块或子项目, 时构建的一部分。
  • project.repositories: 发现依赖的远程仓库列表。
  • project.pluginRepositories: 发现插件的远程仓库列表。
  • project.dependencies: 描述项目构建的所有依赖情况。
  • project.dependencyManagement: 继承自该项目的子项目的默认依赖信息, 如果子项目声明一个依赖某些信息未描述, 就会使用这里的依赖信息。
  • project.distributionManagement: 项目分发信息, 表示项目构建完成后发布的仓库位置。

2.3、POM 重要标签详解

1. dependency标签

       
            
            
            
            
            
            
            
            
            
                
                      
                      
                
            
        

dependency标签标识了项目依赖的某个组件的信息, 包含被依赖组件的唯一标识三元组groupIdartifactIdversion

type表示依赖的类型, 可选值和project.packaging类似, 默认是jar, 可以通过设置extensions构建新的类型。

scope表示依赖的范围, 主要包含:

  • test
    表示应用程序的正常使用不需要依赖,只在测试编译和执行阶段可用。此作用域不可传递。通常,此范围用于测试库,例如 JUnit 和 Mockito。

  • runtime
    表示被依赖项目无需参与项目的编译,但是会参与到项目的测试和运行。与compile相比,被依赖项目无需参与项目的编译。
    例如,在编译的时候我们不需要 JDBC API 的 jar 包,而在运行的时候我们才需要 JDBC 驱动包。

  • compile
    compile 是默认值,如果没有指定 scope 值,该元素的默认值为 compile。被依赖项目需要参与到当前项目的编译,测试,打包,运行等阶段。打包的时候通常会包含被依赖项目。

  • system
    system 元素与 provided 元素类似,但是被依赖项不会从 maven 仓库中查找,而是从本地系统中获取,systemPath 元素用于制定本地系统中 jar 文件的路径。

  • provided
    被依赖项目理论上可以参与编译、测试、运行等阶段,相当于compile,但是在打包阶段做了exclude的动作。
    例如, 如果我们在开发一个web 应用,在编译时我们需要依赖 servlet-api.jar,但是在运行时我们不需要该 jar 包,因为这个 jar 包已由应用服务器提供,此时我们需要使用 provided 进行范围修饰。

  • import: 该作用域只在dependencyManagement元素中生效, 可以代替parent继承。parent继承的方式存在的问题在于, 如果子module特别多, 需要将子module的依赖都在parent中声明, 这样子会造成parent中dependencyManagement特别庞大, 无法进行有效的分类。 这个时候采用import scope的方式就可以有效解决, 可以声明多个不同类型的pom, 在子mudule的dependencyManagement中按需引入即可。 import scope代替parent继承的方式:

org.exmaple
parent
1.0.0
pom

  
      
          com.test
          test1
          1.0.0
      
      
          org.junit
          junit
          0.0.1
          test
      
 

这样就可以在子module中引入了:

org.exmaple
mudule1
1.0.0
jar

  
      
          org.example
          parent
          1.0.0
          pom
          import
      




      
          com.test
          test1
      
      
          org.junit
          junit
      
 

exclusions 表示要排除的依赖。
systemPath 只有在以来范围是system的时候才生效,表示依赖在本地文件系统的位置。
optional 表示可选依赖, 默认值为false, 依赖具备传递性,比如A->B->C, 按照默认值, A也会依赖C, 如果B依赖C时声明了optional为true, 则A不会依赖C。如下:

// B项目POM声明:

   org.example
   C
   1.0.0
  true

classifier 表示依赖的分类器,classifier元素用来帮助定义构件输出的一些附属构件。附属构件与主构件对应,比如主构件是 kimi-app-2.0.0.jar 该项目可能还会通过使用一些插件生成 如 kimi-app-2.0.0-javadoc.jar 、 kimi-app-2.0.0-sources.jar 这样两个附属构件。这时候,javadoc,sources就是这两个附属构件的classifier,这样附属构件也就拥有了自己唯一的坐标。

maven中一般使用groupIdartifactIdversion来唯一标识一个组件, 但是有一些特殊的组件,具备更细粒度, 需要增加classifier来声明依赖, 否则会报错找不到jar包, 比如 JSON-lib:

image.png

这个时候就必须使用classifier属性指定了:


            net.sf.json-lib
            json-lib
            2.4
            jdk15 
        

2. build标签

    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    

finalName 表示构建目标文件的名称, 默认在${basedir}/target目录下, 一般使用project.artifactId

directory 表示构建目标文件的存放目录,默认是${basedir}/target。

sourceDirectory 表示项目源代码的目录, 默认是${basedir}/src/main/java。

scriptSourceDirectory 表示项目脚本的源代码的目录。大多数情况下构建时会被拷贝到目标目录下。

outputDirectory 表示构建目标中class文件的存放目录, 默认是${basedir}/target/classes。

testSourceDirectory 表示项目测试源代码的目录, 默认是${basedir}/src/test/java。

testOutputDirectory 表示构建目标中测试class文件的存放目录, 默认是${basedir}/target/test-classes。

resources 表示项目中资源文件的位置, 用于包含或排除某些资源文件。

         
            
                
                
                
                
                    
                
                
                    
                
            
        
  • resource: 一个与项目关联的资源文件的列表, 用来描述资源文件是什么和在哪里。

  • targetPath: 表示构建完后resource文件存放的位置,默认是basedir, 通常打包在jar包中的资源文件的目标目录是META-INF。

  • directory: 表示resource文件所在的目录, 通常是${basedir}/src/main/resources。

  • filtering: true/false, 表示构建时是否用元素和元素中列出的属性文件中定义的值替换掉资源文件中的同名的属性。 比如:

  
      Tom
  
  
   
        true
        /src/main/resources
   

假如/src/main/resources下有一个application.properties, 其中有一行:
username: ${username}
编译完成后, 就会变成:
username: Tom

  • includes: 表示包含哪些资源文件, 以*作为通配符。

  • excludes: 表示忽略哪些资源文件。

testResources: 表示项目中测试资源文件的位置, 用法和resources一致。

defaultGoal: 表示构建时执行的阶段, 默认是install, 即如果在命令行中执行mvn, 相当于执行mvn install。

filters: 定义.properties文件,包含一个properties列表,该列表会应用到支持filter的resources中。也就是说,定义在filter的文件中的name=value键值对,会在build时代替${name}值应用到resources中。* 它可以配合profile标签进行不同环境的隔离配置。

  
            /profiles/${profile.id}/*.properties
  

plugins: 表示构建的插件。


            
                
                
                
                
                    
                        
                        
                        
                        
                        

                        
                    
                
                
                
                
                
                
                
                
            
        
  • groupId: 代表插件的全球唯一ID, 默认org.apache.maven.plugins

  • artifactId: 代表插件的ID

  • version: 代表插件的版本号。

  • executions: 配置包含一组指示插件如何执行的属性:

    id : 执行器命名
    phase:标识执行的阶段
    goals:标识执行的目标或功能
    configuration:标识执行目标所需的配置文件

  • extensions: 标示是否扩展

  • goals: 标示执行的阶段

  • inherited: 标示是否继承

  • dependencies: 插件的依赖

  • configuration: 插件的自定义配置信息

extensions: 表示构建需要用到的一系列扩展, 具体目前不知道怎么用, TODO。

pluginManagement: 表示构建时插件的声明。 它与plugins区别与dependenciesdependencyManagement的区别一致。

3. profiles标签
profiles标签表示不同环境的maven配置, 比如仓库配置、依赖配置、插件配置、构建配置, 基本上覆盖了maven配置的重要几个方面。在开发过程中, 我们的项目往往会存在多个环境, 比如:开发环境、测试环境、预发环境、线上环境等, 往往不同环境数据源配置、日志配置等等不一样, 这样我们每次部署到不同的环境, 都需要修改配置进行构建打包, 来回修改很容易出错,并且浪费时间人力。
profiles标签就是为了解决以上问题而存在的, 可以看到profiles标签的定义如下:

   
       
           prod
           true
           
           
           
           
           
           
           
           
           
           
       
   

id: 表示不同环境的Profile的唯一ID。
activation: 表示Profile激活的方式, 可以根据jdk版本、操作系统版本、maven属性、文件存在或缺失等方式来激活。它的定义如下:

   
               true
               1.7
               
                   
                   
               
               
                   
                   
                   
                   
               
               
                   
                   
               
           
  • activeByDefault: 表示默认激活
  • jdk: 表示根据jdk版本激活。
  • os: 表示根据操作系统激活
  • property: 表示根据maven属性激活。
  • file: 表示根据文件存在不存在激活。

properties: 表示Profile自定义的属性, 可以定义通过, 通常用来其他地方引用, 比如表示环境变量等。

其他字段和POM文件中一级标签一致, 详见各个标签的使用方式。

激活方式

  • 根据环境自动激活, 如上所示根据jdk、os等激活。
  • 通过命令行参数激活, 如:mvn command -Pprofile, 就会激活对应profile。
  • 配置默认自动激活, 通过activeByDefault来设置。

使用方式
比如,我们有2个环境:开发环境(dev)和线上环境(prod), 它的配置如下:

    
          
                dev
                
                      true
                
                
                     dev
                
          

           
                prod
                
                     prod
                
          
    

    
         
            /profiles/${env}/*.properties       
        
        
            
                  /src/main/resources
                  true
            
        
    

这样子当我们选择不同的环境时, filters就会根据不同的环境加载不同的配置文件并且应用到资源文件中,替换同名的键值对, 比如替换jdbc的配置等等。

除过使用不同的配置, Profile还可以帮助在不同环境使用不同的maven仓库、发布仓库, 采用不同的构建过程,构建不同的包等等。

4. dependencyManagement标签
denpendencyManagement用来统一管理项目的依赖版本号, 确保各个子项目的依赖和版本一致,不用每个项目都单独声明依赖的版本号。当变更版本号时,只需要在父项目的denpendencyManagement中修改版本号, 子项目不需要任何修改; 如果子项目依赖于一个特殊的版本号, 只需要在自己的dependencies中修改即可。

 
        
            
            
        
    
  • dependencies: 描述项目的依赖信息, 见dependencies标签。

它与dependencies的区别:

  • denpendencies相对于dependencyManagement, 所有子项目dependencies声明的依赖如果没有单独声明版本号, 就会使用dependencyManagement中声明的版本号。

  • dependencyManagement只是声明依赖的版本号, 并不实际引入依赖, 因此子项目需要实际引入依赖。 dependencyManagement里只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

你可能感兴趣的:(Maven基础)