Java 是否可以创建一个包含项目类和项目依赖项的“uber”jar 作为带有自定义清单文件的 jars?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1832853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:05:18  来源:igfitidea点击:

Is it possible to create an "uber" jar containing the project classes and the project dependencies as jars with a custom manifest file?

javamaven-2build-processmaven-pluginuberjar

提问by please delete me

I'm trying to create a executable jar(using maven) that contains the project classes and it's dependencies with a manifest file that has the entry for the main class and the class path entry that points to the dependencies packed in the root of the jar;something like this :

我正在尝试创建一个包含项目类的可执行 jar(使用 maven),并且它与一个清单文件的依赖项具有主类的条目和指向打包在 jar 根目录中的依赖项的类路径条目;像这样:

Manifest File:

清单文件:

.....
Main-Class : com.acme.MainClass
Class-Path : dependecy1.jar dependecy2.jar
.....

Jar:

罐:

jar-root
|-- ....
|-- com/acme/../*.class
|-- dependecy1.jar
`-- dependecy2.jar

I'm using the maven-jar-plugin to create the manifest file and the maven-shade-plugin to create the "uber" jar but the dependencies are unpacked and added as classes to my jar.

我正在使用 maven-jar-plugin 创建清单文件,并使用 maven-shade-plugin 创建“uber”jar,但依赖项已解包并作为类添加到我的 jar 中。

采纳答案by Pascal Thivent

Actually, I didn't check what the maven-shade-pluginis doing exactly (or any other plugin) as maven 2 has everything built-in to create a megajar or uberjar. You just have to use the maven-assembly-plugin with the predefined jar-with-dependenciesdescriptor.

实际上,我没有检查maven-shade-plugin正在做什么(或任何其他插件),因为 maven 2 内置了所有内容来创建 megajar 或 uberjar。您只需要使用带有预定义jar-with-dependencies描述符的 maven-assembly-plugin 即可。

Just add this snippet to your pom.xmlto customize the manifest:

只需将此代码段添加到您pom.xml的自定义清单中即可:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

And the following command will generate your uberjar:

以下命令将生成您的 uberjar:

mvn assembly:assembly -DdescriptorId=jar-with-dependencies

But, again, the default behavior of this descriptor is to unpack dependencies (like the maven-shade-plugin). To be honest, I don't get why this is a problem but, if this is really not what you want, you can use your own custom assembly descriptor.

但是,同样,这个描述符的默认行为是解包依赖项(如 maven-shade-plugin)。老实说,我不明白为什么这是一个问题,但是,如果这真的不是您想要的,您可以使用您自己的自定义程序集描述符。

To do so, first, create your assembly descriptor, let's say src/assembly/uberjar.xml, with the following content:

为此,首先,创建您的程序集描述符,比方说src/assembly/uberjar.xml,具有以下内容:

<assembly>
  <id>uberjar</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <unpack>false</unpack>
      <scope>runtime</scope>
      <useProjectArtifact>false</useProjectArtifact>
    </dependencySet>
  </dependencySets>
  <fileSets>
    <fileSet>
      <directory>${project.build.outputDirectory}</directory>
      <outputDirectory>/</outputDirectory>
    </fileSet>
  </fileSets>
</assembly>

Then, configure the maven-assembly-plugin to use this descriptor and to add the dependencies to the Class-Pathentry of the manifest:

然后,配置 maven-assembly-plugin 以使用此描述符并将依赖Class-Path项添加到清单的条目中:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <descriptors> 
      <descriptor>src/assembly/uberjar.xml</descriptor>
    </descriptors>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
        <addClasspath>true</addClasspath>
      </manifest>
    </archive>
  </configuration>
  <!--
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
  -->
</plugin>

Finally run mvn assembly:assemblyto produce your uberjar.

最后运行mvn assembly:assembly以生成您的 uberjar。

Optionally, uncomment the executionselement to bind the assembly plugin on the packagephase (and have the assembly produced as part of the normal build).

或者,取消注释executions元素以在package阶段上绑定程序集插件(并将程序集作为正常构建的一部分生成)。

回答by Carl Smotricz

I know of two products that do this:

我知道有两种产品可以做到这一点:

  • One is called 'bigjar', but that's too general a term to be useful in a Google search; I wasn't able to find it.
  • The other is called 'onejar'. There's quite a few references to it, and it claims to do what you need.
  • 一个叫做“bigjar”,但这个词太笼统,在谷歌搜索中没有用;我无法找到它。
  • 另一个被称为“onejar”。有很多对它的引用,它声称可以满足您的需求。

Here's a post from someone who uses OneJar in a Maven assembly:

这是一个在 Maven 程序集中使用 OneJar 的人的帖子:

http://5341.com/list/55/498657.html

http://5341.com/list/55/498657.html

回答by Karl

I've used FatJar for this in the past. http://fjep.sourceforge.net/

我过去曾为此使用过 FatJar。 http://fjep.sourceforge.net/

I had created a relatively simple application, the client was going to want to double click on an executable and have it just work. Installers or dependencies are out of the question. Fatjar bundled up the project libraries and referenced files from Eclipse into a several megabyte executable jar for me. Flawless.

我创建了一个相对简单的应用程序,客户端想要双击一个可执行文件并让它正常工作。安装程序或依赖项是不可能的。Fatjar 将 Eclipse 中的项目库和引用文件捆绑到一个数兆字节的可执行 jar 中。完美无瑕。

回答by skaffman

回答by Priyanshu Shekhar

task uberJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'main.RunTest'
    }
    dependsOn configurations.runtimeClasspath
    from sourceSets.main.output
    from sourceSets.test.output
    from sourceSets.main.resources
    from sourceSets.test.resources
    from {
        configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
    }
    from {
        project(':someothermoudule').sourceSets.main.resources // If current project depends on some other modules
        project(':someothermoudule').sourceSets.test.resources // If current project depends on some other modules
    }
    exclude 'META-INF/*.RSA'
    exclude 'META-INF/*.SF'
    exclude 'META-INF/*.DSA'
}

In case of gradle above can help. Note the from { project('')}lines, this is only required when the current project depends on some other sub projects or modules.

如果上面的gradle可以提供帮助。请注意这些 from { project('')}行,这仅在当前项目依赖于其他一些子项目或模块时才需要。