浅谈java 中构建可执行 jar 包的几种方式

概述

      有时候,由于项目的需要,我们会将源码编译后以工具包(即将class打成jar包)的形式对外提供,此时,你的 jar 包不一定要是可执行的,只要能通过编译,能被别的项目以 import 的方式调用就行了。

       但还有的情况是,我们的 jar 包是要可执行的,即能直接在 cmd 下直接通过java -jar的命令运行。

       前者的打包很简单,在 eclipse 中,直接选中要打包的 java 文件和其它资源、依赖文件, export → Java → JAR file 即可。需要注意的是,这种方式导出的 jar 包是不可执行的,比如你执行如下的语句:
java -jar test.jar
java -classpath test.jar com.test_maven.App
      会直接报错:无法找到主类或者找不到 xxx 依赖包/类,这是由于你没有定义 MANIFEST.MF 资源描述文件所致。另一个原因可能是你直接把依赖的 jar 包打进了你最终的 jar,而这种嵌套的依赖 jar 包是不能直接被程序 import 识别的。

 

如何构建可执行Jar包
        

方法1、最简单的还是依赖于 eclipse 的导出功能

export → java → Runnable JAR file,这种形式的导出可以通过 lanuch configuration 指定一个 MainClass,并会自动生成 MANIFEST.MF ,而且会帮你把依赖的 jar 包解压出来,一并打进最终的 jar 包,这样就能被你的代码 import 引用了。

 


 

 

方法2、利用Eclipse的Fat Jar

       上述方法是 eclipse 自带的,此外eclipse 也有个专门的插件叫做 Fat Jar,支持许多定制化的功能,但是这个插件有些缺陷,比如修改源码后如果你不 clean & rebuild project, 它会使用缓存重新打包,这样你的编译代码还是老的,会造成执行错误,而且这样是十分不方便的。用Fat Jar Eclipse Plug-In打包可执行jar文件

 

 

方法3、利用Maven的插件

    

3.1: 基于Maven构建的项目最好的方式:

          将项目所支持的所有类库打在一个包中,而不是只将项目编译打包到一个jar中。这样便可以直接拷贝一个jar去执行了。

 

Xml代码   收藏代码
  1. <plugin>  
  2.                 <artifactId>maven-assembly-plugin</artifactId>  
  3.                 <configuration>  
  4.                     <appendAssemblyId>false</appendAssemblyId>  
  5.                     <descriptorRefs>  
  6.                         <descriptorRef>jar-with-dependencies</descriptorRef>  
  7.                     </descriptorRefs>  
  8.                     <archive>  
  9.                         <manifest>  
  10.                             <mainClass>com.ebay.montage.eventprocessor.collector.CodeRollOutEventDataCollector</mainClass>  
  11.                         </manifest>  
  12.                     </archive>  
  13.                 </configuration>  
  14.                 <executions>  
  15.                     <execution>  
  16.                         <id>make-assembly</id>  
  17.                         <phase>package</phase>  
  18.                         <goals>  
  19.                             <goal>assembly</goal>  
  20.                         </goals>  
  21.                     </execution>  
  22.                 </executions>  
  23.             </plugin>  

 

使用命令:

mvn assembly:assembly -DskipTests

这里就会在target目录下生成 {project}.jar文件,

直接运行jar文件: Java -jar  {project}.jar

    备注:当然也可以使用mvn clean install -DskipTests 来构建生成jar包。

 

 需要注意的是,这种方式在新版本的Maven或者Spring中很多时候执行jar包会出现类似如下的exception:

 

Xml代码   收藏代码
  1. Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]  
 其原因是新版本的Maven中推荐使用shade来替代assembly方式,于是可以使用如下的命令来代替上面的命令以解决 Spring NamespaceHandler for XML schema namespace的异常问题

 

 

