Maven工具的超级详解(附带容器概念的通俗讲解)

概念

众所周知,Maven是一款自动构建化工具,那么什么是构建呢?

首先,补充一下,Maven是构建化工具,只服务于java平台。它本身是java写的。构建并不等同于创建。它是以java源文件、框架配置文件、JSP、HTML、图片等资源为“原材料”去生产一个可以运行的项目的过程。(这个生产的过程就称作为构建)

注意:它是一个过程,而不是一种操作。

构建这个过程有三个要点:编译、部署、搭建

编译:java文件通过编译变成class文件(也称字节码文件)然后交给JVM去执行

部署:一个项目最终运行的并不是它本身,而是它的编译结果(编译结果才能在服务器上执行)

搭建:指的是环境的搭建(例如javaweb项目要有tomcat的运行环境,Maevn工程中也要用到Maven的pom.xml中所引入的环境依赖)

Maven的常用命令

①clean(mvn clean)

意为清理,清理target资源包中的全部内容,包括target这个包也会被清理掉

②compile(mvn compile)

意为编译,编辑程序文件,把相应的程序文件编译为字节码文件(class文件),方便执行,编译后的文件会放到Maven项目的target资源包中的classes目录下

③test(mvn test)

意为测试,编译测试程序

④package(mvn package)

意为包装/打包,将项目打包形成一个该项目的jar包或war包(取决于你的打包方式),这个包可放在Tomcat中的webapp中运行,运行后会加载出该项目中相应的包与文件

⑤install(mvn install)

意为安装,操作基本与package相同,不同的是,它打包后还会安装到你的Maven本地仓库中

⑥deploy(mvn deploy)

意为部署,操作基本与install相同,不同的是,它除了安装到Maven本地仓库中,还会安装到Maven的中心仓库。

package、install、deploy三者的关系图:

常用的依赖范围(scope)

compile依赖范围(scope的默认值是compile)

对主程序是否有效:有效

对测试程序是否有效:有效

是否参与打包:参与

是否参与部署:参与

test依赖范围

对主程序是否有效:无效

对测试程序是否有效:有效

是否参与打包:不参与

是否参与部署:不参与

provided依赖范围(意为这个包是从容器中提供的)

对主程序是否有效:有效

对测试程序是否有效:有效

是否参与打包:不参与

是否参与部署:不参与

那么,看到provided,不禁让人思考一个问题,什么是容器?

        参考了一些其他文章之后,我的个人理解是:容器指的是包含了完整的运行环境,应用所需的全部依赖和类库以及其他的class文件和配置文件等的一个镜像包。它封装了运行程序所必须的相关细节,比如一个程序中,有很多依赖关系,那么运行这些程序时,会先在容器中寻找这些依赖,如果找不到程序中所用到的相关依赖则会报异常。如Spring中的IOC,如果你的项目中要用到一些类、接口的对象及其属性,就要把类和接口先用@Component把该类或接口注入到Spring容器中,实现控制反转,实现后我们才可以用@Autowired把他们的对象或属性注入到被依赖的类中。

⭐直接放图加深理解

BookService这个类用@Service将其对象注入到了Spring容器中,那么我们在用它的时候才能用

@Autowired把他注入到我们的IndexController类中

如果BookService没有注入到容器中【会标红,报异常表示找不到该对象(依赖)】:

 

那么,JDK,Spring这些算是一种容器么,当然不算是。JDK、Spring它们本身不能仅算作是一种容器,我们只能说Spring里有Spring提供的容器,JDK里有JDK提供的容器。(Spring是一种轻量级的java开发框架,JDK是java开发工具包,它们里面都包含了很多东西)

Maven的生命周期

Maven有三套互相独立的生命周期,每一个生命周期都有着一些相应的构建环节:

①Clean Lifecycle→在进行真正的构建之前进行一些清理工作。

②Default Lifecycle→构建的核心部分,编译,测试,打包,安装,部署等。

③Site Lifecycle→生产项目报告,站点,发布站点

Clean生命周期(有三个阶段)

1)pre-clean 执行一些需要在clean之前完成的工作

2)clean 移除所有上一次构建生成的文件

3)post-clean 执行一些需要在clean之后立刻完成的工作

Site生命周期(site命令---->生成一堆html,打开即可查看当前项目的信息)

1)pre-site 执行一些需要在生成站点文档之前完成的工作

2)site 生成项目站点文档

3)post-site 执行一些需要在生成站点文档之后完成的工作,并为部署做准备

4)site-deploy 将生成的站点文档部署到特定的服务器上

Default生命周期(重点)

绝大部分的工作都发生在这个生命周期当中。

引用其他文献的图给以参考(图中内容仅作了解就好)

validate   生命周期最初的位置(开始执行的位置)
generate-sources process-sources
generate-resources
process-resources 复制并处理资源文件,至目标目录,准备打包。。
compile  开始编译项目的源代码。
process-classes
generate-test-sources process-test-sources
generate-test-resources
process-test-resources 复制并处理资源文件,至目标测试目录。
test-compile 编译测试源代码。
process-test-classes
test 使用合适的单元测试框架运行测试。这些测试代码不会被打包或部署
prepare-package
package 接受编译好的代码,打包成可发布的格式,如JAR。 pre-integration-test integration-test
post-integration-test verify
install 将包安装至本地仓库,以让其它项目依赖
deploy 将最终的包复制到远程的仓库,以让其它开发人员与项目共享或部署到服务器上运行

