起因是这样的,平时开发 Java 项目时,我积累了一些常用的工具方法,使用起来很方便,可以在一定程度上提高开发效率。最近,我想要做一个新的开源项目,任何人都可以克隆到本地并进行打包构建,然后使用。我计划在这个开源项目中引用我的工具 jar 包,但是遇到了一个问题,我的工具 jar 包没有发布到 Maven 中央仓库。我看了码农参上公众号上的一篇文章《发布了一个 jar 包到中央仓库,我的心好累…》,于是我放弃了。然而,我又想在新项目中引入我的工具 jar 包,以提高开发效率。我应该如何解决呢?
通过查找资料,找到一个解决方案,参考知乎文章《Java + SpringBoot + Maven + 外部 jar 打包》。基本思路是将 dependency.scope
设为 system
,并指定 systemPath
。然后在 build
中配置 resources
信息。具体详情如下:
在项目中, 新建 src
平级目录 lib
, 拷贝构建好的 jar 包 avatar-core
, 并以如下方式引入依赖
<dependency>
<groupId>org.enthusa.avatar</groupId>
<artifactId>avatar-core</artifactId>
<version>master-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/avatar-core-master-SNAPSHOT.jar</systemPath>
</dependency>
这样,在使用 IDEA 进行开发时,就能够找到所需的依赖,避免出现错误。然而,如果引用了 avatar-core
中的方法,例如 DateUtil.getDate()
,在打包构建完成后执行时,会报告以下错误:
java.lang.NoClassDefFoundError: org/enthusa/avatar/core/utils/DateUtil
也就是说, 在通过 spring-boot-maven-plugin
插件构建好的可执行 jar 包, 并没有自动把 /avatar-core-master-SNAPSHOT.jar
也打进来. 通过 unzip
解压缩查看, 也验证了这一点.
于是, 我们在 build
中配置 resources
信息, 指定 lib
下的 jar 包也是 resource, 需要拷贝到 BOOT-INF/lib/
目录下.
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>lib</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>*.jar</include>
</includes>
</resource>
</resources>
重新打包后执行, 又会报如下错误:
java.lang.ClassNotFoundException: org.apache.commons.lang3.time.DateFormatUtils
大致可以想到,avatar-core
依赖于 commons-lang3
。但是通过上述方式引入 avatar-core
时,并没有自动引入它的依赖包。这个问题很容易解决,在这个项目中再次手动引入 commons-lang3
就可以解决了。
如果要使用 system scope 这种方式引入 jar 包 (实际工作中很少遇到), 建议不要在项目 project 下, 再分模块 module, 在 module 中引入 system scope 依赖. 因为这种方式引入的依赖, 不会传递, 带来更多麻烦.
- 后端代码地址: https://github.com/enthusa/askdata-backend (代码镜像)
- 前端代码地址: https://github.com/enthusa/askdata-frontend
- 体验地址: https://askdata.inscode.cc (刚刚开始, 敬请期待)