Xml代码   收藏代码
  1. <plugin>  
  2.      <groupId>org.apache.maven.plugins</groupId>  
  3.      <artifactId>maven-shade-plugin</artifactId>  
  4.      <version>2.1</version>  
  5.      <executions>  
  6.     <execution>  
  7.          <phase>package</phase>  
  8.         <goals>  
  9.         <goal>shade</goal>  
  10.         </goals>  
  11.           <configuration>  
  12.         <transformers>  
  13.           <transformer  
  14.     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  15.         <resource>META-INF/spring.handlers</resource>  
  16.         </transformer>  
  17.         <transformer  
  18.     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  19.         <resource>META-INF/spring.schemas</resource>  
  20.     </transformer>  
  21.         <transformer  
  22. implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
  23.     <mainClass>com.chuanliu.c11.bootstrap.C11SearcherBootStrap</mainClass>  
  24.     </transformer>  
  25.     </transformers>  
  26.   
  27.     <filters>  
  28.       <filter>  
  29.         <artifact>*:*</artifact>  
  30.             <excludes>  
  31.         <exclude>META-INF/*.SF</exclude>  
  32.         <exclude>META-INF/*.DSA</exclude>  
  33.         <exclude>META-INF/*.RSA</exclude>  
  34.         </excludes>  
  35.     </filter>  
  36.     </filters>  
  37.     </configuration>  
  38.     </execution>  
  39.        </executions>  
  40. </plugin>  
该命令有几点需要注意:
1、MainClass必须要指定,否则在运行打包生成的Jar包后,会报这样一个错误:“没有主清单属性”
Java代码   收藏代码
  1. <transformer  
  2. implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
  3.     <mainClass>com.chuanliu.c11.bootstrap.C11SearcherBootStrap</mainClass>  
  4.     </transformer>  
 
2、执行生成的Jar包的时候,有时候还会出现: SecurityException: Invalid signature file digest

 

这是由于在META-INF下会有多余的以SF结尾的文件,用winrar打开jar包并删除META-INF下的SF结尾的文件后,执行就不会出现改问题,但更好的方法就是像上面一样,生成可执行jar包时加入filters命令

Xml代码   收藏代码
  1. <filters>  
  2.       <filter>  
  3.         <artifact>*:*</artifact>  
  4.             <excludes>  
  5.         <exclude>META-INF/*.SF</exclude>  
  6.         <exclude>META-INF/*.DSA</exclude>  
  7.         <exclude>META-INF/*.RSA</exclude>  
  8.         </excludes>  
  9.     </filter>  
  10. </filters>  

  

 

      3.2: 在 maven 工程中,我们也可以很方便的打包成可执行的 jar 包。默认Maven生成的JAR包只包含了编译生成的.class文件和项目资源文件,而要得到一个可以直接在命令行通过java命令运行的JAR文件,还要满足两个条件:

 

  • JAR包中的/META-INF/MANIFEST.MF元数据文件必须包含Main-Class信息。
  • 项目所有的依赖都必须在Classpath中,其可以通过 MANIFEST.MF 指定或者隐式设置。

 

Xml代码   收藏代码
  1. <plugins>  
  2.      <plugin>  
  3.     <groupId>org.apache.maven.plugins</groupId>  
  4.     <artifactId>maven-jar-plugin</artifactId>  
  5.     <configuration>  
  6.     <archive>  
  7.     <manifest>  
  8.         <addClasspath>true</addClasspath>  
  9.         <classpathPrefix>lib/</classpathPrefix>  
  10.         <mainClass>com.ebay.montage.eventprocessor.collector.MySpace</mainClass>  
  11.     </manifest>  
  12.     <manifestEntries>  
  13.         <Class-Path>.</Class-Path>  
  14.     </manifestEntries>  
  15.     </archive>  
  16.   
  17.     finalName>eventprocessor</finalName>  
  18.     <!-- <excludes>  
  19.         <exclude>**/*.properties</exclude>  
  20.         <exclude>**/*.xml</exclude>  
  21.     </excludes> -->  
  22.     </configuration>  
  23.     </plugin>  
  24.   
  25.        <plugin>  
  26.     <groupId>org.apache.maven.plugins</groupId>  
  27.     <artifactId>maven-dependency-plugin</artifactId>  
  28.         <executions>  
  29.         <execution>  
  30.             <id>copy-dependencies</id>  
  31.             <phase>prepare-package</phase>  
  32.             <goals>  
  33.             <goal>copy-dependencies</goal>  
  34.             </goals>  
  35.             <configuration>  
  36.             <outputDirectory>${project.build.directory}/lib</outputDirectory>  
  37.             <overWriteReleases>false</overWriteReleases>  
  38.             <overWriteSnapshots>false</overWriteSnapshots>  
  39.             <overWriteIfNewer>true</overWriteIfNewer>  
  40.             </configuration>  
  41.             </execution>  
  42.         </executions>  
  43.     </plugin>  
  44.     </plugins>  

 

使用mvn clean install -DskipTests打jar 包。

 

 

这样打好jar包后就可以使用:java -jar eventprocessor.jar Myspace, 

当然了前提是在Myspace中有一个main方法。这样便可直接去执行Myspace中的main方法了。

但是如果要将jar包放到别的机器上去运行的话,需要将targe中的lib下的内容(上面命令中指定)也同样拷贝过去,因为默认情况下:maven只是将项目编译打包到一个jar中,而其它的类库在上面手动的指定被放到了lib中,所以在执行的时候必须要引用才行。

 


 

 

附:如果对Maven感兴趣,如下文章的几个功能有必要了解一下:关于 Apache Maven 您不知道的 5 件事

http://www.ibm.com/developerworks/cn/java/j-5things13/

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值