面试题:说说maven 以及打包命令

面试题:说说maven 以及打包命令

maven的打包命令:

mvn clean package

依次执行clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。

mvn clean install

依次执行clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。

mvn clean deploy

依次执行clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。

区别

package 命令完成了项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库
install 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库
deploy 命令完成了项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库

maven的生命周期

在这里插入图片描述

讲讲maven

我们任何一个人都是站在巨人的肩膀上。
我们开发的项目也是基于前人的经验。“不要重复造轮子”意思是不要重复的去做别人已经已经做过的事情。
所以我们的项目会使用别人做好的工具包或者框架。比如,Gson,Druid等。这些第三方的代码包我们称为依赖。

这里建议大家了解下一些常用的(大家都知道的)工具类库,帮助提升你的编码效率
apache commons系列 特别是commons-lang https://blog.csdn.net/f641385712/article/details/82468927
hutool https://www.hutool.cn/docs/#/
google guava http://ifeve.com/google-guava/

依赖与传递依赖

现在假设我们的项目 woniushop 依赖了 Druid,请问Druid会否依赖其他的工具或者框架呢?答案是肯定的。那么woniushop和Druid会有多少个这类的依赖呢?答案是很多个。所以一个项目的依赖关系就如同一棵树一样,具备层级关系。事实上,我们确实把依赖的整体关系称为依赖树。
在这里插入图片描述
解释下,woniushop依赖了druid,druid依赖了commons,那么显然woniushop在运行时是需要commons的代码才可以的,所以woniushop间接也依赖了commons。也就是说druid将commons也带进了woniushop的依赖树里。我们把这种关系叫做传递依赖,因为druid的依赖也被传递进了woniushop的依赖。所以,如果要成功运行woniushop,你需要将woniushop所使用到的依赖包都加到classpath中,也必须将这些依赖的依赖加入到classpath中。如果没有工具来管理它,这个工作就比较繁琐了。你需要从woniusho的各个依赖的官网下载jar包,并且又去找到他们的依赖的官网再去下载jar包,并且不能缺一个,也不能有版本上的错误。所以没有依赖管理工具的开发方式是弄一套出来,然后代代相传。

版本冲突

需要解释另一个概念,版本。版本是什么?
版本是某个时间点上的代码。一旦版本发布,代码就固定了。版本升级,代码就会变化。一般版本升级会对代码做哪些操作呢?
增加功能或者修复bug,代码增加
删除功能,比如废弃老旧的功能,代码减少
更改功能,有可能更改包名
所以版本升级可能是兼容老版本,也可能不兼容老版本。假设一个项目 woniumagic是蜗牛开发团队的开发神器工具包。有可能 woniumagic 2.0 和woniumagic1.0是不兼容的。如果不兼容,会出现什么问题呢?轻则编译报错,重则运行时代码逻辑出错。
显然我们不希望这种情况出现,所以一般不会轻易升级依赖的版本。
但是结合上面所说的依赖树的情况,现实中版本冲突的问题仍然存在。比如
在这里插入图片描述
这里有commons的两个版本,是不是就出现了版本冲突的问题呢?如果两个版本不兼容,那么druid和woniumagic中间必然有一个会出现编译问题。
这是依赖管理的另一个问题就是版本冲突的问题。

所以,到这里,大家应该留意到我们需要一个管理依赖的工具。这款工具就是Maven
在这里插入图片描述

Maven定义

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.
Apache Maven是一个软件(特别是Java软件)项目管理及自动构建工具,由Apache软件基金会所提供。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

所以这里提到,maven是一个项目管理及自动构建工具。项目管理最重要的就是依赖的管理,而自动构建指的是另一个话题。稍后再讲解。

刚才的依赖问题,maven是怎么解决的呢?
首先maven对项目结构做了些规范化的处理,并且定义了一个叫做POM的文件来管理所有的依赖。
我们先来安装和简单使用下maven,体验一下再继续讲解

安装及配置

1.官网下载安装(地址),选择bin.zip的版本
2.解压到安装目录
3.path中加入maven安装目录下的bin目录路径
4.测试安装成功:cmd中执行mvn -v
5.修改配置文件,apache-maven-xxx\conf目录下的settings文件
settings.xml文件配置前,建议先备份,配置主要修改两个地方

①(可选,默认在C盘的用户目录下)修改localRepository 为
d:/mvn/repo
②(极速之选,不选龟速)修改mirrors,在标签下加入以下配置,启动阿里云的镜像

alimaven
aliyun maven
http://maven.aliyun.com/nexus/content/groups/public/
central

下面来建一个简单地项目测试下maven的基本使用

创建项目
mvn archetype:generate -DarchetypeCatalog=internal-DgroupId=com.woniuxy.build -DartifactId=demo
执行项目
mvnclean compile exec:java -Dexec.mainClass=“com.woniuxy.build.App”

思考:
1)项目创建后由哪些文件及文件夹组成,分别是什么意思?
2)我们现在可以脱离IDE(eclipse或者idea)创建并执行项目,这对于我们而言有什么好处?

基本结构

Maven的设计理念里有一个重要的理念叫做:约定优于配置 Conversion over configuration。意思是我们约定了,就不要去专门配置它。这样就可以显著的减少配置内容。maven的文件夹结构就是一个约定

─src 源码
├─main 主要内容
│ ├─java java代码
│ │ └─com 以下是java的包路径
│ │ └─example
│ │ └─demo
│ └─resources 资源包括配置文件等
└─test 测试内容
└─java
└─com
└─example
└─demo
─pom.xml 最核心的配置文件

