点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达
今日推荐:分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!个人原创100W +访问量博客:点击前往,查看更多

现在的项目中 Maven 随处可见,面试的时候,经常会被问一些项目中 Maven 的问题,但是平时 Maven 项目一般不会出什么问题,可能你不太注意,以下7个问题,一般说出来并掌握,至少可以证明你 Maven 用的熟练度还可以。

Maven的仓库管理、依赖管理、继承和聚合等特性为项目的构建提供了一整套完善的解决方案,如果你搞不懂Maven,那么一个多模块的项目足以让你头疼,依赖冲突就会让你不知所措,甚至搞不清楚项目是如何运行起来的...

OK,博主就曾经被Maven“伤害”过,所以,我们要:彻底搞定Maven!

回想一下,当你新到一家公司,安装完JDK后就会安装配置Maven,很大可能性你需要修改settings.xml文件,比如你会修改本地仓库地址路径,比如你很可能会copy一段配置到你的settings.xml中(很可能就是私服的一些配置)。接下来,你会到IDEA或者Eclipse中进行Maven插件配置,然后你就可以在工程中的pom.xml里面开始添加标签来管理jar包,在Maven规范的目录结构下进行编写代码,最后你会通过插件的方式来进行测试、打包(jar or war)、部署、运行。

上面描述了对Maven的一些使用方式,下面我们进行一些思考:

1、本地仓库?Maven到底有哪些仓库?它们什么关系?

Maven仓库:

本地仓库路径配置:

你要jar包,不可能每次都要联网去下载吧,多费劲,所以本地仓库就是相当于加了一层jar包缓存,先到这里来查。如果这里查不到,那么就去私服上找,如果私服也找不到,那么去中央仓库去找,找到jar后,会把jar的信息同步到私服和本地仓库中。

私服,就是公司内部局域网的一台服务器而已,你想一下,当你的工程Project-A依赖别人的Project-B的接口,怎么做呢?没有Maven的时候,当然是copy Project-B jar到你的本地lib中引入,那么Maven的方式,很显然需要其他人把Project-B deploy到私服仓库中供你使用。因此私服中存储了本公司的内部专用的jar!不仅如此,私服还充当了中央仓库的镜像,说白了就是一个代理!

中央仓库:该仓库存储了互联网上的jar,由Maven团队来维护,地址是:http://repo1.maven.org/maven2/。

2、关于 <dependency>的使用

依赖管理:

其实这个标签揭示了jar的查找坐标:groupIdartifactIdversion

一般而言,我们可以到私服上输入artifactId进行搜索,或者到http://search.maven.org/、http://mvnrepository.com/上进行查找确定坐标。

version分为开发版本(Snapshot)和发布版本(Release),那么为什么要分呢?

在实际开发中,我们经常遇到这样的场景,比如A服务依赖于B服务,A和B同时开发,B在开发中发现了BUG,修改后,将版本由1.0升级为2.0,那么A必须也跟着在POM.XML中进行版本升级。过了几天后,B又发现了问题,进行修改后升级版本发布,然后通知A进行升级...可以说这是开发过程中的版本不稳定导致了这样的问题。

Maven,已经替我们想好了解决方案,就是使用Snapshot版本,在开发过程中B发布的版本标志为Snapshot版本,A进行依赖的时候选择Snapshot版本,那么每次B发布的话,会在私服仓库中,形成带有时间戳的Snapshot版本,而A构建的时候会自动下载B最新时间戳的Snapshot版本!

3、既然Maven进行了依赖管理,为什么还会出现依赖冲突?处理依赖冲突的手段是?

依赖的版本?

首先来说,对于Maven而言,同一个groupId同一个artifactId下,只能使用一个version

根据上图的依赖顺序,将使用1.2版本的jar。

现在,我们可以思考下了,比如工程中需要引入A、B,而A依赖1.0版本的C,B依赖2.0版本的C,那么问题来了,C使用的版本将由引入A、B的顺序而定?这显然不靠谱!如果A的依赖写在B的依赖后面,将意味着最后引入的是1.0版本的C,很可能在运行阶段出现类(ClassNotFoundException)、方法(NoSuchMethodError)找不到的错误(因为B使用的是高版本的C)!

