Gradle 历险记(二):从 maven 到 gradle 迁移的一些坑
最近写 project,但线上发布需要使用 gradle,开发的时候并没有思考这件事,所以就埋了一个巨大的坑,本文描述一下这个恶心的过程,浪费了我一整天的时间。
一、安装指定版本的gradle
第一步其实可以不做,但是因为我这个网络实在是太烂了,让Intellij去下载 gradle 经常下崩,线上用了某版本的gradle,记为A 版本吧。
我是 Mac,推荐使用 brew 来进行这个操作,但是 brew 是无法安装老版本的,所以就需要找到那个特定的版本,搜了很多,这里提供一个比较笨的方法。
说一下 brew 的原理,brew install 其实是去寻找一个同名的 ruby 脚本,去执行一遍,这些 ruby 被存储在https://github.com/Homebrew/homebrew-core.git这个仓库里,找到里面的 gradle.rb 的修改历史,但由于这个仓库过于大,网页上不让操作,所以只能 clone 下来本地操作,这个就很恶心了,需要花费硬盘空间和网速。
之后拿到那个特定分支的 rb 文件,brew install gradle.rb
即可。
二、将pom转为build.gradle
gradle 本身提供这个操作,命令是 gradle init --type pom
,就会根据pom.xml自动生成 build.gradle
和 settings.gradle
。但这玩意似乎挺破的,遇到不认识的、不常见的标签,就直接跳过了,所以语意可能会改变,需要手动 patch 一些东西。
以我这个项目为例,是 Java 项目,maven 编译时候先按照规则生成一些 java 文件,这些 java 文件将来会当做源码来处理。
坑就在这个地方,这部分代码是没有被 gradle 自动生成的,直接使用会出现 ClassNotFound 的问题,所以我们不能直接删掉 pom.xml,需要借助它替我们生成一些代码。
暂时的解决方案就是,把这些生成出来的 java 文件也添加到git仓库里,反正也不大。
但这样操作之后仍然是 ClassNotFound,搜索发现代码明明在里面,所以应该是没找到,发现是 pom 里的 sourceSets 没有被加到gradle里,所以也要手动加。这个故事告诉我们,一定要把 pom 里的主要逻辑都移植过去,自动初始化很蠢的。
加完之后,就没有问题了,ok,算是解决了,进入下一个坑。
三、项目依赖的移植
在 pom 的依赖里,曾经是多个项目放在同一个目录下,pom.xml里用
1 | <modules> |
这样subA/B/C就可以相互访问到了,很简洁。
A、B、C 是可以相互知道对方的存在的,假设C 依赖 A 和 B,那么直接在C 的pom.xml里,写好 A 和 B 的 groupId 和 artifactId 和 版本号即可,不需要额外操作。优先从本地获取模块。
但是 gradle 这样做是不行的,就算在 build.gradle 里写的是 A 和 B 的信息,但也不会从本地拿,而是尝试从网络上搜索 A 和 B。 最终的解决方案有两个,一个是使用平级依赖,一个是使用发布 maven 到本地这个功能。
先说平级依赖,settingsC.gradle里要写明 A 和 B,使用
includeFlat("subA")
即可,这时候可以用 ":subA" 来表示 moduleA。 之后修改 buildC.gradle 里的内容,在dependencies里加入
compile project(":subA")
就会将 moduleA 加入到依赖中。
嗯,在 Intellij 的右侧可以正常发现这个模块了。
再说第二个方法,将 maven 仓库发布到本地。需要借助名叫 maven-publishing 的gradle 插件,之后使用 publishingToMavenLocal 即可在本地临时发布,之后按照最常用的方式导入即可。
但是存在缺点,每次都要手动来发布一遍很烦,所以推荐使用第一种方法。
再插播一个小 tips,在最外层的 settings.gradle 里包含 subA 和 subB的时候,默认是去找 subA 这个目录,可以通过这句话来指定文件夹。
1 | include(":subA") |
四、ban 掉 test
这步也不是必须的,但是作为开发者,我并不关心我依赖的库是否 test 通过了,关我屁事,所以可以使用这个语句来关掉。
1 | tasks.withType(Test) {enable=false;} |
其实不是我想关掉它,实在是因为依赖的 test 一直都过不去,懒得修好它,就直接 ban 掉吧,又不是不能用。
五、gradle 编译一个带有依赖的 jar 包(此处不大优雅,偶尔能用,推荐阅读另外一篇关于打包的文章)
默认情况下,调用 gradle jar 只会打包自己的代码,缺失所有的依赖库。这里推荐一款叫 com.github.johnrengelman.shadow 的插件。
1 | apply plugin: 'com.github.johnrengelman.shadow' |
之后使用gradle shadowJar
就可以拿到编译好的jar包了,里面是各种各样的 class 文件。
完结~~ gradle 基本操作,大神勿喷。。。