这个结构是必须记住的。

pom.xml的结构

<?xml version="1.0" encoding="UTF-8"?>


4.0.0


org.springframework.boot
spring-boot-starter-parent
2.3.4.RELEASE



me.maiz.framework
springsecuritydemo
0.0.1-SNAPSHOT

springsecuritydemo
Demo project for Spring Boot

<!--项目的属性配置-->
<properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.7</maven.compiler.source>
  <maven.compiler.target>1.7</maven.compiler.target>
</properties>

<!--本项目的依赖-->
<dependencies>
   
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.48</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    ...
</dependencies>

<!--构建项目的配置-->
<build>
  	<!--构建用到的插件-->
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
通过这种方式就把maven项目标准化了。

依赖管理

maven解决上述依赖管理问题的方式首先是标准化,就是刚才说的GAV坐标和maven的项目结构。

坐标

G:GroupId 分组ID,一般一家公司共用一个,与java包命名方式类似
A:ArtifactId 工件ID,项目ID
V: Version 版本号
可以唯一定位到某个jar包。

依赖范围

compile:编译时依赖在所有阶段都可获得,这是默认值。
provided: 提供的依赖范围用来编译应用程序,但无需部署。若你用到jdk或者应用服务器提供的JAR,则使用此范围,servlet APIs就属于这个依赖范围。测试时,此依赖范围也加入到classpath。
runtime:运行依赖范围在编译阶段是不需要的,只有在运行时需要,比如JDBC驱动程序。
test:测试范围依赖,仅在编译和运行单元测试时需要(比如Junit)。
system 本地依赖,不建议使用。(nexus)
在这里插入图片描述

传递依赖

请注意 只有编译和运行时依赖是传递的
A->B->C
简单传递依赖:A->C
A->B-C(0.1)
A->C(0.2)
最短路径优先原则: A->C(0.2)
A->B->C(0.1)
A->E->C(0.2)
第一声明优先原则:最终依赖C(0.1)

依赖归类

<properties>
    <spring.version>2.5</spring.version>
  </properties>
  <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
      </dependency>
   </dependencies>

依赖排除

 <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-validator</artifactId>
       <version>4.3.1.Final</version>
       <exclusions>
            <exclusion>
                <artifactId>slf4j-api</artifactId>
                <groupId>org.slf4j</groupId>
            </exclusion>
       </exclusions>
</dependency>

Maven仓库

很自然,我们能够想到,所有的maven项目最后需要发布到一个仓库中,以便于通过dependency进行获取。这个仓库称为中央仓库,地址是:https://mvnrepository.com/
但中央仓库是在公网上(而且在墙外),访问速度很慢,因此通常我们会有镜像仓库,或者称为私服。我们配置的是 阿里云的地址 https://maven.aliyun.com/mvn/guide 通过maven配置文件settings.xml中的mirror配置指定
从中央仓库或者maven私服拉取的jar包,存储在本地的一个文件夹中,我们称为maven本地仓库。这个仓库在settings.xml中的localRepository中指定。默认在用户目录的.m2目录下
反之,当需要一个依赖是,maven的查找顺序是

本地仓库 -> 私服 -> 中央仓库

了解这点,可以帮助我们解决很多实际的问题。

自动构建

构建,是指从源码到成品的过程。先举个简单地例子,在java项目中,从java代码到jar包的过程,大致有 编译,打包两步,这个就可以看做是个构建过程了。当然真实的要复杂的多。
maven定义了一个项目构建的完整过程,并且提供了命令给我们来执行这个构建过程。maven将整个构建过程称为生命周期。
在这里插入图片描述
每个环节称为一个阶段,每个阶段又有若干个可以执行的目标
在这里插入图片描述
基本上来说,有 初始化 -> 编译 -> 单元测试 -> 打包 -> 集成测试 -> 安装 -> 部署
这个过程是有顺序的。也就是说执行打包必须先执行单元测试
我们也可以在命令上加-Dmaven.test.skip=true跳过单元测试,因为一般都没写。
完整的描述如下
在这里插入图片描述
以上生命周期称为默认生命周期,maven定义了另一个生命周期clean,只有一个阶段就是clean,意思是清理maven所生成的代码。

对我们的项目执行以下命令并观察结果,请注意要在有pom.xml的目录下执行,所有命令都基于pom.xml来执行的:

mvn compile
mvn clean
mvn clean install

骨架Archetype

maven通过archetype来定义项目的原型骨架,选择一个骨架就可以对应生成某个结构的项目。比如JavaSE的项目,JavaWeb的项目,甚至一本书。我们也可以自定义maven骨架,来生成自己的项目。

Maven命令总汇

#  查看依赖树
mvn dependency:tree
# 查看生效的pom配置
mvn help:effective-pom
# 清理并安装,跳过测试
mvn clean install -Dmaven.test.skip=true
# 清理并打包,跳过测试
mvn clean package -Dmaven.test.skip=true
# 编译源代码
mvn compile
# 执行java项目
mvn exec:java -Dexec.mainClass="***.Main"
# 下载依赖源码
mvn dependency:sources
# -e 选项 开启异常打印
# -T 使用多进程下载

其他主题

● 父POM
● 多模块项目
● 下一代管理工具 gradle

Guess you like

Origin blog.csdn.net/weixin_55604133/article/details/120314528