欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Maven把项目依赖的所有jar包都打到同一个jar中

程序员文章站 2022-04-08 17:45:41
Maven生成jar包时, 怎样把项目中依赖的jar包也包括进去? 这里介绍2种方式: 使用 shade插件, 和使用 assembly插件. 另外扩展Maven安装本地jar包到本地仓库的方法、手动生成jar包的方法、Linux下运行jar包的几种方式. ......

1 使用maven-shade-plugin

(1) 在项目的pom.xml文件中加入如下插件:

    <build>
        <plugins>
            <!-- maven shade plugin -->
            <plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-shade-plugin</artifactid>
                <version>3.2.0</version>
                <configuration>
                    <createdependencyreducedpom>true</createdependencyreducedpom>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.manifestresourcetransformer">
                                    <!-- 主类的全限定名 -->
                                    <mainclass>com.healchow.consumer.main</mainclass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

(2) 然后使用maven的package命令打包项目;

(3) 打包完成后, 即可在项目的target目录下看到生成的jar包;

(4) 不出差错的话, 使用java -jar xxxx.jar命令即可运行此jar包.

说明: 此方法在mac os系统下的idea中实施, 在jar/meta-inf/目录下有时会出现:

eclipsef.sf eclipse.rsa等文件, 并在运行java -jar xxx.jar时, 会抛出如下错误:

error: a jni error has occurred, please check your installation and try again
exception in thread "main" java.lang.securityexception: invalid signature file digest for manifest main attributes
        at sun.security.util.signaturefileverifier.processimpl(signaturefileverifier.java:330)
        at sun.security.util.signaturefileverifier.process(signaturefileverifier.java:263)
        at java.util.jar.jarverifier.processentry(jarverifier.java:318)
        at java.util.jar.jarverifier.update(jarverifier.java:230)
        at java.util.jar.jarfile.initializeverifier(jarfile.java:383)
        at java.util.jar.jarfile.getinputstream(jarfile.java:450)
        at sun.misc.urlclasspath$jarloader$2.getinputstream(urlclasspath.java:977)
        at sun.misc.resource.cachedinputstream(resource.java:77)
        at sun.misc.resource.getbytebuffer(resource.java:160)
        at java.net.urlclassloader.defineclass(urlclassloader.java:454)
        at java.net.urlclassloader.access$100(urlclassloader.java:73)
        at java.net.urlclassloader$1.run(urlclassloader.java:368)
        at java.net.urlclassloader$1.run(urlclassloader.java:362)
        at java.security.accesscontroller.doprivileged(native method)
        at java.net.urlclassloader.findclass(urlclassloader.java:361)
        at java.lang.classloader.loadclass(classloader.java:424)
        at sun.misc.launcher$appclassloader.loadclass(launcher.java:335)
        at java.lang.classloader.loadclass(classloader.java:357)
        at sun.launcher.launcherhelper.checkandloadmain(launcherhelper.java:495)

