zl程序教程

您现在的位置是:首页 >  后端

当前栏目

SpringBoot应用瘦身记,兼从maven迁移到gradle手记

2023-09-11 14:21:24 时间

前言

线上的SpringBoot应用已经达到350M,每次更新都花费半小时,虽然每天只更新一次。于是决定来一次瘦身。但是为了更方便的打包,例如既能打出fatjar,也能打出thinjar,同时也能根据需要打出war包,决定将构建脚本迁移到gradle。
2003年,我完成了手工构建(JBuilder2005)到ant自动构建的转变,2012年,完成了ant到maven的转变,后来,除了android应用外,Spring应用我都是才有maven构建,一直也很平稳,没给我惹过乱子。记得2012年采用maven构建时,IBM团队的一个老外坚决反对,他选用公司内部的一套ant框架。为何?人总是习惯使用用熟了的东西。

步骤

选择合适的JDK版本

目前JDK8, JDK11, JDK17是三个重要的版本。经过折腾,我选用了JDK11这个版本。不同版本的热部署方案有差异。

从maven切换到gradle

先执行

gradle init

即可生成build.gradle文件,里面包含了依赖,它将pom.xml的依赖转换成了gradle依赖。这个很不错。否则手工去写依赖就比较痛苦。

// 将依赖包复制到lib目录
task copyJar(type: Copy) {
    // 清除现有的lib目录
    delete "$buildDir/libs/lib"
//    //需要复制的文件
    from configurations.compileClasspath
    into "$buildDir/libs/lib"
}

// 拷贝配置文件
task copyConfigFile(type: Copy) {
    // 清除现有的配置目录
//    delete "$buildDir\\libs\\config"
//    from('src/main/resources')
//    into 'build/libs/config'
}

bootJar {
    launchScript()
    // 例外所有的jar
    excludes = ["*.jar", "fonts/*"]
    // lib目录的清除和复制任务
    dependsOn copyJar
    dependsOn copyConfigFile
    // 指定依赖包的路径

    manifest {
        attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
        attributes 'Start-Class': 'com.icool.CmsApplication'
//        attributes "Manifest-Version": 1.0,
//                'Class-Path': project.configurations.compileClasspath.files.collect { "lib/$it.name" }.join(' ')
    }
}

这里两个注意点:

  • excludes把fatjar下的BOOT/lib的文件都排除掉,放到外面去,这是瘦身最主要的步骤
  • 采用PropertiesLauncher启动应用,不能采用缺省的JarLauncher。PropertiesLauncher支持-Dloader.path选项,这样就可以加载外部的jar了。

PropertiesLauncher允许通过配置loader.path使得jar包可以去加载外部的jar。而JarLauncher只能处理jar-in-jar这种模式。通常来说使用JarLauncher作为Main-Class被称为fat-jar,而PropertiesLauncher则可以将fat-jar变成thin-jar,之所以可以这样做,正是应为PropertiesLauncher使得jar包可以去加载外部的jar。

运行thinjar

瘦身后的jar运行方式:

java -Dloader.path=path/to/lib -Dspring.profiles.active=prod -jar cms-0.0.1-SNAPSHOT.jar

也可以:

java -cp bootApp.jar -Dloader.main=com.xxx.DemoApplication org.springframework.boot.loader.PropertiesLauncher

问题

迁移后,发现热部署不起作用了,一堆的Spring Bean创建问题,后来发现是自己安装了HotSwapAgent这个插件导致的。

其它

缺省的fat jar构建

jar {
    manifest {
        attributes "Main-Class": "org.springframework.boot.loader.JarLauncher"
    }

    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

自定义的fat jar

采用下面的task构建即可:

task customFatJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'com.xxx.fatjar.Application'
    }
    baseName = 'all-in-one-jar'
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

参考

  • github.com/spring-projects-experimental/spring-boot-thin-launcher