这里其实涉及到了2个概念:依赖传递(transitive)、Maven的最近依赖策略。

依赖传递:如果A依赖B,B依赖C,那么引入A,意味着B和C都会被引入。

Maven的最近依赖策略:如果一个项目依赖相同的groupId、artifactId的多个版本,那么在依赖树(mvn dependency:tree)中离项目最近的那个版本将会被使用。(从这里可以看出Maven是不是有点小问题呢?能不能选择高版本的进行依赖么?据了解,Gradle就是version+策略)

现在,我们可以想想如何处理依赖冲突呢?

想法1:要使用哪个版本,我们是清楚的,那么能不能不管如何依赖传递,都可以进行版本锁定呢?

使用 <dependencyManagement> 这种主要用于子模块的版本一致性中

想法2:在依赖传递中,能不能去掉我们不想依赖的?

使用 <exclusions>在实际中我们可以在IDEA中直接利用插件帮助我们生成

想法3:既然是最近依赖策略,那么我们就直接使用显式依赖指定版本,那不就是最靠近项目的么?

使用 <dependency>

4、引入依赖的最佳实践,提前发现问题!

在工程中,我们避免不了需要加一些依赖,也许加了依赖后运行时才发现存在依赖冲突在去解决,似乎有点晚!那么能不能提前发现问题呢?

如果我们新加入一个依赖的话,那么先通过mvn dependency:tree命令形成依赖树,看看我们新加入的依赖,是否存在传递依赖,传递依赖中是否和依赖树中的版本存在冲突,如果存在多个版本冲突,利用上文的方式进行解决!

5、Maven规范化目录结构

这里需要注意2点:

1、src/main下内容最终会打包到Jar/War中,而src/test下是测试内容,并不会打包进去。

2、src/main/resources中的资源文件会COPY至目标目录,这是Maven的默认生命周期中的一个规定动作。(想一想,hibernate/mybatis的映射XML需要放入resources下,而不能在放在其他地方了)

6、Maven的生命周期

Maven生命周期:

我们只需要注意一点:执行后面的命令时,前面的命令自动得到执行。

实际上,我们最常用的就是这么几个:

1、clean:有问题,多清理!

2、package:打成Jar or War包,会自动进行clean+compile

3、install:将本地工程Jar上传到本地仓库

4、deploy:上传到私服

7、关于scope依赖范围

既然,Maven的生命周期存在编译、测试、运行这些过程,那么显然有些依赖只用于测试,比如junit;有些依赖编译用不到,只有运行的时候才能用到,比如mysql的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。

总结来说:

1、compile:默认的scope,运行期有效,需要打入包中。

2、provided:编译期有效,运行期不需要提供,不会打入包中。

3、runtime:编译不需要,在运行期有效,需要导入包中。(接口与实现分离)

4、test:测试需要,不会打入包中。

5、system:非本地仓库引入、存在系统的某个路径下的jar。(一般不使用)

来源:https://dwz.cn/PHYFFK27

推荐文章
  • 今天给大家推荐6个Spring Boot项目,拿来就可以赚钱!

  • 分享一套基于SpringBoot和Vue的企业级中后台开源项目,这个项目有点哇塞!

  • 圈子哥推荐一种基于Spring Boot开发OA开源产品,学习/搞外快都是不二选择!

  • 硬刚一周,3W字总结,一年的经验告诉你如何准备校招!

原创电子书历时整整一年总结的 Java面试+ Java入门技术学习指南,这是本人这几年及校招的总结,各种异步面试题已经全部进行总结,按照章节复习即可,已经拿到了了大厂提供。原创思维导图
扫码或者微信搜 程序员的技术圈子 回复 面试 领取原创电子书和思维导图。

