Maven实战计划

作者: 天下无敌强 | 来源:发表于2018-03-20 14:42 被阅读15次

    2018年3月20日14点29分

    前言

    • 接着上一篇JSON的文章,我又算是系统的学习了一遍Maven吧
    • 之前对Maven的使用中,只把它当作一个Jar包自动导入工具,对于它提供的很多其他功能几乎都不怎么用
    • 趁着恶补JSON知识的时候,顺手又来了一发《Maven实战》,算是提升码农搬砖效率的核心工程吧
    • 我记笔记只记录感觉是点睛之笔的语句,纯手敲,不粘贴,为的是在往完扫一本书的过程中记住这些散发着光亮的句子
    • 分享给大家当作看这本书的入口

    优秀的构建工具

    • maven的用途之一就是服务于构建,能够自动化构建过程,从清理,编译,测试到生成报告,再到打包和部署
    • 我们一直在不停地寻找避免重复的方法。设计的重复,编码的重复,文档的重复,当然还有构建的重复。Maven最大化地消除了构建的重复,抽象了构建生命周期,并且为大部分的构建提供了已经实现的插件

    不仅仅是构建工具

    • Maven还是一个依赖管理工具和项目信息管理工具
    • Maven也是一个约定大于配置的开源项目管理构建工具

    编写主代码

    • 项目主代码与测试代码不同,项目的主代码会被打包到最终的构件中,比如Jar包,War包(web归档包),而测试代码只在运行测试时用到
    • src/main/java中的Java类的包名应该与groupId和artifactId相吻合
    • mvn clean compile:Maven编译命令
    • scope为依赖范围,若依赖范围为test表示该依赖只对测试有效,在主代码中import Junit会导致编译报错

    典型单元测试

    1. 准备测试类及数据
    2. 执行要测试的行为
    3. 检查结果

    历史原因Maven核心插件compiler

    • Maven的核心插件之一——compiler只支持编译Java1.3,因此需要配置该插件使其支持Java高版本
    • mvn clean test:编译并运行测试

    打包

    • 项目最终的产出物-Jar|War
    • Maven默认打包类型为Jar
    • mvn clean package:编译并且打包

    如何让其他的Maven项目引用这个Jar

    • mvn clean install:编译并将项目安装到Maven本地仓库中

    maven-shade-plugin

    • maven默认打包生成的Jar包是不能够直接运行的,因为带有main方法的类信息不回添加到manifest中(打开jar文件中的META-INF/MANIFEST.MF文件,将无法看到Main-Class一行)
    • 为了生成可执行的Jar文件,需要借助maven-shade-plugin
    • 配置并重新运行mvn clean install,会生成两个Jar包,其中带有original-前缀的Jar包是原始Jar,依然为不可以运行的Jar包

    通过简单案例学习Maven

    需求用例

    注册账户
    主要场景:
        1,用户注册页面
        2,系统生成验证码图片
        3,用户输入想要的ID,Emial地址
        4,用于输入验证码
        ......
    扩展场景:
        4a,用户无法看清验证码,请求重新生成
            1.跳转到步骤2
    
    • 注册账户=>主要场景=>扩展场景
    • 设计简要的界面原型

    简要设计

    接口

    • 详细了解了这个简单账户注册服务的需求之后,就能勾勒出该系统对外的接口
    • 定义了系统核心的接口之后,基于功能分割和方便复用的原则,再对系统进一步进行划分。这里基于包名划分模块,这也是在Java中比较常见的做法
    • ...service...系统的核心,它封装了所有下层细节,对外暴露简单的接口。这实际是一个Facade模式

    坐标和依赖

    • Maven坐标为各种构件引入了秩序,任何一个构件必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,它们是groupId,artfactId,version,packaging,classifier

    依赖范围

    • compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围,此范围的Maven依赖,对于编译,测试,运行三种classpath都有效。典型的例子是spring-core,在编译,测试,运行的时候都需要使用该依赖
    • test:测试依赖范围。只对于测试classpath有效,典型为Junit,它只有在编译测试代码及运行测试的时候才需要
    • provided:已提供依赖范围,对于编译和测试classpath有效,但在运行的时候无效。典型是Servlet-api,编译和测试项目时需要该依赖,运行时由于容器提供,不需要Maven重复地引入一遍
    • runtime:运行时依赖范围,对于测试和运行classpath有效,但在编译主代码时无效。典型是JDBC驱动实现,项目主代码的编译只需要通过JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要实现上述接口的具体JDBC驱动

    传递性依赖

    • ...Maven会解析各个直接依赖的POM,将那些必要的间接依赖以传递性依赖的形式引入到当前的项目中
    • 当依赖传递性造成问题的时候,我们需要清楚地知道该依赖性传递是从哪条依赖路径引入的。Maven依赖调解(Dependency Mediation)的第一原则是:路径最近者优先。当两个路径相同时,第一声明者优先的第二原则就生效

    可选依赖

    • 使用<option></option>元素声明的依赖表示这个依赖不会被传递给依赖于此项目的项目
    • 在理想的情况下,是不应该使用可选依赖的,大部分情况下使用可选依赖的原因是某一个项目实现了多个特性,有悖于面向对象设计中的单一职责性原则

    排除依赖

    • 使用<exclusion></exclusion>排除依赖,声明的时候只需要groupId和artifactId,而不需要version元素就可以唯一定位依赖图中的某个依赖

    归类依赖

    • 通过在根元素下的<properties>下自定义属性值标签来实现对依赖版本号的统一管理

    优化依赖

    • mvn dependency:list:查看当前项目的已解析依赖
    • mvn dependency:tree:产看该项目的依赖树
    • mvn dependency:analyze分析当前项目的依赖

    仓库

    何为Maven仓库

    • 对于Maven来说,每个用户只有一个本地仓库,但可以配置很多远程仓库
    • 最原始的本地仓库是空的,Maven必须知道至少一个可用的远程仓库,才能在执行Maven命令的时候下载到需要的构件
    • 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,私服代理广域网上的远程仓库,供局域网内的Maven用户使用
    • 在repositories元素下,可以使用repository子元素声明一个或者多个远程仓库
    • 在Maven世界中,任何一个项目或者构建都必须有自己的版本,版本的值可能是1.0.0,1.3-alpha,2.1-SNAPSHOT

    快照版本和发布版本

    • 快照版本只应该在组织内部的项目或者模块间依赖使用,因为这时,组织对于这些快照版本的依赖具有完全的理解及控制权
    • 项目不应该依赖于任何组织外部的快照版本依赖,这样的依赖会造成潜在的危险

    生命周期和构建

    • Maven的生命周期就是为了所有的构建过程进行抽象和统一
    • Maven生命周期包含了项目的清理,初始化,编译,测试,打包,集成测试,验证,部署和站点等几乎所有的构建步骤。也就是说,几乎所有的项目的构建,杜能映射到这样一个生命周期上
    • Maven的生命周期是抽象的,这意味着生命周期本身不做任何实际的工作,在Maven的设计中,实际的任务(如编译源代码,执行测试用例集)都交由插件来完成。这种思想与设计模式中的模板方法(Template Method)非常相似
    • 模板方法模式在父类中定义算法的整体结构,子类可以通过实现或者重写父类的方法来控制实际的行为。这就既保证了算法有足够的可扩展性,又能够严格控制算法的整体结构

    三套生命周期

    • Maven拥有三条相互独立的生命周期,分别是clean,default,site
    • clean目的是清理项目
    • default目的是构建项目
    • site目的是建立项目站点
    • 每个生命周期包含一些阶段(phase),这些阶段是有顺序的,并且后面的阶段依赖于前面的阶段。用户与Maven最直接的交互方式就是调用这些生命周期阶段

    clean生命周期

    • pre-clean:执行一些清理前需要完成的工作
    • clean:清理上一次构建生成的文件
    • post-clean:执行一些清理后需要完成的工作

    default生命周期

    • default生命周期定义了真正构建时所需要执行的所有步骤,它是所有生命周期中最核心的部分
    • validate
    • initialize
    • generate-sources
    • process-sources:处理项目主资源文件,一般来说是对src/main/resources目录的内容进行变量替换等工作后,复制到项目输出的主classpath目录中
    • generate-resources
    • process-resources
    • compile编译项目的主源码。一般来说是对src/main/java目录下的Java文件至项目输出的主classpath目录中
    • process-classes
    • generate-test-sources
    • process-test-sources:处理项目测试资源文件
    • test-compile:编译项目测试代码
    • process-test-classes
    • test:使用单元测试框架运行测试,测试代码不会被打包或部署
    • prepare-package
    • package:接受编译好的代码,打包成可发布的格式,如JAR
    • pre-integration-test
    • integration-test
    • post-integration-test
    • verify
    • install:将包安装到Maven本地仓库,供本地其他Maven项目使用
    • deploy:将最终的包复制到远程仓库,供其他开发人员和Maven项目使用

    site生命周期

    • site生命周期的目的是建立和发布项目站点,Maven能够基于POM所包含的信息,自动生成一个友好的站点,方便团队交流和发布项目信息。该生命周期包含如下阶段:
    • pre-site:执行一些在生成项目站点之前需要完成的工作
    • site:生成项目站点文档
    • post-site:执行一些在生成项目站点之后需要完成的工作
    • site-deploy:将生成的项目站点发布到服务器上

    命令行与生命周期

    • 从命令行执行Maven任务的最主要方式就是调用Maven的生命周期阶段
    • 各个生命周期是相互独立的,而一个生命周期的阶段是有前后依赖关系的
    • mvn clean:该命令调用clean生命周期的clean阶段
    • mvn test
    • mvn clean install:该命令调用clean生命周期的阶段和default生命周期的install阶段,在执行真正的项目构建之前,清理项目是一个很好的实践

    聚合和继承

    • 为了解决软件的复杂性问题,通过各种方式对软件划分模块,以得到更清晰的设计以及更高的重用性。当把Maven应用到实际项目中时候,也需要将项目划分成不同的模块
    • Maven的聚合特性能够把项目的各个模块聚合在一起构建
    • Maven的继承特性则能帮助抽取各模块相同的依赖和插件等配置,在简化POM的同时,还能促进各个模块配置的一致性

    使用Web自动测试工具测试

    • 可以用单元测试覆盖的代码就不应该依赖于Web页面测试
    • Web页面测试应该仅限于页面的层次,如JSP,CSS,JavaScript修改,其他代码测试修改(如数据访问),请编写单元测试

    版本管理

    • 一个健康的项目通常有一个长期的,合理的版本演变过程
    • 理想的发布版本应当对应了项目某个时刻比较稳定的状态,包括源代码的状态以及构建的状态,应当满足如下条件

    发布版本应当满足的条件

    1. 所有自动化测试应当全部通过
    2. 项目没有配置任何快照版本的依赖
    3. 项目没有配置任何快照版本的插件
    4. 项目所包含的代码已经全部提交到版本控制系统中

    Maven版本号约定

    <主版本>.<次版本>.<增量版本>-<里程碑版本>
    
    • 主版本表示项目的重大架构变更
    • 次版本表示较大范围内的功能增加和变化
    • 增量版本一般为重大Bug的修复
    • 里程碑版本,顾名思义,这往往指某一个版本的里程碑

    灵活的构建

    • 一个优秀的构建系统必须足够灵活,它应该能让项目在不同的环境下都能成功地构建
    • Maven三个构建特性:属性,Profile,资源过滤

    常用双子星属性

    • ${basedir}表示项目根目录
    • ${version}表示项目版本

    POM属性

    • 用户可以使用该类属性引用POM文件中对应元素的值
    • ${project.artifactId}
    • ${project.build.sourceDirectory}:项目的主源码目录src/main/java
    • ${project.build.directory}:项目构建输出目录,默认为target

    相关文章

      网友评论

        本文标题:Maven实战计划

        本文链接:https://www.haomeiwen.com/subject/gpcbqftx.html