玩转微服务-基础篇-maven

第一节 maven 的概念

一. 介绍

Maven 是 Apache 软件基金会组织维护的一款自动化构建工具,专注服务于 Java 平台的项目构建和 依赖管理。将项目开发和管理过程抽象成一个项目对象模型(POM)。

下载地址:Maven – Download Apache Maven

二. 目录结构

玩转微服务-基础篇-maven_第1张图片

  • bin:该目录包含了mvn运行的脚本,这些脚本用来配置Java命令,准备好classpath和相关的Java系统属性,然后执行Java命令。
    其中mvn是基于UNIX平台的shell脚本,mvn.bat是基于Windows平台的bat脚本。在命令行输入任何一条mvn命令时,实际上就是在调用这些脚本。
    该目录还包含了mvnDebug和mvnDebug.bat两个文件,同样,前者是UNIX平台的shell脚本,后者是Windows平台的bat脚本。
  • boot:该目录只包含一个文件,以maven 3.0为例,该文件为plexus-classworlds-2.2.3.jar。plexus-classworlds是一个类加载器框架,相对于默认的java类加载器,它提供了更丰富的语法以方便配置,Maven使用该框架加载自己的类库。
  • conf:该目录包含了一个非常重要的文件settings.xml。直接修改该文件,就能在机器上全局地定制Maven的行为。一般情况下,我们更偏向于复制该文件至~/.m2/目录下(~表示用户目录),然后修改该文件,在用户范围定制Maven的行为。
  • lib:该目录包含了所有Maven运行时需要的Java类库,Maven本身是分模块开发的,因此用户能看到诸如maven-core-3.0.jar、maven-model-3.0.jar之类的文件。此外,这里还包含一些Maven用到的第三方依赖,如common-cli-1.2.jar、google-collection-1.0.jar等。对于Maven 2来说,该目录只包含一个如maven-2.2.1-uber.jar的文件,原本各为独立JAR文件的Maven模块和第三方类库都被拆解后重新合并到了这个JAR文件中。可以说,lib目录就是真正的Maven。

三. 环境配置

maven 的使用需要在系统中配置,如下环境变量,这些配置可以在:bin目录下的mvn文件中看到:

JAVA_HOME:

MAVEN_HOME

第二节 项目构建工具

1. Ant

Ant是第一个所谓的“现代构建工具”,用于自动化构建过程。它是用Java实现的,主要用于Java项目。Ant的第一个公开发行版是在2000年,它很快成为Java项目最流行的构建工具,这要归功于它的平台独立性(如Java),设置门槛低,并提供可重复的构建。后来,它还获得了接受插件的能力。

2. Maven

Maven于2004年首次发布,旨在改进开发人员在使用Ant和其他构建工具时遇到的一些问题。Maven最大的成就被认为是引入了项目结构约定、依赖关系管理和一个中心工件库Maven central。

​ Maven仍然使用XML来编写构建文件(pom.XML),但是结构非常不同,因为它变成了声明性的。现在,开发人员不必写下导致某些目标的所有命令,而是描述项目的结构(如果它与约定不同的话),Maven本身提供了程序员可以调用的可用目标。另外,Maven能够通过网络下载依赖项。

3. Gradle

Gradle是三个构建工具中最年轻的一个,它的开发人员试图将Ant的能力和灵活性与Maven的依赖关系管理和约定结合起来,以创建漂亮而闪亮的构建工具。经过几年的开发,GradleV1.0于2012年发布,并迅速开始流行起来。它发展得非常快,已经被一些大企业采用——例如,Gradle被选为谷歌Android操作系统的构建工具。

第三节 maven的优缺点

优点:

  • 对第三方依赖库进行统一的版本管理
  • 统一项目的目录结构
  • 统一软件构建阶段
  • 便于项目升级,无论是项目本身升级还是项目使用的依赖升级。
  • 有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,而不用自己去编译。
  • maven有很多插件,便于功能扩展,比如生产站点,自动发布版本等
  • 自动生成项目网站和报表

