赞
踩
开发JAVA工程代码(main方法启动)如何构建出可以通过java -jar命令直接执行的jar?如果工程中依赖其他jar又如何处理?本文即针对以上两点通过IDEA开发工具来做一个简单的分析和尝试,测试如下四种方法,如有瑕疵请轻喷。
如下所示通过IDEA创建一个本地JAVA工程,此处工程名JavaPackage1,在lib引入一个hutool-all-5.3.7.jar作为测试,目录结构如下点击运行JPackage1正常打印日期。
如何通过IDEA直接构建可执行jar呢?具体步骤如下:
选择File -> Project Structure
选择Arifacts->ADD->JAR->Form modules with dependencies
在Main Class栏选择要打包成jar文件的java类,点击OK
出现如下界面,点击ok。最后构建完成jar的启动相关信息会写入到META-INF/MANIFEST.MF清单文件中。
点击Build->Build Artifacts,参照以下两张图,最后在\out\artifacts\目录下生成j可执行ar文件
最后通过在cmd窗口直接执行java -jar JavaPackage1.jar 运行正常输出hutool工具类获取的日期
后续若修改代码后可直接执行Build->Build Artifacts生成jar,不需要再做前面的配置步骤。同时解压该生成的jar可以发现依赖的hutool工具类是以class文件全部打入进来了。其中生成的MANIFEST.MF文件很简单就指明了Main-Class启动类信息。
<?xml version="1.0" encoding="UTF8"?> <project name="buildJar" default="jar" basedir="."> <tstamp> <format property="TODAY" pattern="yyyy-MM-dd HH:mm:ss" /> </tstamp> <!-- 定义:打包生成的jar的名字 --> <property name="jar.name" value="JavaPackage2.jar"/> <!-- 定义:主类路径 --> <property name="main.class" value="com.xren.jpackage2.JPackage2"/> <property name="build.dir" value="${basedir}/build" /> <property name="classes.dir" value="${basedir}/classes" /> <property name="lib.dir" value="${basedir}/lib" /> <!--阶段1.删除之前生成的jar包--> <target name="clean"> <delete dir="${build.dir}"/> <delete dir="${classes.dir}"/> </target> <!--定义依赖jar路径--> <path id="lib.path"> <fileset dir="${lib.dir}"> <include name="*.jar"/> </fileset> </path> <!--阶段2.编译java文件--> <target name="compile" depends="clean"> <!--创建classes文件夹--> <mkdir dir="${classes.dir}"/> <!--编译java文件--> <javac srcdir="${basedir}/src" destdir="${classes.dir}" encoding="UTF8"> <!--编译依赖jar --> <classpath refid="lib.path"/> </javac> </target> <!--阶段3.生成可运行的jar包--> <pathconvert property="relate.classpath" pathsep=" "> <mapper> <chainedmapper> <flattenmapper /> <globmapper from="*" to="lib/*" /> </chainedmapper> </mapper> <path refid="lib.path" /> </pathconvert> <target name="jar" depends="compile"> <mkdir dir="${build.dir}"/> <!--指定清单文件 --> <manifest file="${build.dir}/MANIFEST.MF"> <!--主类路径--> <attribute name="Main-class" value="${main.class}"/> <!-- 引入依赖jar-classpath --> <attribute name="Class-Path" value="${relate.classpath}" /> <attribute name="Built-Date" value="${TODAY}" /> </manifest> <jar destfile="${build.dir}/${jar.name}" basedir="${classes.dir}" manifest="${build.dir}/MANIFEST.MF"> </jar> <!--拷贝依赖jar到当前build目录 --> <copy todir="${build.dir}/lib" > <fileset dir="${lib.dir}"></fileset> </copy> </target> </project>
此方式生成的jar需要和同级目录下的lib依赖引入才能运行成功,原因是在ant.xml文件中打包时已经在清单文件MANIFEST.MF里固定了lib路径。
如果想将外部的jar全部打入到jar中,需要在xml中做如下单独引入,最后jar可直接运行。xml配置及包结构如下:
<target name="jar" depends="compile">
<mkdir dir="${build.dir}"/>
<!--指定清单文件 -->
<manifest file="${build.dir}/MANIFEST.MF">
<!--主类路径-->
<attribute name="Main-class" value="${main.class}"/>
</manifest>
<jar destfile="${build.dir}/${jar.name}"
basedir="${classes.dir}"
manifest="${build.dir}/MANIFEST.MF">
<zipfileset src="${lib.dir}/hutool-all-5.3.7.jar"/>
</jar>
</target>
<dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
</dependencies>
如果hutool-all.jar依赖下载不了请检查IDEA的maven配置是否正确。
<build> <plugins> <!-- 使用maven-assembly-plugin插件打包 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <!--主类 --> <mainClass>com.xren.jpackage3.JPackage3</mainClass> </manifest> </archive> <descriptorRefs> <!-- 可执行jar名称结尾--> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
通过Maven-assembly插件构建的jar和ant构建出来的jar中结构基本一致,将依赖jar以class方式加入内容部,同时在打包配置文件中指定清单文件MANIFEST.MF的主启动类Main-Class。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.xren.jpackage4.JPackage4</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
利用maven-shade-plugin构建除了会生成可执行jar,还会在target目录下生成一个以original-开头的原始jar,该jar不可执行内部没有依赖其他,其清单文件MANIFEST.MF如下:
而可执行jar清单文件如下,差别就是多了一个Main-Class
**总结:**综上几种构建可执行jar的方式可知,其都有一个共同点-jar里面有一个包含Main-Class的MANIFEST.MF文件,Main-Class配置指向main方法的主启动类。jar依赖的其他程序会以lib-jar或者class文件的方式包含其中(此文只验证依赖jar,没有验证配置文件依赖)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。