跳转至

Maven 面试题(爪哇程序员)

maven是什么?

原文:https://zwmst.com/1286.html

Apache Maven是一个软件项目管理和理解工具。基于项目对象模型(POM)的概念, Maven可以从一个中心信息管理项目的构建,报告和文档。

项目构建

在eclipse中新建一个WEB工程。

进行编码及编写配置文件

对源代码进行编译运行,生成class文件

打成war包,部署至tomcat

使用Maven好处

原文:https://zwmst.com/1288.html

Maven能提供一种项目的配置,配置好的项目,只需要运行一条简单的命令,就能完成重复 的,繁琐的构建动作.

Maven能提供一种项目的依赖配置.可以自动的导入项目依赖的jar,并且自动导入这些jar包依赖的第三方的jar包.

Maven提供了一种标准的项目目录结构,测试命名规则等项目的最佳实践方案,统一了不同项 目的学习成本.

maven的常用命令

mvn clean : 清理

mvn compile:编译

mvn package:打包

mvn test : 测试,⾃动运⾏所有的测试⽤例

mvn install : 安装,将项⽬打的包安装到本地仓库,其他项⽬就可以依赖了

mvn jetty:run : 运⾏jetty插件

Maven的坐标和依赖

原文:https://zwmst.com/1290.html

maven的坐标组成部分

groupId: 组织机构id,org.aptech.hdax, org.springframework

artifactId: ⼦项⽬编号,springmvc, spring-test, spring-core

version: 版本号,可以⼀直迭代,平时项⽬开发⽤的是快照版本 0.0.1-SNAPSHOT

Package: jar war pom

项⽬依赖的核⼼概念:

框架整合最害怕jar包冲突,之前不使⽤maven,经常出现这个⽂件。

依赖范围 scope标签进⾏配置

Compile: 默认值,项⽬打包的时候会把该依赖包打进去

Test : 测试依赖,只是在运⾏测试⽤例的时候会⽤到,打包是不打进去的 Provided: 提供依赖,类似于test

传递依赖

a -> b, b->c ,如果在a中导⼊到b的依赖,c会⾃动过来

依赖调解

如果不同的包传递依赖了⼀个相同的jar,但是版本不⼀致

原则:

最短路径

第⼀声明优先原则

排除依赖

归类依赖: ⽅便后期的依赖版本升级、降级

Maven的⽣命周期

原文:https://zwmst.com/1292.html

一个项目的构建过成通常包括清理、编译、测试、打包、集成测试、验证、部署等。Maven从 中抽取了一套完善的、易扩展的生命周期。Maven的生命周期是抽象的,其中的具体任务都交 由插件来完成。Maven为大多数构建任务编写并绑定了默认的插件。

Maven定义了三套生命周期:clean、default、site,每个生命周期都包含了一些阶段(phase)。三套生命周期相互独立,但各个生命周期中的阶段却是有顺序的,且后面的夹断 依赖于前面的阶段。执行某个阶段时,其前面的阶段会依顺序执行,但不会触发另外两套生命 周期中的任何阶段。

你们项目为什么选用 Maven 进行构建?

原文:https://zwmst.com/1294.html

首先,Maven 是一个优秀的项目构建工具。使用maven,可以很方便的对项目进行分模 块构建,这样在开发和测试打包部署时,效率会提高很多。

其次,Maven 可以进行依赖的管理。使用 Maven ,可以将不同系统的依赖进行统一管 理,并且可以进行依赖之间的传递和继承。

Maven 规约是什么?

原文:https://zwmst.com/1296.html

/src/main/java/ :Java 源码。

/src/main/resource :Java 配置文件,资源文件。

/src/test/java/ :Java 测试代码。

/src/test/resource :Java 测试配置文件,资源文件。

/target :文件编译过程中生成的 .class 文件、jar、war 等等。

pom.xml :配置文件

Maven 要负责项目的自动化构建,以编译为例,Maven 要想自动进行编译,那么它必须知道 Java 的源文件保存在哪里,这样约定之后,不用我们手动指定位置,Maven 能知道位置,从 而帮我们完成自动编译。

遵循“ >>> ”。即能进行配置的不要去编码指定,能事先约定规则的不要去 进行配置。这样既减轻了劳动力,也能防止出错。

