【问题标题】:How to create spring-based executable jar with maven?如何使用 maven 创建基于 spring 的可执行 jar?
【发布时间】:2012-06-25 00:12:11
【问题描述】:

我有一个基于 Maven 的 Spring-WS 客户端项目,我想将其打包为单个 jar。在eclipse中,一切运行正常。当我尝试将其打包为可执行 jar 时,我收到 ClassNotFound 异常,因为 Spring jar 不包含在我的应用程序 jar 中。

所以我添加了 maven-shade-plugin 以在我的应用程序 jar 中包含我的所有依赖项。当我查看我的应用程序 jar 时,我会看到所有依赖项中的所有类文件(所有库 jar 都已分解)。

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.cws.cs.Client</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>

        </plugin>
    </plugins>
</build>

我的问题是,在打包过程中,我的多个spring依赖有不同的META-INF/spring.schemas文件相互覆盖。因此,我的最终 jar 有一个不完整的 spring.schemas 文件。

因此,当我尝试运行可执行 jar 时,我收到 Spring 错误消息,指出由于 spring.schemas 文件不完整(Spring-WS 的 jar 已覆盖 Spring-core 的 spring.schemas 文件),因此无法找到文件。

我的可执行 jar 的 META-INF/spring.schemas:

http\://www.springframework.org/schema/web-services/web-services-1.5.xsd=/org/springframework/ws/config/web-services-1.5.xsd
http\://www.springframework.org/schema/web-services/web-services-2.0.xsd=/org/springframework/ws/config/web-services-2.0.xsd
http\://www.springframework.org/schema/web-services/web-services.xsd=/org/springframework/ws/config/web-services-2.0.xsd

而不是 Spring-beans.jar META-INF/spring.schemas:

http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd

我被难住了。我不确定是否/如何将所有内容打包为单个可执行 jar。我不知道这是否是一个阴影插件配置问题,或者我是否正在尝试做一些不可能的事情。我必须手动创建自己的 spring.schemas 文件(其他文件的串联)似乎不正确。

我可能有点过激了。在挖掘有关阴影插件的更多信息时,我注意到了我之前错过的AppendingTransformer。但是,我关心的是如何知道哪些其他文件有同样的问题?我发现/发现了这个特殊的 Spring 问题。我不知道任何其他图书馆可能正在做类似的事情......

任何建议将不胜感激。

【问题讨论】:

  • 效果很好的替代方法是将 Spring jar 放入单独的 lib 文件夹中,并将此 lib 文件夹添加到清单中的类路径中 - 请参阅 André Aronsen 的回答 stackoverflow.com/a/4323501/241986

标签: java spring maven spring-ws maven-shade-plugin


【解决方案1】:

您可以添加以下配置,以便将所有 jar 中的 .schema 文件的内容附加在一起。

<configuration>
  <transformers>
    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
      <resource>META-INF/spring.handlers</resource>
    </transformer>
    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
      <resource>META-INF/spring.schemas</resource>
    </transformer>
  </transformers>
</configuration>

【讨论】:

  • 谢谢 - 我看到了同样的事情,并且刚刚编辑了我的问题以包含该信息。我的问题/问题是如何知道是否还有其他库可能遇到类似问题?不能指望我知道我使用的所有库的所有 META-INF 文件夹的内容...
  • 可能无法通过分析得出结论。唯一可行的选择是执行一些测试,确保它正常工作并修复任何损坏的东西。
  • @gkamal 是什么意思get appended together 打包在jar 中时不是具有相同文件名的文件相互覆盖吗? jar中同名的不同文件怎么不会冲突?
  • @Jas - 如果添加了上述配置,maven shade 插件会将文件附加在一起。
【解决方案2】:

使用 onejar-maven-plugin 代替 maven-shade-plugin。 One-JAR 让您可以将 Java 应用程序及其依赖 Jar 打包到一个可执行 Jar 文件中。

【讨论】:

【解决方案3】:

你试过maven-assembly-plugin吗?

它会为你创建一个带有依赖项的 jar,而且它可以使这个 jar 可执行:

使用 mainClass 指定要执行的类。

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.3</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>org.sample.App</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-assembly</id> <!-- this is used for inheritance merges -->
        <phase>package</phase> <!-- bind to the packaging phase -->
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

【讨论】:

  • Shade 和组装插件是同一个概念。它们都会分解依赖关系并尝试将它们包含在同一区域中。当多个依赖项在同一路径中有文件时,两者都会遇到问题(例如:META-INF/spring.schemas)
【解决方案4】:

昨天我也遇到了这个问题。

解决方案是通过手动连接和配置程序集插件来准备所需的文件:

  <files>
    <file>
        <source>src/META-INF/spring.schemas</source>
        <outputDirectory>META-INF</outputDirectory>
    </file>
    <file>
        <source>src/META-INF/spring.handlers</source>
        <outputDirectory>META-INF</outputDirectory>
    </file>
  </files>
  <dependencySets>
    <dependencySet>
      <outputDirectory>/</outputDirectory>
      <useProjectArtifact>true</useProjectArtifact>
      <unpack>true</unpack>
      <scope>runtime</scope>
      <unpackOptions>
        <excludes>
            <exclude>META-INF/spring.handlers</exclude>
            <exclude>META-INF/spring.schemas</exclude>
        </excludes>
      </unpackOptions>  
    </dependencySet>
  </dependencySets>

注意:使用一个 jar 方法还不够好 - 你不能确定手头的混合文件,尽量保持原样导出所有依赖项......

【讨论】:

    【解决方案5】:
    assembly plugin have issues, use below plugin
    
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>at.seresunit.lecturemanager_connector.App</mainClass>
                        </transformer>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                            <resource>META-INF/spring.handlers</resource>
                        </transformer>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                            <resource>META-INF/spring.schemas</resource>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
    you may get security exception resolve it using below configuration
    
     <configuration>
        <filters>
            <filter>
                <artifact>*:*</artifact>
                <excludes>
                    <exclude>META-INF/*.SF</exclude>
                    <exclude>META-INF/*.DSA</exclude>
                    <exclude>META-INF/*.RSA</exclude>
                </excludes>
            </filter>
        </filters>
    </configuration>
    

    【讨论】:

      【解决方案6】:

      对于希望为 Spring Boot 应用程序找到答案的人,您只需要:

      <build>
          <plugins>
              <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
              </plugin>
          </plugins>
      </build>
      

      【讨论】:

        猜你喜欢
        • 2019-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 2012-06-13
        相关资源
        最近更新 更多