jar包的多层级maven依赖的坑与正确传递方法
这个问题简述起来就是项目加载jar包但是无法加载jar包的依赖
这是一个maven的特性吗?
问题发生前
程序猿经常自己写一些库实现或收集常用的逻辑方法(算法和设计模式等等),以方便多个项目使用,避免重复编码。本猿现在有这么一个库,本猿把他叫 E库
, E库
用maven做工程和生命周期管理,以便能用到其他java工程中。同时库里面也引用了其他一些开源公共库,使用或包装他们以实现自己的功能。(如下是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主类:
鹅?! 找不到类?是本猿打开方式不对吗? 命令中敲一次mvn -Dmaven.test.skip=true clean compile package
-_-! 还真找不到啊。。。
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个依赖包,而junit
和ejoker
就直接是末端,没有更下层的依赖了
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] ------------------------------------------------------------------------
再看看依赖树:
全部都出来了
再跑一下主类App :
不再是刚刚的错误 而是一个RuntimeException,也就是依赖问题已经被解决,(这个运行时异常是因为本猿在createDefaultMQConsumer的第三个参数传入了null)
再附上一个Nexus私库时如果想最终项目能够继承这个依赖的话应该是这样的,下图红框的位置,同时上送你的jar和项目的pom.xml
有问题欢迎指正😂
出处:http://www.cnblogs.com/jiefzz/
微信公众号:冇
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
本文链接: