【问题标题】:Spring Boot Maven Plugin - No BOOT-INF directorySpring Boot Maven 插件 - 没有 BOOT-INF 目录
【发布时间】:2017-08-24 18:59:13
【问题描述】:

在 spring-boot-maven-plugin 的 1.3.8.RELEASE 版本和 1.4.0.RELEASE 版本之间 - 生成的包结构发生了变化(如果您提取 uber jar 文件) 1.3.8.RELEASE com、lib、META-INF 和 org 目录 1.4.0.RELEASE 有 BOOT-INF、META-INF 和 org 目录 基本上从 1.4.0.RELEASE 开始——所有的类和库都在 BOOT-INF 目录中。 因此 - 当您尝试在 Amazon Lambda 上运行 Spring Boot 项目时 - 它说找不到 jar,因为它无法读取新的 Spring Boot Uber jar 结构

我的问题是 - 在较新版本的 Spring Boot Maven 插件中是否有可能让它生成与版本 1.3.9.RELEASE 相同的结构的 uber jar?

我尝试了 maven-shade-plugin - 但这会导致其他问题

非常感谢任何帮助

谢谢 达米安

【问题讨论】:

    标签: java spring maven spring-boot spring-boot-maven-plugin


    【解决方案1】:

    解决方案是在 pom.xml 文件中为插件添加 MODULE 布局

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <layout>MODULE</layout>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    【讨论】:

    • 为什么没有人将其标记为正确答案。当我升级弹簧靴时,我遇到了类似的问题。对 docs.Spring 的描述感到困惑。添加这件作品。MODULE
    • 如何为 build.gradle 做到这一点?我正在使用以下插件类路径“org.springframework.boot:spring-boot-gradle-plugin:1.4.2.RELEASE”,因此,我的胖罐子具有以下结构 BOOT-INF MATA-INF org.springframework.boot .loader 但我想要下面的结构 > META-INF
    • 它说,未能执行目标 org.springframework.boot:spring-boot-maven-plugin:2.1.2.RELEASE:repackage (repackage) on project businessunit-service-businessunit: Unable to parse mojo org.springframework.boot 的配置:spring-boot-maven-plugin:2.1.2.RELEASE:repackage:无法将“模块”转换为枚举:没有枚举常量 org.springframework.boot.maven.RepackageMojo.LayoutType.MODULE - > [帮助1]
    【解决方案2】:

    在我的情况下,我使用的是 spring boot 2.X,我在 maven-dependency-plugin 之后声明了 spring-boot-maven-plugin(我曾经在 Docker 中解压并创建分解的应用程序),它必须在解压之前,这是有道理的,它在spring boot maven插件执行之前被解包。下次我将在插件链中声明它的第一件事,为此浪费了一个多小时。希望它可以帮助某人。

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>${spring.boot.mainClass}</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>unpack</id>
                        <phase>package</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>${project.groupId}</groupId>
                                    <artifactId>${project.artifactId}</artifactId>
                                    <version>${project.version}</version>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    【讨论】:

    • 我还通过将我的 maven-shade-plugin 声明放在 pom.xml 中的 spring-boot-maven-plugin 声明之前,让我的设置正常工作。生成的 shade jar 按预期在根目录中包含所有内容,而 Spring boot jar 按预期在 BOOT-INF 中包含所有内容。
    【解决方案3】:

    上面的答案用

    <layout>MODULE</layout>
    

    不再起作用,这是因为 layout 元素在 Spring Boot 2.x 中已被弃用。 我正在使用 Spring Boot 2.0.x,我在 github 上发现了这条有用的评论:

    在 Spring Boot 2.0 中删除了对模块布局的支持,在 1.5 中已弃用。不幸的是,Maven 插件文档的更新被遗漏了,所以我们可以使用这个问题来解决这个问题。您应该改用custom LayoutFactory

    但由于我不想实现 LayoutFactory,所以我尝试了下面的第二个解决方案,它实际上重新打包并创建了一个带有给定名称的分类器的额外 jar:

    这是由于 Spring Boot 1.4 中可执行 jar 的布局发生了变化。应用程序类现在打包在 BOOT-INF/classes 中。 您的客户端模块依赖于重新打包的 web 模块的胖 jar。由于新布局意味着客户端模块无法再加载 Web 模块的类。如果你想使用你的 web 模块作为依赖,你应该配置 Boot 的重新打包以将分类器应用于 fat jar。例如:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                        <configuration>
                            <classifier>exec</classifier>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    这样做将允许其他模块依赖于原始 jar,该 jar 没有嵌入模块的依赖项,并且在 jar 的根目录下具有类。

    一个原始罐子的结构与我想要的一样

    com.my-package.foo.bar
    META-INF
    

    第二个分类器具有更新的结构,带有 BOOT-INF/ 等。

    【讨论】:

    • 非常感谢。很好的回答
    【解决方案4】:

    对我来说,解决方案有点阴险......我将 spring-boot-maven-plugin 嵌套在 pluginManagement 下(见下文)。嗬!

    令人讨厌的是,当我运行 mvn spring-boot:run 时,spring boot 运行良好,并运行 app!直到我们尝试部署到 PCF(作为 spring-boot JAR),我们才得到一个错误,表明二进制格式有问题....

    <build>
    
      <!-- 
        DON'T DO THIS!! 
      -->
      <pluginManagement>
    
        <plugins>             
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring.boot.version}</version>            
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>                        
          </plugin>                                     
        </plugins>
    
      </pluginManagement>
    
      <!-- 
        DO THIS INSTEAD!! 
      -->      
    <plugins>
    
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <version>${spring.boot.version}</version>            
          <executions>
              <execution>
                  <goals>
                      <goal>repackage</goal>
                      <goal>build-info</goal>
                  </goals>
              </execution>
          </executions>                        
        </plugin>                         
    
      </plugins>
    
    </build>
    

    从 POM 中删除 pluginManagement 标记后,我现在将获得 ./BOOT-INF 结构。请记住,pluginManagement 通常用于父 pom 结构,您希望该插件的配置在其他模块中使用。

    【讨论】:

      【解决方案5】:

      我使用的是 Gradle,而不是 Maven,这是我必须做的:

      1- 在我的 build.gradle 中,我添加了 https://spring.io/guides/gs/spring-boot-Docker/ 中定义的以下属性。

      buildscript {
          ...
          dependencies {
              ...
              classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
          }
      }
      
      group = 'springio'
      
      ...
      apply plugin: 'com.palantir.docker'
      
      task unpack(type: Copy) {
          dependsOn bootJar
          from(zipTree(tasks.bootJar.outputs.files.singleFile))
          into("build/dependency")
      }
      docker {
          name "${project.group}/${bootJar.baseName}"
          copySpec.from(tasks.unpack.outputs).into("dependency")
          buildArgs(['DEPENDENCY': "dependency"])
      }
      

      2- 我的依赖文件夹没有被写入

      ARG DEPENDENCY=target/dependency
      

      相反,我将它放在另一个文件夹中,因此我在 Dockerfile 中更改了此属性:

      ARG DEPENDENCY=build/dependency
      

      这样我就成功构建了。

      【讨论】:

        猜你喜欢
        • 2020-01-30
        • 2018-11-09
        • 2016-10-30
        • 2014-06-20
        • 2017-03-26
        • 2020-11-03
        • 2018-11-07
        • 2018-11-30
        • 2018-01-07
        相关资源
        最近更新 更多