Spring Boot Maven 插件 - 没有 BOOT-INF 目录

Spring Boot Maven Plugin - No BOOT-INF directory

在 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 启动项目时 - 它说找不到 jar,因为它无法读取新的 Spring Boot Uber jar 结构

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

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

非常感谢任何帮助

谢谢 达米安

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

<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>

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

令人讨厌的是,当我 运行 mvn spring-boot:运行, spring 引导正常时,运行的应用程序!直到我们尝试部署到 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 结构,您希望该插件的配置在其他模块中使用。

上面的答案

<layout>MODULE</layout>

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

Support for the module layout was removed in Spring Boot 2.0 having been deprecated in 1.5. Unfortunately, the updates to the Maven Plugin's documentation were missed so we can use this issue to sort that out. You should use a custom LayoutFactory instead.

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

This is due to the change in layout of executable jars in Spring Boot 1.4. Application classes are now packaging in BOOT-INF/classes. Your client module depends on the repackaged, fat jar of your web module. Due to the new layout that means that the client module can no longer load the web module's classes. If you want to use your web module as a dependency, you should configure Boot's repackaging to apply a classifier to the fat jar. For example:

<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 的根目录中具有 类。

一个原始 jar 与我想要的结构相同

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

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

在我的例子中,我使用 spring 启动 2.X 并且我在 maven-dependency-plugin 之后声明了 spring-boot-maven-plugin(我曾经在Docker) 并且它必须在解包之前,这是有道理的,它在 spring boot maven 插件执行之前解包。下次我将在插件链中首先声明它,为此损失了 1 个多小时。希望对大家有帮助。

<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>

我使用的是 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

有了这个我就成功构建了。