重新打包 Spring Boot Jar 时如何修复压缩错误

Posted

技术标签:

【中文标题】重新打包 Spring Boot Jar 时如何修复压缩错误【英文标题】:How to fix compression error when repackaging Spring Boot Jar 【发布时间】:2021-02-26 18:18:27 【问题描述】:

我需要将静态 UI 文件注入现有的 Spring Boot 可执行 jar。为此,我将 jar 作为依赖项,并使用 maven antrun 插件:

将jar解压到临时目录

在解压后的 jar 中添加资源目录

将静态 UI 文件复制到资源目录

重新压缩 jar

 <plugin>
   <artifactId>maven-assembly-plugin</artifactId>
   <version>3.1.0</version>
   <executions>
     <execution>
       <id>build-ui-kit</id>
       <phase>package</phase>
       <goals>
         <goal>single</goal>
       </goals>
       <configuration>
         <descriptors>
           <descriptor>ui-assembly-config.xml</descriptor>
         </descriptors>
       </configuration>
     </execution>
   </executions>
 </plugin>

 <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-antrun-plugin</artifactId>
   <version>1.6</version>
   <executions>
     <execution>
       <id>repack</id>
       <phase>compile</phase>
       <goals>
         <goal>run</goal>
       </goals>
       <configuration>
         <target>
           <!-- unzip jar -->
           <unzip src="$com.xxx:xxx:jar" dest="$project.build.directory/tmp"/>
           <!-- make resources dir in unzipped jar dir -->
           <mkdir dir="$project.build.directory/tmp/resources"/>
           <!-- copy ui files to resources dir -->
           <copy todir="$project.build.directory/tmp/resources">
             <fileset dir="$basedir/../../src/ui/dist">
               <include name="*"/>
             </fileset>
           </copy>
           <!-- zip tmp dir to create txapps jar  -->
           <zip basedir="$project.build.directory/tmp" destfile="$project.build.directory/yyyy.jar"/>
         </target>
       </configuration>
     </execution>
   </executions>
 </plugin>

这一切似乎都有效;但是,当我运行 Jar 时,出现以下错误:

原因:java.lang.IllegalStateException:无法打开嵌套条目“BOOT-INF/lib/HdrHistogram-2.1.12.jar”。它已经被压缩并且嵌套的jar文件必须在没有压缩的情况下存储。请检查用于创建可执行 jar 文件的机制

当我检查 Jar 的内容时,一切看起来都很好(库似乎没有被压缩)。对这里发生的事情有任何想法或对更好的重新打包解决方案的建议吗?谢谢!

【问题讨论】:

注入静态 UI 文件 听起来您使用的方法没有任何意义。为什么在最初构建 jar 时不包含这些文件,如果它们是可变的,为什么不将它们作为“sidecar”运行时资源提供? 在生产中,应用程序不提供 UI。我正在为开发人员添加一个调试 UI。 UI 文件不是可变的,但是在构建 Jar 时无法添加。当我使用 7-zip 手动添加文件时,一切正常,Spring 为 UI 提供服务。必须有一种简单的方法来自动化这个过程。 所以只需使用配置文件或启动配置属性禁用 UI 控制器。在不同的环境中部署不同的工件是在乞求难以诊断的错误。 错误信息听起来很全面!你是怎么做到的:“重新压缩罐子”? ;) 所以存在您的I need to inject static UI files into an existing Spring Boot executable jar. spring boot 应用程序的构建...那么为什么不更改该构建并在那里添加文件...到底是什么问题以及为什么要修改 spring-boot建好后的罐子? 【参考方案1】:

我最终使用 exec-maven-plugin 和 Java jar 实用程序来添加 UI 文件。见下面的代码(ui文件在/tmp/resources目录下):

<plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.0.0</version>
      <executions>
        <execution>
          <id>update-jar</id>
          <phase>package</phase>
          <goals>
            <goal>exec</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <executable>jar</executable>
        <workingDirectory>$project.build.directory/tmp</workingDirectory>
        <arguments>
          <argument>uf</argument>
          <argument>dependencies/myjar-$version.jar</argument>
          <argument>resources</argument>
        </arguments>
      </configuration>
    </plugin>

【讨论】:

以上是关于重新打包 Spring Boot Jar 时如何修复压缩错误的主要内容,如果未能解决你的问题,请参考以下文章

Gradle 如何打包 Spring Boot 可执行 JAR

spring boot 打包jar 失败,及运行jar失败如何解决

Spring boot如何引入本地jar包?

Spring Boot 外置配置文件

如何运行 spring boot 重新打包目标

如何使用新的spring-boot JAR重新启动容器而没有jar的绝对路径?