11

在 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 - 但这会导致其他问题

任何帮助是极大的赞赏

谢谢达米安

4

5 回答 5

20

解决方案是在 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>
于 2017-03-30T20:29:06.517 回答
10

在我的情况下,我使用的是 spring boot 2.X 并且我声明了spring-boot-maven-pluginafter maven-dependency-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>
于 2019-12-17T16:11:20.527 回答
4

The answer above with

<layout>MODULE</layout>

does not work anymore, this is because layout element is deprecated in Spring Boot 2.x. I am using Spring Boot 2.0.x, I found this helpful comment on 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.

But as I did not want to implement LayoutFactory I tried this second solution below that actually repackage and creates an extra jar with a classifier given name:

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>

Doing so will allow other modules to depend on the original jar that does not embed the module's dependencies and has the classes at the root of the jar.

One original jar have the same structure as I wanted like

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

and the second classifier have the newer structure with BOOT-INF/ etc.

于 2019-08-27T14:50:24.413 回答
0

我使用的是 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-05-23T17:12:46.530 回答
0

对我来说,这个解决方案有点阴险……我将 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 结构,您希望该插件的配置在其他模块中使用。

于 2019-08-22T14:45:13.093 回答