缺点:

  • maven是一个庞大的构建系统,学习难度大
  • maven采用约定优于配置的策略(convention over configuration),虽然上手容易,但是一旦出了问题,难于调试。
  • 由于需要下载,导入等,导致加载缓慢,或者出现错误,和不稳定
  • 缺少对Maven的文档描述(网上一大堆,但是没有标准)
  • 中央存储库中的元数据不佳
  • POM.xml做为项目元数据的来源,xml技术文件庞大,不便于理解和维护。

第四节 maven的基本命令

  • mvn archetype:generate :创建 Maven 项目
  • mvn compile :编译源代码
  • mvn test-compile :编译测试代码
  • mvn test : 运行应用程序中的单元测试
  • mvn site : 生成项目相关信息的网站
  • mvn clean :清除目标目录中的生成结果
  • mvn package : 依据项目生成 jar 文件
  • mvn install :在本地 Repository 中安装 jar
  • mvn deploy:将jar包发布到远程仓库

注意:运行Maven命令时一定要进入pom.xml文件所在的目录!

第五节 仓库

在maven世界中,任何一个依赖,插件或者项目构建的输出,都可以成为构件。
maven在某个位置统一存储所有Maven项目共享的构建,这个统一的位置就是仓库。
maven项目只需要声明这些依赖的坐标,在需要的时候(如:编译时)maven会自动根据坐标找到仓库中的构件,并使用他们。

为了实现重用,项目构建完毕后生成的构建也可以安装或部署到仓库中,供其他项目使用。

一. 仓库

玩转微服务-基础篇-maven_第2张图片

当maven根据坐标寻找构件的时候,它首先会查看本地仓库,如果本地仓库存在此构件,就直接使用。如果本地不存在此构件,或者需要查看是否有更新的构建版本,maven就会去远程仓库中寻找,发现需要的构件之后下载到本地仓库之后再使用。如果本地和远程都没有需要的构建maven就会报错。

中央仓库是maven自带的远程仓库,它包含了绝大部分开源的构建。在默认配置中,当本地仓库没有maven需要的构件的时候,他就会从中央仓库下载。

私服:私服是另一种特殊的远程仓库,为了节省时间和宽带。应该在局域网内架设一个私有的仓库服务器,用于代理所有外部的远程仓库。内部的项目还能部署到私服上供其他项目使用。

二. 私服构建

参考:Maven私服仓库配置-Nexus详解_nexus 仓库配置

第六节 maven的特性

一. 依赖管理

依赖管理系统 maven为java世界引入了一个新的依赖管理系统jar包管理jar升级时修改配置文件即可,在java世界中,可以用groupid,artifactid,version组成的Coordination(做标)唯一标识一个依赖。

任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是jar包,也可以是war包或者jar包。

①groupId:定义当前Maven项目隶属的实际项目–公司名称。

②artifactId:该元素定义实际项目中的一个Maven模块–项目名。推荐的做法是使用实际项目名称作为artifactId的前缀。比如:spring-bean,spring-webmvc等。

③version:该元素定义maven项目当前所处的版本。

玩转微服务-基础篇-maven_第3张图片

二. 多模块构建

多模块构建 项目复查时dao service controller 层分离将一个项目分解为多个模块已经是很通用的一种方式。

在maven中需要定义一个parent POM作为一组module的聚合POM,在该POM中可以标签来定义一组子模块,parent POM不会有什么实际构建产生。而parent POM中的build配置以及依赖配置都会自动继承给子module。

三. 一致的项目构建

一致的项目构建 主要解决了我们在idea中和eclipse中创建的项目,目录可能不一样,但是如果使用了maven后,我们创建的项目目录都是一样的。 Maven在设计之初的理念就是Conversion over configuration(约定大于配置) ,其制定了一套项目目录结构作为标准的java项目结构,解决不同ide带来的文件目录不一致问题。

玩转微服务-基础篇-maven_第4张图片

四. 一致的构建模型和插件机制

通过统一的pom.xml文件来配置tomcat、jetty等插件,非常方便。比如之前构建一个web项目还要各种配置tomcat服务器等的,就很麻烦。


	
	org.mortbay.jetty
	maven-jetty-plugin
	6.1.25
	
	10
	/test


第七节 maven的生命周期

一. 构建

构建就是以我们编写的 Java 代码、框架配置文件、国际化等其他资源文件、如:页面和图片等静态资源作为“原材料”,去“生产”出一个可以运行的项目的过程。

