前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从青铜到王者,Maven全了解

从青铜到王者,Maven全了解

原创
作者头像
香菜聊游戏
修改2021-06-01 10:08:03
4500
修改2021-06-01 10:08:03
举报
文章被收录于专栏:香菜聊游戏香菜聊游戏

  Maven是每个Java程序都会遇到的包管理工具,今天整理一下Maven的相关知识,从青铜到王者,一文全了解

1、maven是什么,为什么存在?项目结构是什么样子,怎么定位jar

官方网站说了好多,整的多复杂一样,简单说:maven是一个管理包的工具。

Maven 存在的必要性是什么呐?想想开源的jar包如此之多,版本又如此之多,在没有Maven之前,我们管理jar包全部都是下载之后创建一个lib的文件夹,然后项目进行引用,在其他的项目成员需要修改一个jar的时候需要到处拷贝,在部署的时候也很麻烦,问题存在就要解决,因此出现了Maven,统一管理,统一的仓库,只需要配置是要哪个版本的包,直接下载就够了,不用拷贝,是不是很方便。

现在大的问题解决了,怎么定位一个jar包呐?

图片
图片

2、Idea 的操作

1.新建maven项目

File ->新建->project

图片
图片

    勾选从原型(模板)创建,选择maven-archetype-qiuckstart

图片
图片

填入项目的名字,和groupId (公司域名反过来,如com.alibaba)

图片
图片

选择本地仓库的位置,和自定义的setting配置

图片
图片

一路finish,然后等待idea 创建模板项目就好了。

2.配置仓库

Maven 仓库有三种类型:

  • 本地(local)
  • 中央(central)
  • 远程(remote)

当我们执行 Maven 构建命令时,Maven 开始按照以下顺序查找依赖的库

  • 步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
  • 步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
  • 步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
  • 步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。

阿里云仓库配置:

代码语言:javascript
复制
   <repositories>
       <repository>
           <id>central</id>
           <name>aliyun maven</name>
           <url>https://maven.aliyun.com/repository/public/</url>
           <layout>default</layout>
           <!-- 是否开启发布版构件下载 -->
           <releases>
               <enabled>true</enabled>
           </releases>
           <!-- 是否开启快照版构件下载 -->
           <snapshots>
               <enabled>false</enabled>
           </snapshots>
       </repository>
   </repositories>
3.添加依赖,添加fastjson的依赖

    举个例子:

代码语言:javascript
复制
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>fastjson</artifactId>
       </dependency>
4.打包项目
图片
图片

4、Maven坐标主要组成

  • groupId:组织标识(包名),一般常用公司域名的反序,比如com.alibaba
  • artifactId:项目名称,项目的具体名称
  • version:项目的当前版本 ,一般版本号为 大版本.小版本.小版本序号
  • packaging:项目的打包方式,最为常见的jar和war两种

5、maven生命周期

5.1 名词解释
  • lifecycle:生命周期,这是maven最高级别的的控制单元,它是一系列的phase组成,也就是说,一个生命周期,就是一个大任务的总称,不管它里面分成多少个子任务,反正就是运行一个lifecycle,就是交待了一个任务,运行完后,就得到了一个结果,中间的过程,是phase完成的,自己可以定义自己的lifecycle,包含自己想要的phase
  • phase:可以理解为任务单元,lifecycle是总任务,phase就是总任务分出来的一个个子任务,但是这些子任务是被规格化的,它可以同时被多个lifecycle所包含,一个lifecycle可以包含任意个phase,phase的执行是按顺序的,一个phase可以绑定很多个goal,至少为一个,没有goal的phase是没有意义的
  • goal: 这是执行任务的最小单元,它可以绑定到任意个phase中,一个phase有一个或多个goal,goal也是按顺序执行的,一个phase被执行时,绑定到phase里的goal会按绑定的时间被顺序执行,不管phase己经绑定了多少个goal,你自己定义的goal都可以继续绑到phase中
  • mojo: lifecycle与phase与goal都是概念上的东西,mojo才是做具体事情的,可以简单理解mojo为goal的实现类,它继承于AbstractMojo,有一个execute方法,goal等的定义都是通过在mojo里定义一些注释的anotation来实现的,maven会在打包时,自动根据这些anotation生成一些xml文件,放在plugin的jar包里

可以通俗理解为lifecyle 是一个公司,phrase 是具体的部门,goal 是一个项目,Mojo 是项目内部的人,其他的都是管理层级,具体的执行还是人。

5.2 生命周期
图片
图片
5.3 goal 的概念

一个goal是独立的,它可以被绑定到多个phase中去,也可以一个phase都没有。如果一个goal没有被绑定到任何一个lifecycle,它仍然可以直接被调用,而不是被lifecycle调用。