Maven 常用命令

原文:https://zwmst.com/1298.html

  • mvn archetype:create :创建 Maven 项目。 mvn compile :编译源代码。

  • mvn deploy :发布项目。

  • mvn test-compile :编译测试源代码。

  • mvn test :运行应用程序中的单元测试。

  • mvn site :生成项目相关信息的网站。

  • mvn clean :清除项目目录中的生成结果。

  • mvn package :根据项目生成的 jar/war 等。

  • mvn install :在本地 Repository 中安装 jar 。 mvn eclipse:eclipse :生成 Eclipse 项目文件。

  • mvn jetty:run 启动 Jetty 服务。

  • mvn tomcat:run :启动 Tomcat 服务。

  • mvn clean package -Dmaven.test.skip=true :清除以前的包后重新打包,跳过测试类。

用到最多的命令:

  • mvn eclipse:clean :清除 Project 中以前的编译的东西,重新再来。
  • mvn eclipse:eclipse :开始编译 Maven 的 Project 。
  • mvn clean package :清除以前的包后重新打包。

Maven 有哪些优点和缺点

原文:https://zwmst.com/1300.html

1)优点

简化了项目依赖管理。

当年,多少人被 SSH 整合搞死搞活,很多时候,是因为依赖不完整,或者版本不正确。 自从 Maven 出来后,终于可以无痛了~当然,也有一部分功劳是 Spring Boot ,这是后 话。

易于上手,对于新手可能一个 mvn clean package 命令就可能满足我们的工作。

便于与持续集成工具(Jenkins)整合。

便于项目升级,无论是项目本身升级还是项目使用的依赖升级。

有助于多模块项目的开发,一个模块开发好后,发布到仓库,依赖该模块时可以直接从仓库更新,而不用自己去编译。

Maven 有很多插件,便于功能扩展,比如生产站点,自动发布版本等。

2)缺点

Maven 是一个庞大的构建系统,学习难度大。

这里的学习,更多指的完整学习。如果基本使用,并不会存在该问题。

Maven 采用约定优于配置的策略(convention over configuration),虽然上手容易,但是一旦出了问题,难于调试。这个确实,略微痛苦。

当依赖很多时,m2eclipse 老是搞得 Eclipse 很卡。

使用 IDEA ,而不是 Eclipse ,完美解决。

中国的网络环境差,很多 repository 无法访问,比如 Google Code、 JBoss 仓库无法访 问等。

这个也好解决,在 中增加阿里巴巴的 Maven 私服,具体可以参见 《提高 Maven 速度 —— Maven 仓库修改成国内阿里巴巴地址》 文章。

Maven 版本规则?

原文:https://zwmst.com/1302.html

Maven 主要是这样定义版本规则的:.. 。比如说 1.2.3 ,主 版本是 1 ,次版本是 2 ,增量版本是 3 。

  • 主版本,一般来说代表了项目的重大的架构变更,比如说 Maven 1 和 Maven 2 ,在架构上已经两样了,将来的 Maven 3 和 Maven 2 也会有很大的变化。
  • 次版本,一般代表了一些功能的增加或变化,但没有架构的变化,比如说Nexus 1.3 较之 于 Nexus 1.2 来说,增加了一系列新的或者改进的功能(仓库镜像支持,改进的仓库管理界面等等),但从大的架构上来说,1.3 和 1.2 没什么区别。
  • 增量版本,一般是一些小的 bug fix ,不会有重大的功能变化。

一般来说,在我们发布一次重要的版本之后,随之会开发新的版本。比如说,myapp-1.1 发布之后,就着手开发 myapp-1.2 了。由于myapp-1.2 有新的主要功能的添加和变化,在发布测试前,它会变得不稳定,而 myapp-1.1 是一个比较稳定的版本,现在的问题是,我们在 myapp-1.1中 发现了一些 BUG(当然在 1.2 中也存在),为了能够在一段时间内修复 BUG 并 仍然发布稳定的版本,我们就会用到分支(branch),我们基于 1.1 开启一个分支 1.1.1 ,在这个 分支中修复 BUG ,并快速发布。这既保证了版本的稳定,也能够使bug得到快速修复,也不同 停止 1.2 的开发。只是,每次修复分支 1.1.1 中的 BUG 后,需要 merge 代码到 1.2 中。