构建过程的几个主要环节

①清理:删除以前的编译结果,为重新编译做好准备。
②编译:将 Java 源程序编译为字节码文件。
③测试:针对项目中的关键点进行测试,确保项目在迭代开发过程中关键点的正确性。
④报告:在每一次测试后以标准的格式记录和展示测试结果。
⑤打包:将一个包含诸多文件的工程封装为一个压缩文件用于安装或部署。Java 工程对应 jar 包,Web 工程对应 war 包。
⑥安装:在 Maven 环境下特指将打包的结果——jar 包或 war 包安装到本地仓库中。
⑦部署:将打包的结果部署到远程仓库或将 war 包部署到服务器上运行。

二. 生命周期简介

Maven的生命周期是一个抽象的概念,并不具体指某个操作,是Maven经过长时间思考和分析后总结出来的。它包括了一个项目的清理、初始化、编译、测试、打包、集成测试、验证、部署和站点生成等一系列的构建流程。

但它仅仅是抽象而已,并不执行具体操作,它的具体操作是交给Maven的各种插件来实现,所以说生命周期插件是密不可分的。

三. maven的生命周期

Maven的生命周期并不像我们所想的是一条线,它实际上有3套相互独立的生命周期,分别是:cleandefaultsite

而这三套生命周期,又各自都有一些不同的阶段(phase),这些阶段就是生命周期中最细化的操作,当然它仍然是抽象概念,具体操作是给插件做的。

下面具体的说明这3个生命周期的各个阶段,注意是有顺序的,各个阶段之间的顺序也是如下的顺序

1. clean

用于清理项目,clean 生命周期包括以下 3 个阶段:

  1. pre-clean: 清理前的准备工作;
  2. clean:清理上一次构建的结果;
  3. post-clean:清理结束后需要完成的工作。

2. default

default 生命周期定义了项目真正构建时所需要的所有步骤,它是所有生命周期中最核心,最重要的部分.

各阶段如下表:

玩转微服务-基础篇-maven_第5张图片

3. site生命周期

site生命周期的目的是建立和发布项目站点,maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。

site 生命周期包含以下 4 个阶段:

  1. pre-site:准备阶段。在生成站点前所需要做的工作;
  2. site:生成站点阶段;
  3. post-site:结束阶段。生成站点结束后所需要做的工作;
  4. site-deploy:发布阶段。我们可以将上面生成的站点发布到对应服务器中。

四. 生命周期执行规则

每套生命周期包含一系列的构建阶段(phase),这些阶段是有顺序的,且后面的阶段依赖于前面的阶段。用户与 Maven 最直接的交互方式就是调用这些生命周期阶段。

以 clean 生命周期为例,它包含 pre-clean、clean 以及 post-clean 三个阶段,当用户调用 pre-clean 阶段时,则只有 pre-clean 阶段执行;当用户调用 clean 阶段时,pre-clean 和 clean 阶段都会执行。当用户调用 post-clean 阶段时,则 pre-clean、clean 以及 post-clean 三个阶段都会执行。

三套生命周期本身是相互独立的,用户可以只调用 clean 生命周期的某个阶段,也可以只调用 default 生命周期的某个阶段,而不会对其他生命周期造成任何影响。当然也可以同时调用两套生命周期的某个阶段。

通过将阶段名传递给 mvn 命令,就可以调用构建阶段,例如:
mvn clean,就是调用clean生命周期的clean阶段,当前项目的target目录会被清空。

如下图:
玩转微服务-基础篇-maven_第6张图片

第八节 maven的属性体系

一. maven 中 有六种类型的属性

1. 内置属性

maven 中内置的预定义,用户可以直接使用 常见于项目的根配置文件,这里说的是顶级根,如:

${basedir}表示项目根目录,即包含pom.xml文件的目录;

${version}表示项目版本;

${project.basedir}同${basedir};

${project.baseUri}表示项目文件地址;

${maven.build.timestamp}表示项目构件开始时间;

${maven.build.timestamp.format}表示属性${maven.build.timestamp}的展示格式,默认值为yyyyMMdd-HHmm,可自定义其格式,其类型可参考java.text.SimpleDateFormat。用法如下:
  
    yyyy-MM-dd HH:mm:ss
  