因此可以这样理解phase与goal的关系:

  1. phase其实就是goal的容器。实际被执行的都是goal。phase被执行时,实际执行的都是被绑定到该phase的goal。
  2. goal与goal之间是独立的。因此单独执行一个goal不会导致其他goal被执行。

goal可以通俗理解为一个项目。

5.4 生命周期和phase的关系

  clean生命周期每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。比如,运行mvn clean ,这个的clean是Clean生命周期的一个阶段。有Clean生命周期,也有clean阶段。Clean生命周期一共包含了三个阶段:

  1. pre-clean 执行一些需要在clean之前完成的工作
  2. clean 移除所有上一次构建生成的文件
  3. post-clean 执行一些需要在clean之后立刻完成的工作

  "mvn clean" 中的clean就是上面的clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,"mvn clean"等同于 mvn pre-clean clean ,如果我们运行 mvn post-clean ,那么 pre-clean,clean 都会被运行。这是Maven很重要的一个规则,可以大大简化命令行的输入

执行phase实际执行的是goal。如果一个phase没有绑定goal,那这个phase就不会被执行。

代码语言:javascript
复制
<plugin>
  <groupId>com.mycompany.example</groupId>
  <artifactId>display-maven-plugin</artifactId>
  <version>1.0</version>
  <executions>
    <execution>
      <phase>process-test-resources</phase>
      <goals>
        <goal>time</goal>
      </goals>
    </execution>
  </executions>
</plugin>

一个生命周期包含一些列的步骤,当执行生命周期的时候,会把所有的步骤执行一次

官方文档:

http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

http://maven.apache.org/ref/3.3.9/maven-core/lifecycles.html

6、idea maven的配置

POM 中可以指定以下配置:

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

具体的配置可以参考fastjson 的配置:

https://github.com/alibaba/fastjson/blob/master/pom.xml

7、POM有2个很重要的关系:聚合、继承

一、聚合

  如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合

1.聚合配置代码

代码语言:javascript
复制
 <modules>
       <module>模块一</module>
       <module>模块二</module>
       <module>模块三</module>
 </modules>

  例如:对项目的Hello、HelloFriend、MakeFriends这三个模块进行聚合

代码语言:javascript
复制
 <modules>
       <module>../Hello</module>  
       <module>../HelloFriend</module>        
       <module>../MakeFriends</module>
 </modules>

  其中module的路径为相对路径。

二、继承

  继承为了消除重复的配置,我们把很多相同的配置提取出来,例如:grouptId,version,相同的依赖包等。

继承配置代码:

代码语言:javascript
复制
<parent>  
         <groupId>me.gacl.maven</groupId>
         <artifactId>ParentProject</artifactId>
         <version>0.0.1-SNAPSHOT</version>
         <relativePath>../ParentProject/pom.xml</relativePath>  
</parent>

Idea 中可以新建一个maven项目,然后删光文件夹,只留一个pom.xml,然后添加模块,选择继承。

图片
图片

8.Maven 中的 profile

  • Maven 中有一个概念叫做:profile,它主要是为了解决不同环境所需的不同变量、配置等问题。比如我们内网开发的数据库配置,端口配置等是和生产环境不同的,这个时候就需要区分。
  • 有了 profile,可以根据激活的条件,启动不同条件下的配置信息。
  • profile 是可以有多个的,也可以同时激活多个 profile,方便自由组合。
代码语言:javascript
复制
<profiles>
       <profile>
           <!--不同环境Profile的唯一id-->
           <!--开发环境-->
           <id>dev</id>
           <properties>
               <!--profiles.active是自定义的字段(名字随便起),自定义字段可以有多个-->
               <profiles.active>dev</profiles.active>
           </properties>
       </profile>
       <profile>
           <!--线上环境-->
           <id>prod</id>
           <properties>
               <profiles.active>prod</profiles.active>
           </properties>
           <activation>
               <activeByDefault>true</activeByDefault>
           </activation>
       </profile>
   </profiles>
图片
图片

Idea 中会显示配置的两个profile ,可以选择激活

图片
图片

pom文件里的配置为

