为依赖于其他项目的 Spring Boot 应用程序创建胖 jar 时出现异常

Posted

技术标签:

【中文标题】为依赖于其他项目的 Spring Boot 应用程序创建胖 jar 时出现异常【英文标题】:Exception while creating a fat jar for spring boot application which depends on other project 【发布时间】:2019-10-08 21:49:24 【问题描述】:

这是我上一个问题的后续 Convert gradle multi project to springboot fat jar application

我有一个 http servlet 应用程序,它是一个多项目 gradle 构建,我的项目是一个包含 gradle HttpServlet 项目,它依赖于其他两个 gradle java 项目。我在 tomcat webapps/Web-INF/lib 目录中部署了所有 3 个 jar 并运行它。

现在有一个要求,我必须将我的应用程序转换为 Spring Boot 应用程序,而不是 3 个单独的 jar,我必须创建一个我应该运行它的胖 jar。

我的代码安排如下

    Rootrepository
      - settings.gradle 
     - build.gradle
      - Springboot project
         - build.gradle
         -src….
    - OtherGardleProject1
        - Src…
    - OtherGardleProject2
        - Src…

Please see `root project’s build.gradle`

version = '1.0.0'
group = ‘myproj’
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'groovy'
apply plugin: 'eclipse'

subprojects 
    repositories 
        mavenCentral()
            
    

    apply plugin: 'java'

    sourceCompatibility = 1.8

    compileJava

    jar 
     from sourceSets.main.allSource
    


subprojects.each  subproject ->
  evaluationDependsOn(subproject.path)



task mmJar(type: Jar, dependsOn: subprojects.jar) 
      manifest 
        attributes 'Main-Class': 'org.springframework.boot.loader.JarLauncher'
        attributes 'Start-Class': ‘mypackage.springboot.Application'
    
  subprojects.each  subproject ->
    from subproject.configurations.archives.artifacts.files.collect 
      zipTree(it)
    
  



dependencies 
        compile 'junit:junit:4.12'
        compile 'org.slf4j:slf4j-api:1.7.7'

请看springboot projects’ build.gradle

buildscript 
    ext 
        spring_plugin_version = '2.1.1.RELEASE'
    

    repositories 
        mavenCentral()
    

    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$spring_plugin_version")
        classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"

    


apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'



dependencies 
    implementation('org.springframework.boot:spring-boot-starter-quartz')
    implementation('org.springframework.boot:spring-boot-starter-web')

    compile project(‘:otherproject1’)


    compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1'

    compile group: 'commons-io', name: 'commons-io', version: '2.4'
    compile('org.springframework:spring-webmvc')

    runtimeOnly('org.springframework.boot:spring-boot-devtools')
    compileOnly('org.projectlombok:lombok:1.18.8')
    annotationProcessor('org.projectlombok:lombok:1.18.8')

    testCompile('org.springframework.boot:spring-boot-starter-test')

然后我运行gradle clean assemble mmJar,它按预期创建了一个胖罐。

但是当我尝试运行java -jar build/libs/myproj-1.0.0.jar

Exception in thread "main" java.lang.IllegalStateException: Failed to get nested archive for entry BOOT-INF/lib/JavaEWAH-1.1.6.jar
    at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:108)
    at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:86)
    at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:70)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:49)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.io.IOException: Unable to open nested jar file 'BOOT-INF/lib/JavaEWAH-1.1.6.jar'
    at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:256)
    at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:241)
    at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:103)
    ... 4 more
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/JavaEWAH-1.1.6.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
    at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:284)
    at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:264)
    at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:252)
    ... 6 more

有人可以建议我做错了什么吗?

【问题讨论】:

使用 Spring Boot 创建一个 fatjar 不要自己动手。 Spring Boot 已经生成了一个包含所有内容的可执行 fatjar,您正试图将其硬塞到另一个 fatjar 中。 你的意思是我在根 build.gradle 中的 mmJar 不是正确的方法吗?您能否使用我的两个 gradle 文件将其发布为答案 您的 Spring Boot(子)项目是 fatjar...您不需要其他任何东西。 【参考方案1】:

正如@M.Deinum 和我在链接帖子中所建议的那样,只需让 spring boot gradle 插件完成这项工作。在您的根文件夹中保留settings.gradle 文件并删除build.gradle。运行

gradle clean build

Rootrepository 文件夹中。 Gradle 将构建 settings.gradle 中包含的项目,并在 Springboot project/build/libs 文件夹中创建 fat jar

【讨论】:

我删除了根项目中的 build.gradle 并运行了 ./gradlew bootJar 然后我在第二个项目中出现错误 Build file 'Otherproject1/build.gradle' line: 2 * 出了什么问题:一个问题发生评估项目':Otherproject1'。 > 在 org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler 类型的对象上找不到参数 [group=com.google.guava, name=guava, version=18.0] 的方法 compile()。 请看Otherproject1/build.gradle依赖的build.gradle compile group: 'com.google.guava', name: 'guava', version:'18.0' compile 'org.slf4j: slf4j-api:1.7.7' 编译'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.9.5' 编译'com.fasterxml.jackson.core:jackson-databind:2.9.5' 编译'org. apache.commons:commons-lang3:3.4' testCompile 'junit:junit:4.11' 我很傻。忘记将应用插件“java”添加到第二个项目的 build.gradle 是的,它解决了这个问题。我检查了胖 jar 的内容(jar tf myspringboot.jar),我可以在其中看到我的 otherproject1.jar

以上是关于为依赖于其他项目的 Spring Boot 应用程序创建胖 jar 时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot/Gradle/Querydsl项目有相同的依赖依赖于不同版本的另一个依赖

Spring Boot 概念学习

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

spring boot应用程序作为maven依赖项[重复]

3Spring Boot 核心技术

Spring boot 打包为war包报错:提示缺少web.xml