Плагин Spring Boot Maven - без каталога BOOT-INF

Между версией 1.3.8.RELEASE модуля spring-boot-maven-plugin и версией 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. Из-за этого - когда вы пытаетесь запустить проект Spring Boot на Amazon Lambda - он говорит, что не найден jar, поскольку он не может прочитать новую структуру jar Spring Boot Uber

Мой вопрос - возможно ли в более новых версиях Spring Boot Maven Plugin заставить его генерировать uber jar такой же структуры, как в версии 1.3.9.RELEASE?

Я попробовал Maven-Shade-плагин - но это приводит к другим проблемам

Любая помощь с благодарностью

Спасибо Дэмиен

6 ответов

Решение

Решением было добавить макет МОДУЛЯ для плагина в файле 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>

В моем случае я использую весеннюю загрузку 2.X, и я объявил spring-boot-maven-plugin после maven-dependency-plugin(который я использовал для распаковки и создания взорванного приложения в Docker), и это должно быть до распаковки, имеет смысл, он распаковывался до запуска плагина весенней загрузки 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>

Ответ выше с

<layout>MODULE</layout>

больше не работает, это связано с тем, что элемент макета устарел в Spring Boot 2.x. Я использую Spring Boot 2.0.x, я нашел этот полезный комментарий на github:

Поддержка макета модуля была удалена в Spring Boot 2.0, а в версии 1.5 устарела. К сожалению, обновления документации подключаемого модуля Maven были пропущены, поэтому мы можем использовать эту проблему для решения этой проблемы. Вместо этого вы должны использовать собственный LayoutFactory.

Но поскольку я не хотел реализовывать LayoutFactory, я попробовал это второе решение ниже, которое фактически переупаковывает и создает дополнительную банку с заданным именем классификатора:

Это связано с изменением макета исполняемых jar-файлов в Spring Boot 1.4. Классы приложений теперь упаковываются в BOOT-INF/classes. Ваш клиентский модуль зависит от переупакованной толстой банки вашего веб-модуля. Из-за нового макета это означает, что клиентский модуль больше не может загружать классы веб-модуля. Если вы хотите использовать свой веб-модуль в качестве зависимости, вам следует настроить переупаковку Boot для применения классификатора к толстой банке. Например:

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

Одна оригинальная банка имеет такую ​​же структуру, как я хотел

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

а второй классификатор имеет более новую структуру с BOOT-INF / и т. д.

Как мы можем добиться того же результата, используя gradle? Я перешел с Spring-Boot-gradle-plugin 1.2.5 на 1.4.0, и теперь структура jar изменилась. Это решение<layout>MODULE</layout>имеет эквивалент в Gradle?

Для меня решение было немного более коварным... У меня был плагин spring-boot-maven-plugin, вложенный в pluginManagement (см. Ниже). Дох!

Противно то, что когда я запускал mvn spring-boot:run, весенняя загрузка запускалась нормально и запускала приложение! Только когда мы попытались выполнить развертывание на PCF (как 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>

После того как я удалил теги pluginManagement из POM, я получил структуру./BOOT-INF. Имейте в виду, что pluginManagement обычно используется для структуры parent-pom, где вы хотите, чтобы конфигурация этого плагина использовалась в других модулях.

Я использовал 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

С этим я получил успешную сборку.

Другие вопросы по тегам