当前位置: 首页 > news >正文

你真的了解Maven吗?

(一)什么是Maven

Maven是Apache下的一个开源项目,目前可以用于构建和管理任何基于 Java 的项目的工具,让 Java 开发人员的日常工作更轻松。为了让开发人员更轻松,Maven做到了以下几点:

简化构建过程

提供了标准的、跨平台的自动化项目构建方式。Maven 并没有消除了解底层机制的需要,但是Maven确实让Java项目的构建变得更简单了。

提供统一的构建系统

Maven 使用其项目对象模型 (POM) 和一组插件来构建项目。一旦你熟悉了一个 Maven 项目,你就会知道所有的 Maven 项目是如何构建的。这在浏览开源项目和其他项目时会十分节省时间。

依赖管理

更加方便快捷地管理项目依赖的Jar包,同时可避免不同Jar包版本之间的冲突。

(二)Maven中的基础概念

仓库

仓库中存储了各种Jar包,Maven本身维护了一个包含全球大部分Jar包的仓库,称为中央仓库,可以在Maven提供的网站中搜索需要的Jar包:https://search.maven.org/。

每个人的本地也会有一个Maven仓库称为本地仓库,当我们使用一些Jar包时,需要先从中央仓库拉取Jar包到本地仓库,再从本地仓库拉取到项目中。

一些公司为了更快的访问速度以及方便将本公司的Jar包给员工使用,会搭建
Maven私服仓库,私服仓库会定期读取中央仓库,也会维护自身的Jar包在里面。

坐标

坐标是用来描述maven中每个资源的位置,坐标主要通过三个标签来定位到一个资源:比如我上传到中仓仓库的一个Jar包:

<dependency>
  <groupId>io.github.oliverliy</groupId>
  <artifactId>fast-sso-client</artifactId>
  <version>0.0.2</version>  
</dependency>

groupId:当前Jar包所属的机构,通常采用域名反写的方式,我这里是使用了github的域名。

artifactId:当前项目名称,我上传的这个项目名称就叫fast-sso-client。

version:定义当前的项目版本。

(三)Maven中的依赖管理

依赖是指一个项目所需的所有Jar包,在Maven中,统一将依赖放在dependencies下的dependency中。

<dependencies>
    <dependency>
      <groupId>io.github.oliverliy</groupId>
      <artifactId>fast-sso-client</artifactId>
      <version>0.0.2</version>
    </dependency>
</dependencies>

4.1 依赖传递

Maven中的依赖具备依赖传递的功能,比如在上面这个例子中引入了fast-sso-client这个依赖包,而fast-sso-client又会依赖其他的Jar包,就如下图所示:

直接引入的依赖包称为直接依赖,被直接依赖带入项目的其他依赖包称为间接依赖。

4.2 依赖冲突

当一个项目中同时存在多个版本的依赖包时,就会出现依赖冲突的情况。Maven项目在选择依赖包时,会采取就近原则的方式。配置顺序靠前的会替换配置顺序靠后的,配置层级浅的会替换配置层级深的。

在这里插入图片描述

以上面这个依赖关系图来看,最终项目A依赖的Jar包分别是:1.0版本的依赖A和1.0版本的依赖B。

4.3 依赖冲突

如果想在项目中排除掉依赖包中的某个传递依赖时,可以通过exclude排除掉依赖。被排除的依赖无需指定版本。

<dependency>
    <groupId>io.github.oliverliy</groupId>
    <artifactId>fast-sso-client</artifactId>
    <version>0.0.2</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

4.4 依赖范围

在依赖中可设置scope标签代表依赖的范围,可选参数有compile、provided、runtime、test,默认是compile。

<dependency>
    <groupId>io.github.oliverliy</groupId>
    <artifactId>fast-sso-client</artifactId>
    <version>0.0.2</version>
    <scope>compile</scope>
</dependency>

当scope为compile时,项目代码(main文件夹范围内)、测试代码(test文件夹范围内)和package打包指令下这个依赖都有效,绝大部分的Jar包都是compile。

当scope为test时,只有测试代码范围内是有效的,最常见的就是junit包,只会在测试代码里使用就可以将scope定为test。

当scope为provided时,表示在项目代码范围和测试代码范围内有效,但是不会被打包,常见的是servlet-api这个依赖,原因是如果将servlet-api打入jar包,就会和一些web容器里的servlet依赖冲突。

当scope为runtime时,主会在打包时生效,最常见的就是jdbc的驱动依赖,我们写jdbc代码时,驱动都是用全限定名的字符串指定的,因此在项目代码中根本就不会用到,只要在打包时把这个jar包打进去就行。

(四)Maven的生命周期

maven的生命周期很长,但是我们只需要关注最常用的那些就可以了,在IDEA的maven插件中,就可以看到常用的生命周期:

从上往下代表了Maven的生命周期,当执行某个命令时,它往前的生命周期命令都会被执行,比如执行compile,那么会依次执行clean、validate、compile。

有的时候我们在打包时希望可以跳过测试,那么可以通过命令

mvn install -D skipTests

或者在IDEA中直接通过闪电符号快速跳过

其中比较常用的几个命令:clean会清除掉前一次的打包记录。compile会编译项目的源代码、package会将编译后的代码打包成文件,比如war包、jar包。install会安装项目包到本地仓库,这样其他项目就可以使用该项目包。deploy可以将项目包发送到远程仓库中。

(五)Maven中的插件

插件和生命周期的每个阶段绑定,maven中的每个生命周期上都绑定有预设的功能,通过插件可以实现更多的自定义功能。比较常用的是打包插件,比如我现在想要打一个源码包,就可以在maven的官网找到对应的插件:

然后放到pom文件中去:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                    <phase>test</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

其中groupId、artifactId、version就不用介绍了,executions表示插件执行的参数,其中goals对应官网中的goals

每个插件都有自己的goals,比如这个打源码包的插件,当选择jar时,就表示将源码文件打包到一个jar文件中去。
phase表示在哪个生命周期执行,选择test就表示在test这个生命周期内执行。

(六)Maven中的模块聚合

为了更方便地管理整个项目的版本,往往会在父项目中将各个模块都会用到的依赖控制起来,防止每个模块用不同版本的依赖包,这个时候就需要用到<dependencyManagement>
首先在父工程中定义依赖包:

<dependencyManagement>
    <dependencies>
        <artifactId></artifactId>
        <groupId></groupId>
        <version></version>
    </dependencies>
</dependencyManagement>

接着在每个子项目上用parent标签指出依赖的父工程是谁:

<parent>
    <artifactId></artifactId>
    <groupId></groupId>
    <version></version>
</parent>

这样子工程就可以使用父工程里引入的依赖包了。

同样的方式可以管理插件,pluginManagement起到了和dependencyManagement一样的能力。

(七)Maven的版本管理

在依赖包中,经常可以看到有些版本会带上SNAPSHOT,有些就不会带。这就是Maven的不同版本所附有的标识。

SNAPSHOT代表快照版本,也就是测试阶段版本,这个版本会随着开发进度不断更新。

RELEASE是发布版本,当项目开发达到某个相对稳定的阶段时,就可以对外发布相对稳定的版本,这种版本就是发布版本。

但是在maven库中,也能发现有些开源jar包命名并非是SNAPSHOT和RELEASE,这些还是按照每个企业自己的定义即可。

相关文章:

  • 【转】Xcode常用快捷键与技巧分享
  • 【设计模式】快速理解观察者模式,原来它还有这么多其他名字
  • linux实际应用小技巧
  • 时间类有多复杂,JDK竟设计了三版
  • AOP之PostSharp5-LocationInterceptionAspect
  • 如何快速学习一门新技术
  • 模拟实现部分库函数(strcpy,strcmp,strcat,strstr,memcpy,memmove,memset)
  • 组成原理(一):计算机是如何组成的
  • JDK9相比于JDK8,究竟变强了多少
  • Hive之分区(Partitions)和桶(Buckets)
  • 列式存储?OLAP?ClickHouse究竟是何方神圣
  • 分享Open-E DSS V7 应用系列十篇!
  • 基于SpringBoot和BootStrap的全栈论坛网站(附上源码)
  • 我的Java全系列技术博客
  • 闲着无聊造个轮子,开源一个可快速接入的分布式SSO系统
  • 收藏网友的 源程序下载网
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • ES10 特性的完整指南
  • Go 语言编译器的 //go: 详解
  • Java-详解HashMap
  • k8s 面向应用开发者的基础命令
  • mongo索引构建
  • Netty源码解析1-Buffer
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • passportjs 源码分析
  • Phpstorm怎样批量删除空行?
  • React-生命周期杂记
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • TCP拥塞控制
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • Vue组件定义
  • 初识MongoDB分片
  • 判断客户端类型,Android,iOS,PC
  • 山寨一个 Promise
  • 无服务器化是企业 IT 架构的未来吗?
  • 学习ES6 变量的解构赋值
  • 一个项目push到多个远程Git仓库
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • #DBA杂记1
  • #预处理和函数的对比以及条件编译
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (9)目标检测_SSD的原理
  • (k8s中)docker netty OOM问题记录
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (简单) HDU 2612 Find a way,BFS。
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (转)ObjectiveC 深浅拷贝学习
  • (转)shell调试方法
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)一些感悟
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .net framework4与其client profile版本的区别
  • .Net 垃圾回收机制原理(二)
  • .net 受管制代码