Gradle 打的Jar包,如何配置Jar包运行的时候指定resources目录

May 11, 2023 作者: yijianhao 分类: java 浏览: 396 评论: 0
  • 更新: 写的太抽象了,导致我自己回顾的时候都不知道在说些什么,其实主要注意gradle的配置使用了kotlin,与groovy有一定区别。找个时间修改一下吧。
  • 主要思想是通过官方的distribution、application插件生成的springboot启动脚本,修改该脚本的启动参数,指定springBoot的resources文件存放位置;为此,需要剔除jar包内部的resources目录,以及指定resources存放位置。
  • 网上资料这么少。估计是因为大家都用cicd,比较少关注这一部分内容了。

打Jar包通常情况下会将配置文件一起打包到Jar包中,这很方便,只要执行java -jar ...就可以了,但现实往往是需要经常的去修改那个配置文件,解压再打包很不人性。比较合理的方案应该是可以将配置文件目录放在jar包外面。
这看起来是一个很常见的问题,但是我在网上找了一天才找到比较满意的结果。解压后的目录为:

my-app/
├── bin/
│   ├── my-app
│   └── my-app.bat
├── config/
│   ├── application.yml
│   └── logback.xml
└── lib/
    ├── my-app-1.0-SNAPSHOT.jar
    ├── lib1.jar
    ├── lib2.jar
    └── ...

结论

先说结论:只需要在CLASSPATH环境变量中指定该Jar外部的resources目录就可以达到该目的

为此需要做如下三件事:

  • 生成Jar包的时候剔除内部的resources目录
  • 将Jar包内的resources目录文件拷贝到外部的resources目录
  • 设置环境变量

插件

在这里使用到了gradle的两个官方插件:

plugins {
    ... ...
    distribution
    application
}

....

application {
    mainClass.set("your.main.class")
}


distribution: 打压缩包 https://docs.gradle.org/current/userguide/distribution_plugin.html application:打Jar包 https://docs.gradle.org/current/userguide/application_plugin.html

distribution不仅可以打压缩包,还能生成启动脚本,我们的环境变量就可以在里面设置。

剔除内部的resources目录

剔除的目的是防止冲突,这不多说

tasks.jar {
    exclude{it.file.toPath().startsWith("$buildDir/resources/main") }
}

拷贝resources目录到外部目录config

这里我指定的外部目录名称为config,将它放在压缩包中

distributions {
    main {
        contents {
            from("src/main/resources") {
                into("config")
            }
        }
        distributionBaseName.set("YourName")
    }
}

修改环境变量

由于distributions插件生成一个启动jar包的shell(unix link)和bat(windows)脚本, 所以我们直接操作修改这两个文件

生成的这两个文件中,有一个CLASSPATH环境变量,指向了所有Jar包,我们只需要在后面加上:$APP_HOME/config 或者:$APP_HOME\\config即可

...
CLASSPATH=....:$APP_HOME/config
...

gradle distributions中的CreateStartScripts可以设置配置生成启动脚本的逻辑,但遗憾的是,操作他会覆盖我们原有的环境变量,得不偿失。不过还好,stackoverflow有人给出了解决方案:

tasks.startScripts {
    classpath = classpath?.plus(files("src/dist/XxxAPlaceHolderForAConfigxxX"))
    doLast {
        val windowsScriptFile = file(getWindowsScript())
        val unixScriptFile = file(getUnixScript())
        windowsScriptFile.writeText(windowsScriptFile.readText().replace("%APP_HOME%\\lib\\XxxAPlaceHolderForAConfigxxX", "%APP_HOME%\\config"))
        unixScriptFile.writeText(unixScriptFile.readText().replace("\$APP_HOME/lib/XxxAPlaceHolderForAConfigxxX", "\$APP_HOME/config"))
    }
}

注意:我这里用了kotlin语言, 与groovy不太一样, 方案来自stackoverflow,可以直接看原文: https://stackoverflow.com/questions/27968376/gradle-copy-resources-processresources

最终结果

运行gradle distZip, 在build/distributions中会生成一个zip压缩包,对这个压缩包进行解压可以看到如下结果,执行脚本文件放在了bin中,配置文件放在了config中, lib是运行的jar包和依赖包。

image-1683801218152

把这个压缩包扔到生产环境中,解压->修改配置->执行 就OK了微信图片_20230511183916

#gradle(1)

评论