2. POM属性

pom 中对应元素的值

常用的pom属性值有:

${project.build.directory}表示主源码路径;

${project.build.sourceEncoding}表示主源码的编码格式;

${project.build.sourceDirectory}表示主源码路径;

${project.build.finalName}表示输出文件名称;

${project.version}表示项目版本,与${version}相同;

3. 自定义属性

在pom.xml文件的标签下定义的Maven属性



  

    xiaoming

  


在其他地方使用${my.pro}使用该属性值。

4. Settings属性

与pom属性同理,用户使用以settings.开头的属性引用settings.xml文件中的XML元素值)

${settings.localRepository}表示本地仓库的地址;

5. Java系统属性

所有Java系统属性都可以使用Maven属性引用,例如{user.home}指向了用户目录。可以通过命令行mvn help:system查看所有的Java系统属性。

在Java代码中引用Maven属性

在Java代码中,我们可以使用System.getProperty()方法来获取Maven属性的值。System.getProperty()方法接受一个字符串参数,该参数是要获取的属性的键。

例如,要获取在pom.xml中定义的java.version属性的值,可以使用以下代码:

String javaVersion = System.getProperty("java.version");
System.out.println("Java版本:" + javaVersion);

6. 环境变量属性

所有环境变量都可以使用以env.开头的Maven属性引用。例如${env.JAVA_HOME}指代了JAVA_HOME环境变量的值。也可以通过命令行mvn help:system查看所有环境变量。

二. 配置文件加载属性

1. 在pom中自定义属性


   jdbc:mysql://127.1.1.1:3306/ssm_db

2. jdbc.properties文件中引用属性

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=${jdbc.url}
jdbc.username=root
jdbc.password=root

3. 设置maven过滤文件范围

Maven在默认情况下是从当前项目的src\main\resources下读取文件进行打包。


    
        
        
            ${project.basedir}/src/main/resources
            
            true
        
    

module 项目方式时,可在顶级pom 下统一配置。

第九节 maven的版本管理

在我们jar包的版本定义中,有两个工程版本用的比较多:

  • SNAPSHOT(快照版本)

​ 1. 项目开发过程中临时输出的版本,称为快照版本

​ 2. 快照版本会随着开发的进展不断更新

  • RELEASE(发布版本)

​ 1. 项目开发到一定阶段里程碑后,向团队外部发布较为稳定的版本,这种版本所对应的构件文件是稳定的

​ 2. 即便进行功能的后续开发,也不会改变当前发布版本内容,这种版本称为发布版本

第十节 maven 的核心概念

一. POM文件的介绍

  
      
      
          
          
          
          
          
          
          
          
      
      
    4.0.0  
      
    asia.banseon  
      
    banseon-maven2  
      
    jar  
      
    1.0-SNAPSHOT  
      
    banseon-maven  
      
    http://www.baidu.com/banseon  
      
    A maven project to study maven.  
      
      
          
          
      
      
      
          
        jira  
          
        http://jira.xxxx.com/xxxx  
      
      
      
          
          
          
          
          
          
              
              
                  
                  
                  
                  
                  
                  
                  
                  
                  
                  
                  
                
Demo [email protected] [email protected] [email protected] http://localhost:8080/demo/dev/ HELLO WORLD youname [email protected] Project Manager Architect demo http://www.xxx.com/ No +8 Apache 2 http://www.xxxx.com/LICENSE-2.0.txt repo A business-friendly OSS license scm:svn:http://svn.xxxx.com/maven/xxxxx-maven2-trunk(dao-trunk) scm:svn:http://svn.xxxx.com/maven/dao-trunk http://svn.xxxxx.com/ demo http://www.xxxxxx.com/ ...... ...... Windows XP Windows x64 6.1.7100 mavenVersion 2.0.3 /usr/local/xxxx/xxxx-home/tomcat/maven-guide-zh-to-production/workspace/ /usr/local/xxxx/xxxx-home/tomcat/maven-guide-zh-to-production/workspace/ ...... ...... ...... ...... ...... ...... banseon-repository-proxy banseon-repository-proxy http://10.10.10.123:8080/repository/ default ...... org.apache.maven maven-artifact 3.8.1 jar test spring-core org.springframework true ...... xxx-maven2 xxx maven2 file://${basedir}/target/deploy xxx-maven2 xxx-maven2 Snapshot Repository scp://svn.xxxx.com/xxx:/usr/local/maven-snapshot banseon-site business api website scp://svn.baidu.com/xxx:/var/www/localhost/web

