文章目录
背景
我们最近在开发一个Java web项目,当时的设计基本是这样:将各个基础档案或者其它应用按照模块划分,基本上是一个档案对应一个git仓库(也有一个git下面有多个maven模块,这样的也有),按照职责划分开,希望将来能够按照微服务进行拆分(每个模块都会有api,domain,web层),但是暂时并不会这样做,也没有用springboot,常规的war包项目。而且设计上会有一个启动器,由一个启动器来控制要依赖哪些模块并且把它们启动,不同的启动器所包含的内容会不一样,但它们之间也会有共同使用的一些模块。
最后创建了大约有十余个git仓库,也有十个左右的开发,然后基本上每个开发会参与其中的一些(大于等于二,一个启动器+几个模块)。使用IDEA开发,基本上会在同一个工作空间(这个我指的是一个IDEA窗口)里面会导入多个git项目,通过maven视图的添加按钮添加进来的,这样开发的话,就会使用到本地最新的代码去编译测试,测试完了以后是需要deploy到远程仓库,供其他人和构建测试环境使用。
基本问题
我刚开始并没有参与设计和开发,最近加入了,不过我先是梳理十几个Git仓库之间的关系,因此把所有的代码拉取下来并加入到IDEA的一个工作空间内(注意有的项目代码,是我很久之前已经拉下来了),之后我在启动项目的过程当中碰见了两个问题:
假设有3个工程吧,A是启动工程,A依赖了B和C。
问题1: 本地启动,报错;发在群里面问一下,这是谁负责的,应该怎么处理。有人告诉我应该去拉取一下项目B的代码,然后build一下,再启动。我试了一下,果然好了。
关于这个问题,我当时就非常郁闷,我启动的时候,为什么要用本地工作空间的代码编译启动?为什么没有用maven仓库的。而且在之间群里面,隐约记得,有好几次有这种问题,解决方案都是如此。
我在意的有两点:
- 我并不关心项目B,我也没有修改它,因此我不需要也不应该操作它。我启动工程就不应该去拉取B的代码,我用最新的仓库里面的就行了呀。
- 默认启动的话,为什么用的是工作空间的,而不是仓库的。
我抛出了这样的问题,并且想去查看一下为什么。当然得到了一个比较错误的结论,是因为对方导入idea的方式有问题,并且让对方按照我的来。在这个过程里面,而且我用maven package的时候,发现打出来的依赖包,居然不是最新的,是因为对方并没有deploy。基于这两点,我以为回答了上面的这两个问题。
后来,我又碰到了一个问题,让我知道了我理解的有问题,并且这个问题很重要,必须要彻底搞清楚。
问题2: 我后面启动的时候,报错,一个类找不到,是C工程里面,我下意识的进行了一系列操作:拉代码,build,启动,错误仍然还在。最新的代码里面,有那个类,没有问题。然后我又查看了A工程target目录中的c.jar,发现里面确实没有。我又进一步查看了本地和远程maven仓库,发现都没有问题。那么问题来了,这个错误的c.jar到底是从哪里来的?一定要找到问题,一顿操作,发现是在c工程目录下的target/classes下面,并没有那个类的class文件。
哇哦,原来如此。说明IDEA在启动A的时候,处理C依赖的时候,用了C工程target目录下的相关文件用于打包,而且它并没有用C的源码去编译,当然也就没有使用maven仓库里面的了。
那显然我自己的导入方式也是不正确的,因此就展开了一系列的研究,我觉得非常有必要去搞清楚这个问题,肯定可以提高开发效率。
明确目标
我为什么要去研究这个呢?我希望是这样一种场景:十几个人开发同一个项目,分为好多模块,各自负责各自的就行,但是负责的模块里面肯定也会有交集,当别人正确的修改完模块B的代码以后,发布到远程仓库里面,其它人启动的时候,都应该直接用远程仓库的(尽管自己本地也有这个模块),这样就不会有任何问题(排除他本身提交的错误的情况),同时我们自己在做开发的时候,本地测试的时候,编译使用的应该就是本地的,并且在测试完成后,发布的仓库中以后,它本身也可以用仓库中的进行测试,保证仓库中那个的也是没有问题的,这样别人甚至搭建的环境中的是没有问题的。当然,这些都建立在所有开发都遵循我们的开发规范,这样也就可以节省很多不必要的时间了。而且在整个过程当中,所有的项目都是在同一个工作空间的,我不需要对它们进行移除和添加操作。
刚才说的是做这件事情的原因,那如何来实现这件事情呢?基本上当时是有如下的目标:
- IDEA在debug或者run的时候,会先build,或者build也可以单独执行,那么这个build到底是如何来区分用工作空间中的还是仓库?到底是在哪里配置的,我们能不能手动修改,然后自己来控制?虽然我当时见到的全是使用工作空间的,但很明显有一个现象,我把工程B移除了工作空间,它就会使用仓库的,我想那肯定是有配置的。
- 在IDEA中的maven仓库中的clean,compile以及package等命令,与IDEA的build命令到底有什么关系?或者它们分别做了什么事情?
这是两个比较大的目标,但是在实际过程执行的时候,其实也帮助我弄清楚了一些其它小问题,比如maven仓库中关于快照版本的处理方式,build的时候,有时候会构建,有时候不构建,它到底是怎么判断的?package结束了,直接build的时候,有时候没有任何变化,但有的时候就会有变化,这是为什么?如果当不变化的时候,意味着你用的代码是最新的仓库里面的,并不是你本地的,但是你可能不知道。而且还发现了IDEA的关于Build的源码在哪里,处理jar或者resources的是哪个类,当然没有仔细看,还不至于到那一步。
有时候会觉得整个过程特别玄幻,基本上就是大量的测试,采用控制变量法,不断的去观察记录现象,好不容易得出一个结论,过一会儿现象就会推翻之前的结论,然后一度怀疑人生~
关于maven的快照版本:SNAPSHOT
这个我简单说一下,详细的可以去查询资料。
快照版本的出现就是用来解决在开发态会不定期高频率更新代码的场景的。
使用的发行版本的话,只要本地有,就不会去远程仓库拉,除非把本地的删除。加参数-U也没用。
想要拉取最新代码,就必须更新版本,其实就是升级版本,1.0.0升级到1.0.1。对于开发者和使用者都一样。
那么快照版本的话,就允许在同一个版本下,提交无数次快照版本,并且快照版本和发布版本会放在maven仓库的不同地方,区别处理