面试官:Maven 的这 7 个问题你思考过没有?相关推荐

  1. Android岗大厂面试官常问的那些问题,深夜思考

    我们程序员经常迷茫于有太多东西要学,有些找不到方向.不知所措. 很多程序员都愿意说,我想变得更好,但是更好是什么却很模糊,同时我们又不知道该怎么样去做.我们的生命如此短暂,作为程序员的职业生涯可能会更 ...

  2. main线程 子线程 顺序_面试官:线程池如何按照core、max、queue的执行顺序去执行?详解...

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

  3. adguard没有核心 core no_面试官:线程池如何按照core、max、queue的执行顺序去执行?...

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

  4. 面试官又整新活,居然问我for循环用i++和++i哪个效率高?

    前几天,一个小伙伴告诉我,他在面试的时候被面试官问了这么一个问题: 在for循环中,到底应该用 i++ 还是 ++i ? 听到这,我感觉这面试官确实有点不按套路出牌了,放着好好的八股文不问,净整些幺蛾 ...

  5. 项目经验不丰富、技术不突出的程序员怎么打动面试官?

    前言 相信不少的程序员都有过类似的困惑:如果我没有大型的项目经历,也不能靠技术征服面试官,那我要怎么才能给面试官留下一个好印象呢? 按照本人的面试经验来说,面试主要看几点:项目经验+基本技术+个人潜力 ...

  6. 网络状态码302和303的区别究竟是啥?面试官最满意这种回答

    为了避免很多小白进来看到这个问题一脸蒙圈,我想做一个完整的补充.老杨的文章一向是以详细(废话多)出名的,所以,看了开头就觉得好的速度收藏起来看,保证给你搞懂. 周五了,老杨写完回答就准备去海底捞吃顿夜 ...

  7. 职言 | 校招面试有感,一个面试官的几点建议

    职言: 最近一直在校招,我(作者)和同事说等这段时间结束,我不想再参与面试了,快面吐了.从校招开始,我团队前前后后陆续进了500多封学生简历,我经常一整天排满了面试,聊到后面,审美疲劳.网上说,202 ...

  8. 面试官问:生成订单30分钟未支付,则自动取消,该怎么实现?

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源 | https://blog.csdn.net/hjm4702192/article/details/80519010 在开发 ...

  9. 面试官三连问:你这个数据量多大?分库分表怎么做?用的哪个组件?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 1.  概述 ShardingSphere是一套开源的分布 ...

  10. 面试官:Java如何绑定线程到指定CPU上执行?

    不知道你是啥感觉,但是我第一次看到这个问题的时候,我是懵逼的. 而且它还是一个面试题. 我懵逼倒不是因为我不知道答案,而是恰好我之前在非常机缘巧合的情况下知道了答案. 我感觉非常的冷门,作为一个考察候 ...

最新文章

  1. ASP.NET 2.0实现自带TreeView的客户端连带选择
  2. 研读代码必须掌握的五个Eclipse快捷键
  3. 开源GIS---.Net系列
  4. python制作简单K线图
  5. c++ 截取屏幕图片并保存
  6. Object类的使用,包装类的使用
  7. nginx图片缓存服务器配置实战
  8. java rsync上传_Rsync自动同步工具
  9. (5)机器学习_K折交叉验证(iris数据集实例)
  10. IOS笔记 : addChildViewController
  11. 兼容sdk7iOS7的issue解决小片段总结
  12. 英特尔显卡驱动 Intel Graphics Driver for Windows 10 v30.0.101.1069 官方正式安装版 64位
  13. 七牛云上传文件、视频截图、合成gif图
  14. Java打包exe文件
  15. 行人重识别论文阅读7-基于图卷积的行人骨架识别
  16. 详解 Java 内部类
  17. JAVA跑步计时器app_锻炼计时器app
  18. SpringBoot+Vue实现前后端分离的财务管理系统
  19. 11 种主要神经网络结构图解
  20. 山茶油的功效与食用方法

热门文章

  1. MVC --.Routing
  2. 傅里叶级数FS, 离散傅里叶变换DFT
  3. webstorm打开网页_网页前端之HTML+CSS+JS
  4. C++ Primer 5th笔记(chap 17 标准库特殊设施)ECMAScript正则表达式
  5. 跨链(2)跨链技术“侧链(Sidechains)”
  6. 《研磨设计模式》chap18 状态模式state(4)例子
  7. 初等数论--同余--MILLER-RABIN素性检测算法
  8. 20-Granule Protection Tables Library
  9. MoeCTF 2021Re部分------ez(递归转循环)
  10. BabyXor flower逆向寒假生涯(19/100)