引言
前面我们学习了Groovy语言,Gradle相关知识(如:生命周期/project/task等)
了解到了Gradle是一个很好用的构建工具,具体细节可以自行回顾往期文章:
6)【Gradle系列】Gradle 之Project详解(一)
7)【Gradle系列】Gradle之Project详解(二)
8)【Gradle系列】Gradle之 Project详解(三)
10)【Gradle系列】Gradle在Android上的拓展
接下来,我们将用前面学习的理论,逐步用到实战中去
背景
日常开发中,我们如果开发了一个基础组件,都会通过maven来发布到远程或者本地,来提供给业务开发的同学使用;
如果基础组件比较多的时候,那么上传脚本的通用性就必须要考虑了,因为不可能再每一个基础组件的项目中,都重复写上传的脚本;
所以接下来,我们将利用前面学过的知识(如:gradle属性拓展/生命周期等)来实现maven上传的通用脚本;
另外,基于方案的科学性/实用性方面考虑,本章将通过研究微信Tinker项目中的maven-publish封装来开展
实现的效果
1)根工程的gradle
在上传maven的时候,一般要指定上传的地点/组件的版本号/组件名称等信息
这些是输入信息,会根据不同开发者/企业等的不同而改变,属于配置信息
所有需要抽到指定的地方(如:根工程的gradle文件/单独的配置文件等),这里我们
放在了根工程的gradle中
上图可以看出我们配置了的信息有:
VERSION_NAME = '1.0.666'
GROUP = 'com.davi.mavenPlu'
// 会在项目根目录生成文件夹
POM_URL = 'file:daviRepoMaven666'
复制代码
其中,我们上传到本地仓库(即特定的文件夹中)
2)组件工程的gradle
这里我们是一个java的组件(java工程模块),在输出jar后上传到本地仓库;
这里是使用《maven-publish封装》的地方,可以看出我们引入了通用封装好的脚本:
apply from: rootProject.file('daviGradle/DaviPublish.gradle')
复制代码
使用的时候,比较简单:
1)daviPublish,自定义的拓展标示,代表发布maven
2)pom,自定义的拓展,代表要发布的内容
3)publishToMaven,自定义的拓展,代表要发布的地址
3)通用封装好的脚本
在第2点中,封装好的脚本位置如下:
细节先不在这里展开
4)运行效果
通过前面的3步之后,执行task就可以实现java组件的上传,具体效果如下:
除此之外,无论下次是任何java组件需要上传,只需要简单的配置即可(也就是第1和第2点)
然后引用下第3点这个封装好的《maven-publish封装》即可,比如微信Tinker项目中的复用效果:
《maven-publish封装》具体实现
// Register extension
extensions.create('daviPublish', JavaLibraryPublishExtension.class, project)
//ext.artifactId = name
/**
*
* 基于《maven-publish》方式的上传java工程的jar
*
* */
class JavaLibraryPublishExtension {
private final Project project
protected final ArrayList<Closure> pomClosures = []
private final ArrayList<Closure> mavenPublishClosures = []
JavaLibraryPublishExtension(Project p) {
project = p
//执行阶段 publish
p.afterEvaluate {
this.publish()
}
}
protected void publish() {
//强校验
//因为这个功能是基于'maven-publish'的通用设计
if (!project.plugins.hasPlugin('maven-publish')) {
project.plugins.apply('maven-publish')
}
emitPublicationDSL(project)
emitRepositoryDSL(project)
}
/**
* 要发布的内容准备(如:java源码/javaDoc等)
* */
protected void emitPublicationDSL(Project project) {
/***
* 获取源码的task
* */
def sourcesJarTask = project.task('sourcesJar', type: Jar) {
classifier = 'sources'
//project.sourceSets.main 中的代码的位置目录保存起来,输出到 srcDirs = []
def srcDirs = []
def sources = project.sourceSets.main
['java', 'groovy', 'scala', 'kotlin'].each {
if (sources.hasProperty(it)) {
println "获取源码的task : project.sourceSets.main has ${it}"
srcDirs << sources[it].srcDirs
}
}
from srcDirs
}
/***
* maven 要发布的内容(可配置多个)
*
* 发布:sourcesJarTask的源码
* */
project.publishing.publications {
//${publicationName},称为发布组件Component,用于配置一项要发布的内容
//只是一个命名,并无特殊含义(也可以将其更换为别的名称,但不能与其它发布组件名称重复)
"${publicationName}"(MavenPublication) {
from project.components.java
groupId this.groupId
version this.version
//将 sourcesJarTask 看作 artifact,交给 archives 管理
//artifact sourcesJarTask
}
}
/**
* maven 要发布的内容(可配置多个)
* 外部传进来的pom
* */
pomClosures.each { cl ->
//要发布的内容(可配置多个)
project.publishing.publications {
"${publicationName}"(MavenPublication) {
// 闭包存到 pomClosures数组
pom cl
}
}
}
}
/**
* 要发布的地点
* */
private void emitRepositoryDSL(Project project) {
mavenPublishClosures.each { cl ->
project.publishing.repositories {
maven {
cl.delegate = delegate
cl()
}
}
}
}
String getGroupId() {
return project.group
}
String getVersion() {
return project.version
}
final protected String getPublicationName() {
return project.name
}
/***
* 自定义拓展属性 pom
* */
void pom(Closure cl) {
if (cl != null)
pomClosures << cl
}
/***
* 自定义拓展属性 publishToMaven
* */
void publishToMaven(Closure cl) {
if (cl != null)
mavenPublishClosures << cl
}
}
复制代码
源码地址
结尾
哈哈,该篇就写到这里(一起体系化学习,一起成长)