
赶在凌晨一点写这些,窗户外头黑漆漆的,只有屏幕亮着。
并非是什么规模巨大的项目,只是被 Maven 折腾了好些年,仿佛处于亏欠债务那般的状况。
复制粘贴的耻辱
想想以前。
建新项目,第一件事:去旧项目里翻 lib 文件夹。
先按下 Ctrl+C,又按下 Ctrl+V。几百个 jar 被如同难民那般驱赶过来。
最怕那样的下午,明明已经加了包,却还是报出 NoClassDefFoundError,需要一个人,对着十几个文件夹,逐个去核对版本。
那时候哪敢叫“工程师”,就是个 Jar 搬运工。
仓库是个好东西
之后才晓得,Maven 所讲的那句话是,不要把 Jar 放置在项目里面,而是要把“坐标”放置在项目里面。
坐标这词真好。
groupId:artifactId:version。
三个向量,定位宇宙里唯一的一个包。
像北斗导航。
你将坐标写入pom.xml,Maven会沿着网线前往中央仓库找寻,寻得后便拉回到你电脑的.m2/repository。
从此所有项目都指着这一份 Jar 吃饭。
问题来了,仓库默认在哪?

第一次跑 mvn compile。
见到那呈现为绿色字样的BUILD SUCCESS这一行,我一下子呆住了,心里想着:Jar呢?之前我并没有向它告知放置的地点呀。
将C盘里,用户所属文件夹中对应你的名字的文件夹打开,再打开其中位置为.m2的文件夹,而后打开repository文件夹。
全在这。
像发现一个秘密基地。
依赖还会生小孩?

更离谱的是,我明明只引了 spring-core。
运行 mvn dependency:tree 命令查看,发现其底层挂着几十个包,令人惊叹,令人咂舌啊!
依赖会自动依赖别的依赖,Maven 管这叫“传递性依赖”。
package com.hzg.maven;
public class Hello {
public String sayHello(String name){
return "Hello "+name+"!";
}
}
以前手动加包,A 依赖 B,B 依赖 C,C 依赖 D。
你需要亲自逐个地将B拖进lib,接着把C拖进lib,然后把D拖进lib,若缺少其中任何一个,便会出现报错的情况。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.hzg.maven
Hello
0.0.1-SNAPSHOT
Hello
junit
junit
4.0
test
此刻你仅只需讲“我要 A”,Maven 回应道:行嘞,我会把与 A 有着极为深远亲缘关系的众多先辈都给你唤来。
这才是人干的事。
版本打架怎么办
但麻烦也来了。
项目引入了 A,它依赖 log4j 1.2.7,还引入了 B,它依赖 log4j 1.2.9。
Maven 懵了:俩版本,用谁?
它有个原则叫“路径最近优先”。
谁离项目近就用谁。
如果一样近,谁写在上面用谁。
——像极了小时候爸妈分苹果:看谁先开口。

后来我学会在 pom.xml 里用 统一版本。
像立家规。
什么依赖该留,什么不该留
scope 这玩意我以前总跳过。
随后,在线上出现了报错情况,报错内容为:显示出java.lang.ClassNotFoundException,具体所指的是javax.servlet.Servlet。
反复查找许久,servlet - api 包被嵌入到 war 之中,这与 Tomcat 自身所带的产生冲突了。

原先 scope 等于 provided 的含义是这般的,那就是在进行编译以及测试的阶段,是由我来为你提供使用的条件,然而到了运行的时候,你就得自行离开不用再依靠我了。
另外有 test,JUnit 应当待在 test 当中,不要朝着生产包里跑去凑热闹哟。
mvn clean 不是魔法

在首次开展 mvn clean 的执行操作时,整个的 target 文件夹呈现出消失不见的状况。
我差点报警。
后来懂了,这不是删代码,是打扫屋子再请客。
Maven的生命周期存在着三套,它们分别是clean, default以及site。
clean 删编译结果。
default 做正事:编译、测试、打包、安装、部署。
当你执行mvn install时,实际上它是默默地依次通过了validate,通过了compile,通过了test,并且通过了package。
你只点了最后一杯,它把前菜主菜甜点全上了。
坐标与路径的悄悄话
groupId=org.springframework
artifactId=spring-core
version=4.3.4.RELEASE
你去本地仓库看:
一一对应。
Maven 把坐标翻译成路径,像翻译一首诗。
私服与镜像,是成年人的体面
中央仓库在国外。
以前拉个 2M 的包能卡五分钟。

后来配了阿里云镜像。
central
把中央仓库的请求全转到国内节点。
速度快得像换了一根网线。
为公司项目配备私服是必要的,Nexus 运行于内网环境里,将自己所编写的公共组件部署至其上,供同事能够直接进行引用。
带有后续跟随 -SNAPSHOT 的版本号的情况,每一次进行构建的时候,都要前往私服去拉取最新的版本。
那是还活着的代码。
依赖排毒
mvn dependency:tree 看依赖树。
有时候,察觉到A引用了B的1.0版本。并且,还发现C引用了B的2.0版本。

如果 1.0 离得近,2.0 就被丢弃。
但你偏偏需要 2.0 的新 API。
上场。
把 B 的 1.0 从 A 的肚子里排出去。
像手术摘掉不合适的器官。

插一句:xml 配置是真的丑
pom.xml 长起来没边。
密密麻麻的尖括号。

但丑归丑,它说话算话。
你写进去的每一个 dependency,它都当回事。
比某些口头承诺靠谱。
最惊喜的那个瞬间
有个工具项目依赖了 core-utils。
C:Program FilesJavarepository
core-utils 又依赖了 common-io。
我向来都未曾于工具项目当中书写过common - io的dependency。
但它出现了。
Maven 把孙子辈的依赖直接带过来了。

那一瞬间觉得,这东西懂我。
查版本去哪查

以前问百度,点进去是 2013 年的博客,版本早过时了。
现在只去 mvnrepository.com。
搜索、复制、粘贴。
三秒搞定。
最新最全,活人在维护。
写完这些,快两点了
回头看,Maven 不是什么了不起的架构。
它只是把你从“复制粘贴”这种低级的重复里解放出来。

你就能仿若身为一名真正的程序员那般,仅仅去操心业务逻辑而已哟,而不用为 Jar 包究竟在何处这事儿操心啦。
你说它难学吗。
也不难。不过是编译、测试、打包、安装、部署。
仅仅是进行compile操作,接着开展test行为,随后执行package步骤,再然后完成install动作,最后实施deploy举措,仅此而已。

几个单词而已。
然而,恰恰是这几个简简单单的单词呀,驱使着我,从那个被称作“复制粘贴工程师”,摇身一变,成了那个专门去写 pom.xml 的人呢。
挺好的。
晚安。


Comments NOTHING