总结:

一、在Default生命周期中无论是你执行哪一个阶段,Maven都会先从生命周期最初的位置开始执行。与构建环节同理。即假如,你要执行compile,它会从validate开始,一直一步一步执行,一直到compile环节执行完毕。

二、在Site生命周期Clean生命周期Default生命周期这三者是互相独立的,如果我们执行了Clean和Compile,那么它就会清空再编译,但如果只执行了Compile,那么它就只会重新编译、更新一些数据资源,不会clean清空

关于插件与目标

这方面其实是属于概念的一些称呼,目标即为调用插件功能的命令。Why?

例如,当Maven调用compile命令时,它使用的插件是maven-compiler-plugin

Maven的重要特性

1.依赖

1)依赖的传递性:假设有两个项目,分别为项目A和项目B,如果B引入了A到pom.xml中,那么A所引入的jar包/环境也会传递到B中。(注意:依赖传递只传递范围是compile的依赖)

前提:如果B依赖于A,则A需要调用install命令安装到本地仓库中,若不安装则无法在B中引入,因为项目A是自己创建的,Maven在本地仓库以及远程仓库都找不到A

图示:

2)依赖的排除:如果在项目中出现有部分jar包可能会对项目造成干扰、威胁或会引发一些依赖冲突以及其他不良影响的问题,并且你自己又改不了。遇上这种情况,则可以使用<exclusion>关键字排除其jar包

如图所示:

我们使用排除关键字排除冲突的依赖👇

3)依赖的原则:

当A←B←C时,A中有mysql8.0.25的架包,B中有mysql5.5的架包,那么这两个架包就有冲突了,C到底会引入谁的mysql jar包呢,依赖的传递性以及依赖的就近原则告诉我们,当这种情况发生,C离谁离得近就引入谁的jar包,所以C会引入B中mysql5.5的架包。在这种依赖关系当中,C对B是直接依赖,对A是间接依赖。

除了上面这种情况,还有一种情况,就是C同时依赖于A和B,但A和B的jar包又不一样,那么,这种情况依赖遵循的原则是顺序原则,意思为<denpendency>顺序谁越前C就引入谁的,如果想C引入B的jar包,就把A的相关jar包的<denpendency>放到其他jar包的下面。

4)依赖的统一管理

Maven中的jar包版本可以通过<properties>标签进行统一管理,例如:

<properties>
    <mysql.version>8.0.25</mysql.version>
</properties>
​
​
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>

这样,当jar包版本就改变时,就不用一个一个去改jar包版本。【例如spring引入各种的相关jar包,发生要修改的情况时,一个个修改会很麻烦】

5)依赖的继承

由依赖的传递性,我们知道依赖传递时,是只传递compile范围的依赖,像test范围的依赖就传递不了,为了解决这种类似的问题,依赖的继承就来了。

Maven中的依赖继承和java的继承机制相似,都是只能实现单继承,那么依赖的继承该如何实现呢?

<!--首先,我们要有一个父工程,父工程中不需要太多的代码,关键是它的pom.xml文件。父工程的打包类型既不是war也不是jar,而是pom,像这样:↓-->
<groupId>com.example</groupId>
<artifactId>Father</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packageing>pom</packageing>
​
<!--子工程对父工程的引用-->
<parent>
    <groupId>com.example</groupId>
    <artifactId>Father</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <!--以当前文件为基准的父工程pom.xml文件的相对路径-->
    <relativePath>../Father/pom.xml</relativePath>
</parent>

引入后,就可以实现对test范围依赖的统一管理了,例如:

父工程的pom.xml👇

    <groupId>com.example</groupId>
    <artifactId>Father</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packageing>pom</packageing>
​
    <!--父工程中用<dependencyManagement>标签来实现依赖的统一管理-->
    <dependencyManagement>
        <depenedencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>5.0</version>
                <scope>test</scope>
            </dependency>
        </depenedenies>
    </dependencyManagement>

子工程的pom.xml👇

        <groupId>com.example</groupId>
        <artifactId>Son</artifactId>
        <version>0.0.1-SNAPSHOT</version>
       
        
        <parent>
            <groupId>com.example</groupId>
            <artifactId>Father</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <relativePath>../Father/pom.xml</relativePath>
        </parent>
        <!--子工程中的junit依赖甚至不用写明版本号,因为父工程已经做了依赖的统一管理-->
        <depenedencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
        </depenedenies>

⭐注意:若当前的工程继承了一个父工程,那么在当前工程调用install命令时,必须先安装父工程

2.聚合

使用<modules>标签实现聚合功能,聚合的功能是把几个模块聚在一起,一键全部生成

首先,聚合功能与继承无关,而且能自动识别依赖传递顺序(即使图中Hello顺序打乱也无所谓,输出时,仍然会显示正确的依赖传递顺序)

<modules>标签中放好项目名称后,在总聚合的项目中调用Maven的install命令即可把<modules>标签中的所有项目全都安装。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值