jar包的多层级maven依赖的坑与正确传递方法

这个问题简述起来就是项目加载jar包但是无法加载jar包的依赖

这是一个maven的特性吗?


问题发生前

程序猿经常自己写一些库实现或收集常用的逻辑方法(算法和设计模式等等),以方便多个项目使用,避免重复编码。本猿现在有这么一个库,本猿把他叫 E库E库用maven做工程和生命周期管理,以便能用到其他java工程中。同时库里面也引用了其他一些开源公共库,使用或包装他们以实现自己的功能。(如下是E库部分依赖截图)

E库的依赖的一部分
E库的依赖的一部分


本猿新建一个项目A,并引入这个自用的库,如果项目人多会用私库,多数情况不会超过5个人的,一般本猿会用项目中的文件夹做仓库。在项目A的pom.xml中加入这个文件夹做的仓库:

<repositories>
	<repository>
		<id>minimal-maven-repository</id>
		<url>file:///${project.basedir}/minimal-maven-repository</url>
		<layout>default</layout>
		<releases>
			<enabled>true</enabled>
		</releases>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
</repositories>

这里就用minimal-maven-repository这个文件夹做仓库。


现在,在项目A根目录执行如下命令把E库部署到这个仓库中:

VERSION=1.2.0-snapshot
mvn deploy:deploy-file -Dfile=/server/data/ejoker/target/ejoker-${VERSION}.jar -DgroupId=pro.jiefzz -DartifactId=ejoker -Dversion=${VERSION} -Dpackaging=jar -Durl=file:./minimal-maven-repository/ -DrepositoryId=minimal-maven-repository -DupdateReleaseInfo=true

如果用Nexus私库的话,上面这一步相当于把jar发布到私库,并在项目中引入私库地址。

其中:

选项 用途
-Dfile 指明部署的库的路径
-DgroupId 设置库的groupId
-DartifactId 设置库的唯一artifactId
-Dversion 设置当前要部署库的版本
-Dpackaging 部署的类型
-Durl 仓库的位置,这里用项目里的一个文件夹做仓库
-DrepositoryId 仓库的id,这个选项在部署到中央仓库时有用,这里自便
-DupdateReleaseInfo (字面意思理解)

如无意外大概会看到如下结果,即代表成功:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building willdelete 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ willdelete ---
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.pom (6 KB at 2.2 KB/sec)
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus/1.0.12/plexus-1.0.12.pom (10 KB at 10.4 KB/sec)
Downloading: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.jar
Downloaded: http://maven.aliyun.com/nexus/content/groups/public/org/codehaus/plexus/plexus-utils/1.5.6/plexus-utils-1.5.6.jar (245 KB at 199.1 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.jar
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.jar (427 KB at 21306.2 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom (398 B at 194.3 KB/sec)
Downloading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 153.3 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.570 s
[INFO] Finished at: 2019-09-26T21:29:43+08:00
[INFO] Final Memory: 8M/99M
[INFO] ------------------------------------------------------------------------

查看下minimal-maven-repository目录看看:

Jiefzzs-MacBook-Pro:willdelete kimffy$ tree minimal-maven-repository/
minimal-maven-repository/
└── pro
    └── jiefzz
        └── ejoker
            ├── 1.2.0-snapshot
            │   ├── ejoker-1.2.0-snapshot.jar
            │   ├── ejoker-1.2.0-snapshot.jar.md5
            │   ├── ejoker-1.2.0-snapshot.jar.sha1
            │   ├── ejoker-1.2.0-snapshot.pom
            │   ├── ejoker-1.2.0-snapshot.pom.md5
            │   └── ejoker-1.2.0-snapshot.pom.sha1
            ├── maven-metadata.xml
            ├── maven-metadata.xml.md5
            └── maven-metadata.xml.sha1

4 directories, 9 files

是不是跟你在别的仓库中看到的结构是一样的啊,仓库就是按这个结构装jar的。


现在,可以在项目A的pom.xml中引入E库以及一些项目中用到的库了:

    <dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>1.7.16</version>
	</dependency>
    <dependency>
		<groupId>pro.jiefzz</groupId>
		<artifactId>ejoker</artifactId>
		<version>1.2.0-snapshot</version>
	</dependency>
    <dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
		<version>4.5.8</version>
	</dependency>

接下来,eclipse中

右键点击项目 -> maven -> update project

正常通过没毛病。


接下来在代码中使用项目A的写一段代码,并在里面用上E库

package pro.jiefzz.willdelete;

import pro.jiefzz.ejoker_support.rocketmq.DefaultMQConsumer;
import pro.jiefzz.ejoker_support.rocketmq.MQInstanceHelper;

/**
* Hello world!
*
*/
public class App 
{
    public static void main( String[] args )
    {
//        System.out.println( "Hello World!" );
        // 这个其实是E库中创建rocketmq客户端的一个助手类,没什么特别的逻辑的。
        DefaultMQConsumer createDefaultMQConsumer = MQInstanceHelper.createDefaultMQConsumer("", "127.0.0.1:9876", null);
    }
}

问题发生了

然后运行项目App主类:

eclipse点击运行App主类

鹅?! 找不到类?是本猿打开方式不对吗? 命令中敲一次mvn -Dmaven.test.skip=true clean compile package

eclipse点击运行App主类

-_-! 还真找不到啊。。。

java.lang.NoClassDefFoundError: org/apache/rocketmq/client/consumer/AllocateMessageQueueStrategy

这个明显是rocketmq的,而这个rocketmq的依赖不是E库带着的吗(参考上面的图)?难道本猿还要在项目A的pom.xml中贴一次E库的依赖吗?(其实本猿是故意调用E库中使用有依赖其他jar的代码的😈)


为什么E库的依赖没有被加载到项目A中?

为什么会酱

终端里看一下依赖树 mvn dependency:tree

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ willdelete ---
[INFO] pro.jiefzz:willdelete:jar:0.0.1-SNAPSHOT
[INFO] +- junit:junit:jar:3.8.1:test
[INFO] +- pro.jiefzz:ejoker:jar:1.2.0-snapshot:compile
[INFO] \- org.apache.httpcomponents:httpclient:jar:4.5.10:compile
[INFO]    +- org.apache.httpcomponents:httpcore:jar:4.4.12:compile
[INFO]    +- commons-logging:commons-logging:jar:1.2:compile
[INFO]    \- commons-codec:commons-codec:jar:1.11:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

有点不好看,不要紧 大概就是 willdelete依赖了3个包,其中httpclient 下有3个依赖包,而junitejoker就直接是末端,没有更下层的依赖了

eclipse看项目依赖树

eclipse里面看到的是一个意思的。很明显,E库(就是这里的ejoker包)下应该有一些依赖啊(例如rocketmq客户端的,以及前面贴了图的)


这个问题以前就出过,只不过那时没闲管他,直接把E库的依赖往项目A里贴一次(相当于手动提供了😹)

今天刷了很久的Google没找到(以前找过也没找到),找到的都是把依赖的直接跟目标jar打到一起(不管是解压后吧class放到一起还是装到提个lib文件夹里面然后把classpath写到META-INF/mainifest.mf里面,这两殊途同归,行话叫打胖包和打瘦包),都不是本猿要的。


其实问题出在上面那个deploy到本地仓库的过程,
mvn deploy过程里有个参数 -DgeneratePom,默认值是true的 -_-**

那他干了些啥呢?看刚刚那个本地仓库的目录

Jiefzzs-MacBook-Pro:willdelete kimffy$ tree minimal-maven-repository/
minimal-maven-repository/
└── pro
    └── jiefzz
        └── ejoker
            ├── 1.2.0-snapshot
            │   ├── ejoker-1.2.0-snapshot.jar
            │   ├── ejoker-1.2.0-snapshot.jar.md5
            │   ├── ejoker-1.2.0-snapshot.jar.sha1
            │   ├── ejoker-1.2.0-snapshot.pom
            │   ├── ejoker-1.2.0-snapshot.pom.md5
            │   └── ejoker-1.2.0-snapshot.pom.sha1
            ├── maven-metadata.xml
            ├── maven-metadata.xml.md5
            └── maven-metadata.xml.sha1

4 directories, 9 files

看看里面的ejoker-1.2.0-snapshot.pom :

Jiefzzs-MacBook-Pro:willdelete kimffy$ cat minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>pro.jiefzz</groupId>
<artifactId>ejoker</artifactId>
<version>1.2.0-snapshot</version>
</project>
Jiefzzs-MacBook-Pro:willdelete kimffy$

这段按人话说就是:这是个包。然后。。 然后没了。 没了?! 是的,没别的了,项目端的maven获得的信息就只有这丁点儿。无语....

他不是E库的pom.xml吧,是那个隐含的-DgeneratePom=true参数的杰作吧...

问题就是这里,maven不知道他还要依赖。一些纯工具类库没有其他依赖的,这样当然不会出问题,他不需要依赖,maven也没为他加载依赖。也有些需要依赖的但是项目中同时又用到了的,似乎没问题,但是只是恰巧遇上刚刚而已,如依赖log类最好理解了 大概率项目也用库里也用。即便有依赖没加载上,回头再打个胖包也是可以的。

但是这不是本猿现在要的。


肿么办才好

既然在仓库里缺了pom.xml那就补上咯,再敲一次命令,其中补上参数-DgeneratePom=false,-Dfile=指向E库的pom.xml,执行如下:

$ mvn deploy:deploy-file -Dfile=/server/data/ejoker/pom.xml -DgroupId=pro.jiefzz -DartifactId=ejoker -Dversion=${VERSION} -Dpackaging=pom -Durl=file:./minimal-maven-repository/ -DrepositoryId=minimal-maven-repository -DupdateReleaseInfo=true -DgeneratePom=false
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building willdelete 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ willdelete ---
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/1.2.0-snapshot/ejoker-1.2.0-snapshot.pom (7 KB at 354.7 KB/sec)
Downloading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Downloaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 27.9 KB/sec)
Uploading: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml
Uploaded: file:./minimal-maven-repository/pro/jiefzz/ejoker/maven-metadata.xml (314 B at 102.2 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.645 s
[INFO] Finished at: 2019-09-26T22:42:18+08:00
[INFO] Final Memory: 7M/123M
[INFO] ------------------------------------------------------------------------

再看看依赖树:

eclipse看项目依赖树

全部都出来了


再跑一下主类App :

输出

不再是刚刚的错误 而是一个RuntimeException,也就是依赖问题已经被解决,(这个运行时异常是因为本猿在createDefaultMQConsumer的第三个参数传入了null)


再附上一个Nexus私库时如果想最终项目能够继承这个依赖的话应该是这样的,下图红框的位置,同时上送你的jar和项目的pom.xml

输出


有问题欢迎指正😂

posted @ 2019-09-27 00:20  车干飞  阅读(7830)  评论(5编辑  收藏  举报