1. 起因
起因是公司内网vdi无法直接连接外网
而很多开源项目使用了gradlew
而gradlew下载gradle需要网络环境,否则无法下载,也无从启动项目
所以,基于实际生产场景,存在解决这个问题的必要性
2. gradlew
在此简要介绍下gradlew
gradlew,即gradle-wrapper,是一个针对gradle的包装器
其主要解决的问题是,gradle的版本繁多,并且后向兼容性像屎一样,根本就没几个版本的gradle相互能做到80%以上的兼容(我这里说的包含major版本相同而medium版本不同的情况)
在这种前提下,如果gradle开发者使用和maven开发者惯用的相同的“把mvn写进path,然后在项目中直接用”的方法,会死的很难看
基于这种考量,他们弄出了个gradlew,根据读取到的项目中的配置文件./gradle/wrapper/gradle-wrapper.properties
,自动化下载、运行指定版本的gradle
3. gradle-wrapper.properties
一个经典的gradle-wrapper.properties内容如下所示:
1 | #Tue Nov 28 14:11:56 CET 2017 |
其中,distributionUrl即为使用的gradle版本的url
执行gradlew的时候,实际上,寻找gradle过程如下
首先尝试从本地的cache目录中读取distributionUrl所对应的zip解压后的结果
如果没有,则先读取distributionUrl所对应的zip并解压,存进cache目录
如果也没有distributionUrl所对应的zip,那么则先下载distributionUrl所对应的zip
所以,在无直接连接外网环境下,从网上获取的使用gradlew管理的开源项目,往往是无法直接启动的,会死在下载distributionUrl所对应的zip
的步骤。
4. 解决办法(正道)
4.1 方法
我们的需求实际上不是下载distributionUrl所对应的文件,而是使distributionUrl所对应的文件可以获取
既然如此,我们可以通过改变Url,来指定一个我们可以获取的Url
通过追溯源码
,我们发现,实际上是把distributionUrl作为一个URI处理
1 | private URI readDistroUrl() throws URISyntaxException { |
大家都知道,java中的URI是包含很多协议的,甚至可以自行注册协议上去对吧。这里我们可以使用最简单的文件协议
将上述配置文件中的distributionUrl改为
1 | distributionUrl=file\:///D:/gradle-5.5-all.zip |
再次运行gradlew,爽到
1 | Download file:///D:/gradle-5.5-all.zip finished, took 205 ms (136.3 MB) |
4.2 缺陷
采用这个方法解决问题的最大的缺陷是,必须修改gradle-wrapper.properties
文件
如果你下载这个项目是纯粹处于观赏的目的,那么这无关紧要
但是如果你是想要debug,并且有创建commit回原项目的计划,那么修改gradle-wrapper.properties
文件将会变得很碍眼
追溯源码
得知,实际上,就算对于同一版本的gradle,只要源URL不同,也会cache在不同的目录,具体的话是对URL的主体部分算哈希值(实现上是采用MD5)
1 | /** |
所以如果你存在“先改成本地URL,下载完了以后再改回去”的想法,劝你早点打消掉比较好
5. 解决办法(外道)
5.1 方法
首先,直接使用gradlew安装失败一次,使其创建出文件夹与失败记录
然后,手动找到该目录,并填充zip,伪造出上次下载好了的假象
然后,再次运行gradlew,观测其使用cache文件夹内的以为是上次下载好,实际上是我们手动注进去的zip,并成功启动
该cache文件夹位于
System.getProperty("user.home") + "\.gradle\wrapper\dists"
根据gradle版本,找到可疑目标,草进去,直接每个都给他注进去你准备好的gradle的zip即可
以windows为例,以用户xxxxxxxx为例,此目录为
C:\Users\xxxxxxxx\.gradle\wrapper\dists
5.2 缺陷
需要手动操作,效率低
6. 解决办法(方术)
6.1 方法
写一个java程序,读取gradle-wrapper.jar,调用其计算下载后zip位置的函数,自己算出地址,把本地指定文件夹中对应版本的zip复制过去,然后再调用gradlew
6.2 缺陷
需要时间和心情做此代码实现
碰巧,最近,我既没有时间,也没有心情
所以这个计划姑且延后吧
已经有了两个能用的方法了,倒也不是不能凑合
- 本文作者: XenoAmess
- 本文链接: http://xenoamess.com/2021/04/24/20210423在离线环境下使用gradlew/
-
版权声明:
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。