代码语言:javascript
复制
<build>
       <resources>
           <resource>
               <directory>src/main/resources/</directory>
               <!--先排除掉两个文件夹-->
               <excludes>
                   <exclude>dev/*</exclude>
                   <exclude>prod/*</exclude>
               </excludes>
               <includes>
                   <!--如果有其他定义通用文件,需要包含进来-->
                   <!--<include>messages/*</include>-->
               </includes>
           </resource>
           <resource>
               <!--这里是关键!根据不同的环境,把对应文件夹里的配置文件打包-->
               <directory>src/main/resources/${profiles.active}</directory>
           </resource>
       </resources>
   </build>

  <profiles>
       <profile>
           <!--不同环境Profile的唯一id-->
           <!--开发环境-->
           <id>dev</id>
           <properties>
               <!--profiles.active是自定义的字段(名字随便起),自定义字段可以有多个-->
               <profiles.active>dev</profiles.active>
           </properties>
       </profile>
       <profile>
           <!--线上环境-->
           <id>prod</id>
           <properties>
               <profiles.active>prod</profiles.active>
           </properties>
           <activation>
               <activeByDefault>true</activeByDefault>
           </activation>
       </profile>
   </profiles>

9、maven 插件

  1. Maven的核心仅仅定义了抽象的生命周期,具体的任务都是交由插件完成的。
  2. 每个插件都能实现多个功能,每个功能就是一个插件目标goal。
  3. Maven的生命周期与插件目标相互绑定,以完成某个具体的构建任务,例如compile就是插件maven-compiler-plugin的一个插件目标。

常用插件:

代码语言:javascript
复制
maven-antrun-plugin

maven-archetype-plugin

maven-assembly-plugin

maven-dependency-plugin

maven-enforcer-plugin

maven-help-plugin

maven-release-plugin

maven-resources-plugin

maven-surefire-plugin

build-helper-maven-plugin

exec-maven-plugin

jetty-maven-plugin

versions-maven-plugin

10 环境变量

代码语言:javascript
复制
${basedir}表示项目根目录,即包含pom.xml文件的目录;

${version}表示项目版本;

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

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

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

${maven.build.timestamp.format}表示属性${maven.build.timestamp}的展示格式,默认值为yyyyMMdd-HHmm,可自定义其格式,其类型可参考java.text.SimpleDateFormat。
${project.build.directory}表示主源码路径;

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

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

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

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

${project.xxx} 当前pom文件的任意节点的内容
${env.xxx} 获取系统环境变量。
${settings.xxx} 指代了settings.xml中对应元素的值。

11、Maven 依赖冲突的2个方法

1.统一版本

使用dependencyManagement 进行版本锁定,dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致。

如果我们项目中只想使用spring core 5.2.0的包,pom.xml可以改为如下

代码语言:javascript
复制
<dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework</groupId>
               <artifactId>spring-core</artifactId>
               <version>5.2.0.RELEASE</version>
           </dependency>
       </dependencies>
   </dependencyManagement>

   <dependencies>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>5.2.7.RELEASE</version>
       </dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-aop</artifactId>
           <version>5.2.0.RELEASE</version>
       </dependency>

   </dependencies>

2.排除依赖

依赖查找的两个原则:

使用路径近者优先原则:直接依赖级别高于传递依赖。

使用第一声明者优先原则:谁先定义的就用谁的传递依赖,即在pom.xml文件自上而下,先声明的jar坐标,就先引用该jar的传递依赖。

Idea 可以安装maven helper插件,解决冲突。

maven helper插件安装成功,点开pom.xml会发现多了一个Dependency Analyzer视图,如下上面按钮的图标含义如下

  • Conflicts(查看冲突)
  • All Dependencies as List(列表形式查看所有依赖)
  • All Dependencies as Tree(树形式查看所有依赖)

上图说明有3个jar存在冲突,点击冲突的jar,可以查看和哪个jar产生冲突,如下图

图片
图片

点开pom.xml,切换到Dependency Analyzer视图,选择All Dependencies as Tree,点击要排除的jar,右键会出现Execlude选项,如下

图片
图片

总结:

    Maven是开发中常用的工具,很重要,所以尽可能的掌握。

原创打字不容易,点赞,转发,关注三连,关注我公众号:【香菜聊游戏】有更多福利

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、maven是什么,为什么存在?项目结构是什么样子,怎么定位jar
  • 2、Idea 的操作
    • 1.新建maven项目
      • 2.配置仓库
        • 3.添加依赖,添加fastjson的依赖
          • 4.打包项目
          • 4、Maven坐标主要组成
          • 5、maven生命周期
            • 5.1 名词解释
              • 5.2 生命周期
                • 5.3 goal 的概念
                  • 5.4 生命周期和phase的关系
                  • 6、idea maven的配置
                  • 7、POM有2个很重要的关系:聚合、继承
                    • 一、聚合
                      • 二、继承
                      • 8.Maven 中的 profile
                      • 9、maven 插件
                      • 10 环境变量
                      • 11、Maven 依赖冲突的2个方法
                      • 总结:
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档