对于一个多模块项目,如果管理项目依赖的版本?

原文:https://zwmst.com/1304.html

方式一,通过在父模块中声明 和, 然后让子模块通过元素指定父模块,这样子模块在定义依 赖是就可以只定义 groupId 和 artifactId,自动使用父模块的 version ,这样统一 整个项目的依赖的版本。继承的方式。

方式二,使用 声明 为 import 的依赖,从而引入一个 pom 的 的。具体的,可以看看 《Maven Spring BOM (bill of materials)》文章。组合的方式。

Maven 依赖原则?

原文:https://zwmst.com/1306.html

1、赖路径最短优先原则。

一个项目 Demo 依赖了两个 jar 包,其中 A-B-C-X(1.0) , A-D-X(2.0) 。由于 X(2.0) 路径最短,所以项目使用的是 X(2.0) 。

2、pom文 件中申明顺序优先。

如果 A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下, Maven 会根据 pom 文件声明的顺序加载,如果先声明了 B ,后声明了 C ,那就最后的 依赖就会是 X(1.0) 。

3、覆写优先

子 pom 内声明的优先于父 pom 中的依赖。

如何解决 jar 冲突?

原文:https://zwmst.com/1308.html

遇到冲突的时候第一步,要找到 Maven 加载的到时是什么版本的 jar 包,通过们 mvn dependency:tree 查看依赖树,或者使用 IDEA Maven Helper 插件。

然后,通过 Maven 的依赖原则来调整坐标在 pom 文件的申明顺序是最好的办法,或者使用将 冲突中不想要的 jar 引入的 jar 进行 掉。

什么是 Maven 插件?

原文:https://zwmst.com/1310.html

Maven 生命周期的每一个阶段的具体实现都是由 Maven 插件实现的。插件通常提供了一个目 标的集合,并且可以使用下面的语法执行:mvn [plugin-name]:[goal-name]

Maven 提供了下面两种类型的插件:

Build plugins :在构建时执行,并在 pom.xml 的 元素中配置。

Reporting plugins :在网站生成过程中执行,并在 pom.xml 的元素中配置。

下面是一些常用插件的列表:

clean :构建之后清理目标文件。删除目标目录。

compiler :编译 Java 源文件。

surefile :运行 JUnit 单元测试。创建测试报告。

jar :从当前工程中构建 JAR 文件。

war :从当前工程中构建 WAR 文件。

javadoc :为工程生成 Javadoc 。

antrun :从构建过程的任意一个阶段中运行一个 ant 任务的集合。

Maven依赖冲突

原文:https://zwmst.com/1312.html

每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被maven间接引入进 来,因而可能造成一个我们不想要的类包的载入,严重的甚至会引起类包之间的冲突。

要解决这个问题,首先就是要查看pom.xml显式和隐式的依赖类包,然后通过这个类包树找出 我们不想要的依赖类包,手工将其排除在外就可以了。 例如:

<exclusions>
     <exclusion>
     <artifactId>unitils-database</artifactId>
     <groupId>org.unitils</groupId>
     </exclusion>
</exclusions>

依赖的解析机制

原文:https://zwmst.com/1314.html

当依赖的范围是 system 的时候,Maven 直接从本地文件系统中解析构件。

根据依赖坐标计算仓库路径,尝试直接从本地仓库寻找构件,如果发现对应的构件,就解析成 功。

如果在本地仓库不存在相应的构件,就遍历所有的远程仓库,发现后,下载并解析使用。

如果依赖的版本是 RELEASE 或 LATEST,就基于更新策略读取所有远程仓库的元数据文件 (groupId/artifactId/maven-metadata.xml),将其与本地仓库的对应元合并后,计算出 RELEASE 或者 LATEST 真实的值,然后基于该值检查本地仓库,或者从远程仓库下载。

如果依赖的版本是 SNAPSHOT,就基于更新策略读取所有远程仓库的元数据文件,将它与本 地仓库对应的元数据合并,得到最新快照版本的值,然后根据该值检查本地仓库,或从远程仓 库下载。

如果最后解析得到的构件版本包含有时间戳,先将该文件下载下来,再将文件名中时间戳信息 删除,剩下 SNAPSHOT 并使用(以非时间戳的形式使用)。



回到顶部