解决办法是: 手动删除jar包中meta-inf/*.rsa meta-inf/*.dsa meta-inf/*.sf这些文件, 然后就可行了.

2 推荐: 使用maven-assembly-plugin

(1) 在项目的pom.xml文件中加入如下插件:

     <build>
        <plugins>
            <!-- maven assembly plugin -->
            <plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-assembly-plugin</artifactid>
                <version>2.4.1</version>
                <configuration>
                    <!-- get all project dependencies -->
                    <descriptorrefs>
                        <descriptorref>jar-with-dependencies</descriptorref>
                    </descriptorrefs>
                    <!-- mainclass in mainfest make a executable jar -->
                    <archive>
                        <manifest>
                            <mainclass>com.healchow.consumer.main</mainclass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <!-- 配置执行器 -->
                    <execution>
                        <id>make-assembly</id>
                        <!-- 绑定到package命令的生命周期上 -->
                        <phase>package</phase>
                        <goals>
                            <!-- 只运行一次 -->
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
         </plugins>
     </build>

(2) 然后使用maven的package命令打包项目;

(3) 打包完成后, 即可在项目的target目录下看到生成的jar包, 其中xxx-jar-with-dependencies.jar是包含依赖jar包的jar文件, 另一个不包含依赖jar包;

(4) 使用java -jar xxxx.jar命令即可运行此jar包.

3 扩展: maven安装本地jar包到本地仓库

命令如下:

mvn install:install-file -dfile=base-util-1.0.release.jar -dgroupid=com.healchow -dartifactid=base-util -dversion=1.0.release -dpackaging=jar

其他命令, 参考这篇博客: maven常用命令.

4 扩展: 手动生成jar包

创建可执行 jar 包的关键在于:让java -jar命令知道 jar 包中的主方法属于哪个类 —— 要配置主类的全限定名.

步骤如下:

(1) 打包指定的项目:

进入项目所在的根目录, 以linux系统为例:

项目名是java-test, 其所在的目录是/data/project/java-test;

main方法所属的类的全限定名是com.healchow.test.main:

# 进入项目所在的根目录:
cd /data/project
# 运行打包命令: 
jar  cvfe  test.jar  java-test.com.healchow.test.main  java-test 

上述命令说明: 将java-test目录下的所有文件打包到test.jar中, 并指定主类的全限定名称, 这里要指明主类所在的文件夹.

关于jar命令的其他用法, 参考如下:

# 用法: jar {ctxui}[vfmn0pme] [jar-file] [manifest-file] [entry-point] [-c dir] files ...
# 选项:
 -c  创建新档案
 -t  列出档案目录
 -x  从档案中提取指定的 (或所有) 文件
 -u  更新现有档案
 -v  在标准输出中生成详细输出
 -f  指定档案文件名
 -m  包含指定清单文件中的清单信息
 -n  创建新档案后执行 pack200 规范化
 -e  为捆绑到可执行 jar 文件的独立应用程序指定应用程序入口点
 -0  仅存储; 不使用任何 zip 压缩
 -p  保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
 -m  不创建条目的清单文件
 -i  为指定的 jar 文件生成索引信息
 -c  更改为指定的目录并包含以下文件
# 如果任何文件为目录, 则对其进行递归处理。
# 清单文件名, 档案文件名和入口点名称的指定顺序 与 'm', 'f' 和 'e' 标记的指定顺序相同。

示例 1: 将两个类文件归档到一个名为 classes.jar 的档案中: 
    jar cvf classes.jar foo.class bar.class 
示例 2: 使用现有的清单文件 'mymanifest' 并将 foo/ 目录中的所有文件归档到 'classes.jar' 中: 
    jar cvfm classes.jar mymanifest -c foo/ .

(2) 运行jar包:

用解压软件打开上一步生成的jar包, 查看meta-inf/manifest.mf文件, 里面如果有main-class: com.healchow.test.main, 说明打包成功.

# 在当前目录下, 运行jar包: 
java -jar test.jar

5 扩展: linux下运行jar包的几种方式

5.1 阻塞式方式

java -jar xxx.jar

特点: 当前终端的会话窗口被阻塞, 可按ctrl + c中断程序的运行, 或者直接关闭会话窗口 —— 此时jar程序将终止.

5.2 后台运行方式

# 通过"&"符号实现后台运行: 
java -jar xxx.jar &

特点: 当前终端的会话窗口不会被阻塞, 但是如果关闭当前窗口, 程序将终止运行.

5.3 后台持续运行方式

# 通过"nohup"命令实现后台运行: 
nohup java -jar xxx.jar &

nohup命令是不挂断运行命令的意思.

特点: 当用户退出或终端关闭时, 程序的运行不受影响.

说明: 用nohup命令运行任务时, 默认情况下这个任务的所有输出都将被重定向到nohup.out文件中, 除非另外指定输出文件. 指定输出文件方式为:

# 将输出重定向到xxx.log文件中: 
nohup java -jar xxx.jar > xxx.log &

> 符号是重定向符, 实现: 把它之前命令的所有输出信息重定向到后面的文件中, 而不是显示到屏幕上.

5.4 其他命令扩展

① 通过jobs命令可以查看后台运行任务, 会给每个任务指定一个编号.
② 通过fg命令可以把指定编号的后台任务调回到前台控制, 如: fg 10 —— 把10号任务调回前台.
③ 查看占用某个端口的进程:

netstat -nlp | grep 2181
# 下述结果说明进程号pid=18434的java进程占用了2181端口
tcp        0      0 :::2181          :::*           listen      18434/java

参考资料

使用maven的assembly插件实现自定义打包

maven构建可执行的jar包(包含依赖jar包)

版权声明

作者: ma_shoufeng(马瘦风)

出处: 博客园

您的支持是对博主的极大鼓励, 感谢您的阅读.

本文版权归博主所有, 欢迎转载, 但请保留此段声明, 并在文章页面明显位置给出原文链接, 否则博主保留追究相关人员法律责任的权利.