二.setting文件的介绍

参见:【精选】Maven的settings.xml配置详解_maven setting配置-CSDN博客

三.依赖

1. 类型

直接依赖和间接依赖

A依赖B,B依赖于C

A和B之间就是直接依赖;

A和C之间就是间接依赖;

依赖关系具有传递性。

依赖传递可能造成的问题

通过依赖传递关系,可以使依赖关系树迅速增长到一个很大的量级,但很有可能会出现依赖重复,依赖冲突等情况,Maven针对这些情况提供了如下功能进行处理:

  • 依赖范围(Dependency scope)
  • 依赖调解(Dependency mediation)
  • 可选依赖(Optional dependencies)
  • 排除依赖(Excluded dependencies)
  • 依赖管理(Dependency management)

2. 依赖的原则(依赖调解)

  • 路径最短者优先
  • 路径相同时先声明者优先(这里“声明”的先后顺序指的是dependency标签配置的先后顺序。)
  • 特殊优先,当资源配置了相同资源的不同版本,后配置的覆盖先配置的

3. 依赖的排除

A项目依赖于B项目,B项目中所依赖的jar包是compile范围;B项目中的依赖jar包就可以传递A项目中;

注意:scope定义了依赖的范围,默认是compile,即使不指定默认也是compile

使用exclusions进行排除,如:


 
    com.mqf.maven

    Hello

    0.0.1-SNAPSHOT

    compile

    

        

            commons-logging

            commons-logging

                                        

    
 

3. 依赖的范围

  • compile:默认。编译范围,编译,测试,运行都有效。参与打包,安装。
  • test:测试范围,只有在test范围下才能用,不参与打包,安装。
  • provided:编译和测试,不参与打包,安装。
  • runtime:运行,只参与运行。
  • system:废弃。系统。
  • import:废弃。引入。

主要从对主程序是否有效、对测试程序是否有效、是否参与打包与部署三个方面对比以上三种依赖范围:

玩转微服务-基础篇-maven_第7张图片

4. 依赖的传递

optional表示是否会传递依赖,有两个可填值(假如不声明optional标签,默认就是false):

  • false: 传递依赖
  • true:不传递依赖

特点:

  • 将依赖设置为true不仅代表着依赖不会传递,就连打包的时候都不会将该jar打包进去,一旦使用到调用该jar包的方法就会异常。
  • 在父工程设置optional为true,并不会影响子工程继承该依赖。
  • 不管是当前项目引用的,还是间接引用的,所有依赖jar包都存放在jar解压后的BOOT-INF下/jar目录下,只要这下面没有jar,那当前项目就不能用。

什么时候将optional设置为true?

谁用谁引入

四. 继承

多个子工程中依赖同样的jar包,但是采用test范围;由于test范围没有传递性;所以,每一个工程都需要对test范围的jar包进行单独依赖;

而如果希望修改多个工程中所依赖test范围的jar包版本,那么,一个一个项目去修改太麻烦,这时可以应用继承解决。

(1)定义一个父工程,父工程packaging必须是pom

pom

项目的打包类型:pom、jar、war

packing默认是jar类型,

pom ---------> 父类型都为pom类型

jar ---------> 普通项目打jar包,一般普通项目设置jar

war ---------> web项目一般都是打war包,web项目的话设置war

(2)在父工程中定义依赖的jar包,属于test范围:

pom
 
       
 
              
 
                     
 
                            junit
 
                            junit
 
                            4.0
 

 
                            test
 
                     
 
              
 

(3)在各个子工程中对父工程进行继承:



    com.mqf.maven

    MavenParent

    0.0.1-SNAPSHOT

    ../MavenParent/pom.xml


(4)在各个子工程中对父工程中的包进行依赖,但是,不需要配置版本号和范围(与父工程的版本号和范围一致)



    junit

    junit


(5)如果希望修改版本,只需要修改父工程中的依赖jar包版本就可以了,那么,各个子工程中的jar包版本就都变了

(6)一个子工程只能继承一个父工程.

第十一节 maven 的插件开发

一. 两种类型的插件

Maven 实际上是一个依赖插件执行的框架,它执行的每个任务实际上都由插件完成的。使用Maven打出来的包并不包含任何 Maven 插件,它们以独立构件的形式存在, 只有在 Maven 需要使用某个插件时,才会去仓库中下载。

如下表所示,Maven 提供了如下 2 种类型的插件:

玩转微服务-基础篇-maven_第8张图片

二. 调用插件有两种方式

插件目标: 对于 Maven 插件而言,为了提高代码的复用性,通常一个 Maven 插件能够实现多个功能,每一个功能都是一个插件目标,即 Maven 插件是插件目标的集合。我们可以把插件理解为一个类,而插件目标是类中的方法,调用插件目标就能实现对应的功能。

使用的两种方式:

  1. 引入到项目当中,然后将插件绑定到指定的生命周期,然后执行声明周期命令会自动调用该插件,例如:mvn clean、mvn install
  2. 通过如下命令可以直接调用插件。
    • 使用 Maven 命令执行插件的目标,语法如:mvn [插件名]:[目标名]
    • 例如,调用 maven-compiler-plugin 插件的 compile 目标,命令如:mvn compiler:compile(注意不能使用插件的全名,一定是缩写名,不然会报找不到插件)

三. 插件绑定

为了完成某个具体的构建任务,Maven 生命周期的阶段需要和 Maven 插件的目标相互绑定。例如,代码编译任务对应了default 生命周期的 compile 阶段,而 maven-compiler-plugin 插件的 compile 目标能够完成这个任务,因此将它们进行绑定就能达到代码编译的目的。

内置绑定

Maven 默认为一些核心的生命周期阶段绑定了插件目标,当用户调用这些阶段时,对应的插件目标就会自动执行相应的任务。

表中,default 生命周期中只列出了绑定了插件目标的阶段,它还有很多其他的阶段,但这些阶段默认没有绑定任何插件目标,因此它们也没有任何实际的行为。

玩转微服务-基础篇-maven_第9张图片

像这些内置绑定的插件我们也可以在项目当中去显示的声明然后修改配置,这时候内置绑定插件的默认配置将会被覆盖!

自定义绑定插件

除了内置绑定之外,用户也可以自己选择将某个插件目标绑定到 Maven 生命周期的某个阶段上,这种绑定方式就是自定义绑定。自定义绑定能够让 Maven 在构建过程中执行更多更丰富的任务。

例如,我们想要在 clean 生命周期的 clean 阶段中显示自定义文本信息,则只需要在项目的 POM 中 ,通过 build 元素的子元素 plugins,将 maven-antrun-plugin插件的run 目标绑定到 clean 阶段上,并使用该插件输出自定义文本信息即可。


	
        
        
              org.apache.maven.plugins
              maven-antrun-plugin
              3.0.0
              
                  
                    
                    custom clean
                    
                    clean
                    
                    
                    	run
                    
                    
                    
                      	
                    	
                        	
                        	
                      
                    
                  
              
          
	


以上配置中除了插件的坐标信息之外,还通过 executions 元素定义了一些执行配置。executions 下的每一个 executin 子元素都可以用来配置执行一个任务。execution 下各个元素含义如下:

  • id:任务的唯一标识。
  • phase:插件目标需要绑定的生命周期阶段。
  • goals:用于指定一组插件目标,其子元素 goal 用于指定一个插件目标。
  • configuration:该任务的配置,其子元素 tasks 用于指定该插件目标执行的任务。

当插件目标绑定到生命周期的不同阶段时,其执行顺序由生命周期阶段的先后顺序决定。如果多个目标绑定到同一个生命周期阶段,其执行顺序与插件声明顺序一致,先声明的先执行,后声明的后执行。

四. 插件获取

官网:https://maven.apache.org/plugins/index.html

五. 插件的开发

参考:

https://blog.51cto.com/u_6346066/7000656

https://zhuanlan.zhihu.com/p/596857284

你可能感兴趣的:(玩转微服务,微服务,maven,架构)