多模块Maven项目下,引入公共模块依赖后,出现的can‘t find sympol问题(刨根问底)

        在开发中,无论是在微服务架构下还是单体架构下,我们经常使用到多模块开发,其中必然有抽取公共模块,将重复的依赖和重复的工具类整合的一个过程。

        但在我们打包时,我们经常会莫名其妙地出现can't find sympol的问题。明明在java类的import语句中正常导入了正确路径的类,也没有爆红,为什么会找不到类呢?这主要是由于我们在对common模块打包时jar包的属性以及结构导致的原因。

1.首先我们要理解maven工程是如何调用我们在pom.xml文件中声明的依赖的。

当我们编译maven项目时,maven工程会去我们本地仓库,根据坐标找到对应的jar包,然后将其复制到本包下的BOOT-INF/libs下,如图:

 我们在本项目中引入了springboot框架的web模块,那我们来到本地maven仓库:

 

 

 

 

 

 可以得知,groupId,artifactId,version三者由高到低组成了maven寻找依赖对应jar包的整个路径,其中这些内容都是在我们导入依赖的时候从中心仓库下载得来。

而我们项目中只要引入了dependency依赖,我们就会根据坐标找到对应jar包,复制到本包下。那我们java类又是如何导入jar包的类呢?

2.我们要了解一个普通JAR包的基本内容

以Netflix-Eureka为例

 我们可以看到其具体结构如下:

 1)其中META-INF存放本jar包的配置信息,如pom.xml,pom.properties等:

 2)org则是其工程下的一个jar子包,其最底层才是我们想要使用的java类:

3)那么我们在java文件中导包的过程,实际上就是导入其类所在的路径: 

 这个了解之后,我们就知道我们在项目中如何进行导包的了,距离解决我们的问题也接近了。

3.然后,我们要了解spring-boot打成的我们项目可执行jar包的结构

 使用7-ZIP打开可以清楚看到,我们的可执行JAR包中主要由两个文件夹,一个是BOOT-INF,一个是META-INF。

上面我们说到,META-INF文件夹是存放一些配置,org则是本文件夹下的一部分jar包。那么我们如何运行这个可执行jar包的呢?可执行jar包和普通jar包的区别在何处呢?

就在BOOT-INF

1)如何启动可执行jar包的

首先我们先查看一下BOOT-INF,其下的结构是这样:

我们点进去后会发现,我们编写的代码在classes文件夹下,我们的主启动程序也在其之下:

 

 

看到这里大家应该能把jar包内容和项目结构完全对应(resources文件夹本质上就是根文件夹,其下的内容就在根路径下,这也是为什么比如mybatis对应的xml文件路径配置前通常我们会加上"classpath:"的原因)

 所以启动可执行jar包的过程,本质上就是我们去BOOT-INF/classes/去启动我们主启动类的过程。

2)libs文件夹下则存放着我们我们找到的依赖:即标题1中找到的jar包,将其复制到了这里

 到这里,我们基本摸清了maven的整个流程,可以解决我们的问题了。

4.为什么我们在IDEA里面明明没有报错,使用mvn compile命令后,却找不到类呢?

直接上答案:因为你把common模块打成了可执行jar包,其具有BOOT-INF文件夹。

那达成可执行jar包为什么会影响我调用common模块下的类呢?

因为我们调用Jar包默认都是在jar包根路径下调用:

再把图贴出来方便大家看:

而一旦我们把项目达成可执行jar包,在标题3中我们讲的,我们项目内的类就会在BOOT-INF/classes下:

所以此时,我们common模块的类并没有在jar包根目录下,而是在BOOT-INF/classes下。

但是我们java导包默认地是去包的根路径下,而根路径此时啥都没有:

 所以就找不到当前类

5.那如何解决java寻找jar包类的寻找过程问题呢?

很简单哇,将common模块变成普通jar包,没有BOOT-INF,其内容都在jar包根路径下不就能过正常找到类了吗?

工作:替换common模块的pom.xml下的打包插件,将spring-boot-maven-plugin下添加一行配置:

 skip标签就能跳过BOOT-INF的打包过程,执行完后:

1)先install common包

2)更新全部依赖

最后我们的结构是这样的:

消费者模块中引入了common模块:

我们的common jar包,就理所应当应该在BOOT-INF/libs/下,我们去仓库寻找:

 打开后,我们发现,此时common模块没有了BOOT-INT文件夹,其原本所有的类均在其子路径下:

 

二者对应:这是jar包的结构

 这是我们项目的结构

 

 我们就可以成功一一对应!

到此结束!

 

 

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值