Gradle初探
(一):创建一个Gradle项目
1. 环境准备
1.1. 先上Gradle官网下载最新版的程序,地址:https://gradle.org/gradle-download/。
1.2. 配置环境变量
GRADLE_HOME:值为gradle根目录路径,并在PATH中添加 "%GRADLE_HOME%\bin"
1.3. 配置IDE工具的Gradle环境
这里我使用IDEA进行创建(eclipse应该也有对应的gradle插件)。
首先在IDEA的settings中找到Gradle选项,配置gradle home路径。
2. 创建Gradle项目
在当前Project中(可以当做eclipse中的workspace),创建一个gradle的java项目。并和Maven项目一样需要设置项目的GroupId、ArtifactId和Version。如下图所示:
点击"Finish",gralde-demo项目就创建好了。
但是idea又抽风了,我明明勾了自动创建空文件夹,但结果还是得自己动手。。。
Gradle的文件结构和Maven基本一致:
src/main/java:存放java代码;
src/main/resources:存放资源和配置文件;
src/test/java:存放测试用的java代码;
src/test/resources:存放测试用的资源和配置文件;
src/main/webapp:存放WEB的代码和资源(如果是web项目的话需要);
手动创建完成后的结构如图所示:
那这个创建的项目究竟能不能用呢,现在我们写一个很单纯的代码,代码如下:
下面可以使用IDEA内建的gradle命令工具执行一下,gradle的build命令,看看能否构建成功。
"BUILD SUCCESSFUL" 看来是成功了。项目目录下多了build文件夹,在libs中已经有了打包好的jar文件。
和Maven的pom.xml一样,Gradle可以这么构建出项目也是有着自己的构建配置文件。
下面我们就打开build.gradle文件看看这里面究竟写了啥。
(二):build.gradle常用配置(java和web项目)
3. 常用配置(针对JAVA和WEB项目)
打开build.gradle文件,由于是IDEA创建的,所以里面已经有了一些内容。
group和version分别为项目的所在组和版本信息。和Maven类似,而artifactId在gradle则是项目的name,值保存在settings.gradle文件的rootProject.name中。
针对java项目和web项目,根据官方文档,我将build.gradle进行了如下修改,如图所示:
apply plugin: 'java'//添加Java插件
apply plugin :'maven'//添加Maven插件
添加Java和Maven插件,可以使用两者的相关配置。
sourceCompatibility=1.7
targetCompatibility =1.7
分别指定开发环境和编译使用的JDK版本。根据Maven项目经验,在不同IDE间导入Maven项目时,经常会出错,通过指定JDK可以有效解决此问题,故保险起见,这里也加上。
task createJavadoc(type: Javadoc) {
source = sourceSets.main.allJava
}
配置了这个任务后,执行gradle的javadoc命令,可以自动生产javaDoc文档。前提当然你自己有给类和方法按规范添加注解。
tasks.withType(JavaCompile) {
options.encoding ="UTF-8"
}
设置编码为UTF-8,如果不设置,则注释有中文等情况时,生成javaDoc会出现乱码,并且执行build命令时会出现警告和错误。
repositories {
mavenLocal()//添加Maven本地资源库
mavenCentral()//添加Maven中央资源库
}
配置获取资源的资源库
mavenLocal()表示会从本地获取资源,获取资源的顺序为
%USER_HOME%/.m2/settings.xml中指定的路径 >
%M2_HOME%/conf/settings.xml中指定的路径 >
%USER_HOME%/.m2/repository。
注:这里发现一个BUG,按照官方文档说,如果系统用户文件夹下的.m2中不存在settings.xml文件会自动去找%M2_HOME%的settings.xml文件,实际却不会,然后直接指向了%USER_HOME%/.m2/repository。建议自定义maven本地库的,把%M2_HOME%的settings.xml文件COPY一份到%USER_HOME%/.m2目录下即可。
mavenCentral()表示会从Maven中央库获取数据。
除这2种,gradle还可以从指定的URL获取资源,比如:
repositories {
maven {
url"http://127.0.0.1:8081/nexus/content/repositories/"
}
mavenLocal()//添加Maven本地资源库
mavenCentral()//添加Maven中央资源库
}
这里除了本地和中央库,还会从我本地的Maven私服中获取资源。
dependencies {
testCompile 'junit:junit:4.12'//添加单元测试
testCompile 'org.springframework:spring-test:4.2.5.RELEASE'// Spring测试支持
compile 'org.springframework:spring-context:4.2.5.RELEASE'
}
添加依赖包,和Maven类似。上面我采用的是简写语法,还有一种是完整的写法,如下:
testCompile group:'junit', name:'junit', version:'4.12'
和Maven类似,gradle导入依赖包也可以定义其作用的生命周期:
compile:编译时必须。
runtime:运行时必须,包括编译时。
testCompile:测试编译时必须。
testRuntime:测试运行时必须,包括编译时。
注:此外配置依赖包,还可以模块化配置、导入list、配置是否传递等。还没细看。
以上这些已经可以支撑平常的java或web项目开发了。接下来还有一个问题,项目开发时,经常会模块化开发,有时候有些jar可以复用,或者项目需要按不同版本(SNAPSHOT/RELEASE等)发布到Maven私服中,下面就说说如何发布项目到Maven私服等资源库中。
(三):发布项目到Nexus资源库
4. 发布项目
在公司开发中,如果采取Maven这种项目构建方式的,一般都会架设一个Nexus Maven私服在公司服务器上,一些公司积累的资源组件和中央库没有提供的资源,以及一些项目都会发布到私服中,然后开发人员可以通过Maven在具体开发时导入内部资源。那么既然现在要用gradle替换Maven,那么这个需求则需要满足,通过查看官方文档,可以通过引入'maven-publish'实现。具体添加的配置如下:
.......
apply plugin: 'maven-publish'//添加Maven发布插件
.......
//上传资源配置
uploadArchives {
repositories {
mavenDeployer {
//上传资源到Maven私服
repository(url: "http://localhost:8081/nexus/content/repositories/releases/") {
authentication(userName:"admin",password:"admin123")
}
pom.version ="$project.version"
pom.artifactId ="$project.name"
pom.groupId ="$project.group"
}
}
}
通过添加以上配置,通过upload命令,已经可以把项目发布到我的本地私服http://localhost:8081/nexus/content/repositories/releases/中。但是问题又来了,这里我只能把项目发布到本地的releases库中,但是如果我这个项目还是dev版或者snapshot版怎么办?
这里就是体现gradle构建方式比maven灵活的地方。整个build.gradle文件其实就是一段groovy语言的代码。说到这里大家就都懂了吧,根据不同版本发布到不同的库,这不就是一个条件判断的事嘛。
将url提取为变量,加入相关判断代码,如下:
//默认发布到Maven Nexus私服的发行库
def nexusUrl ="http://localhost:8081/nexus/content/repositories/releases/"
//如果为快照版本发布到Maven Nexus私服的快照库
if(version.endsWith("-SNAPSHOT")) {
nexusUrl ="http://localhost:8081/nexus/content/repositories/snapshots/"
}
......
uploadArchives {
......
//上传资源到Maven私服
repository(url: nexusUrl) {
authentication(userName:"admin",password:"admin123")
}
......
}
好了,现在所有版本号为"-SNAPSHOT"的都会被发布到快照库,而其他的则会发布到发行库,现在执行下upload看下效果吧。。。。
另外,在引入了'maven-publish'后,如果配置了mavenLocal(),在upload时也会把资源提交到本地Maven资源库中。
总结
几个小时的试玩,说明不了什么问题,但是gradle的灵活性确实还是让我印象深刻,非常能体现它约定优于配置的原则。但是如果要玩转它还需要学习一定的groovy语言。和程序猿都了解XML相比,这里有个时间成本。并且由于非常灵活,而很有可能出现配置的混乱,但是总体还是觉得利大于弊。写腻了配置XML的方式,在配置里写代码,想着都有趣。。。
(四):3.x新版本发布资源的方式
说来惭愧,敲代码这么多年都没写半篇文章,本来想着好好写一回笔记,结果因为工作繁忙、生活琐事又落下了(其实是笔者范懒 >_<!)。这下“初探”这词是没法用了,想着就是写写平常使用时的心得,就改叫“日常”吧。
扯了扯闲话,言归正传。公司要开发一个框架型的项目,本来想用Maven的,我想着之前写过一个多项目的Gradle配置就拿来直接用了。由于强迫症又发了,上官网下个新版本,结果发现3.1版本的文档里多了以下两篇:
lvy 暂时没用过,不提。这里写一下使用Gradle发布资源到 Maven 仓库的方式,在新版本中Gradle在“maven-publish”插件中增加了发布的功能,用来取代旧版本中Task的方式(旧版本发布方式详见上一篇:Gradle初探(三):发布项目到Nexus资源库)。官方文档原文如下:
This chapter describes the new incubating
Maven publishing support provided by the “maven-publish” plugin.
Eventually this new publishing support will replace publishing via the
Upload task.
If you are looking for documentation on the original Maven publishing support using the Upload task please see Chapter 31, Publishing artifacts.
1. 创建项目以新版本的方式发布
创建一个Gradle项目(以多项目Gradle为例)
build.gradle文件内容:
group 'z99'
version '1.0-SNAPSHOT'
subprojects {
group 'z99'
version '1.0-SNAPSHOT'
// 引用的插件
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'maven-publish'
// 编译环境
sourceCompatibility = jdkVer
targetCompatibility = jdkVer
// 字符集
tasks.withType(JavaCompile) {
options.encoding = encoding
}
// 资源库
repositories {
mavenLocal()
maven {
// 啊哈,配上阿里云的资源库,速度杠杠的
url "http://maven.aliyun.com/nexus/content/groups/public/"
}
jcenter()
mavenCentral()
}
// 依赖
dependencies {
testCompile group: 'junit', name: 'junit', version: junitVer
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: slf4jLog4j12Ver
// 添加 libs 文件夹下的 jar
compile fileTree(dir: 'libs', include: ['*.jar'])
}
// 打包
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
// 如果是发行版本,则上传到发行库。否则上传到快照库。
def postfixUrl = "repository/maven-snapshots"
if (project.version.endsWith("-RELEASE")) {
postfixUrl = "repository/maven-releases"
}
// 发布到本地Maven库和远程Maven服务器
publishing {
repositories {
mavenLocal()
maven {
credentials {
username ossUserName
password ossPwd
}
url "$ossHost/$postfixUrl/"
}
}
}
}
gradle.properties文件内容:
\# 基本信息配置
jdkVer=1.8
encoding=UTF-8
\# 资源库配置
ossRepoUrl=http://127.0.0.1:9001/repository/maven-public/
\# 用于上传的资源库配置
ossHost=http://127.0.0.1:9001
ossUserName=admin
ossPwd=admin123
\# 依赖包版本配置
junitVer=4.12
slf4jLog4j12Ver=1.7.21
servletApiVer=3.1.0
settings.gradle文件内容:
rootProject.name = 'gradle-demo'
include 'sub-a',
'sub-b'
build之后,文件结构如下:
之后执行“publish”命令,则可以将两个子项目分别都发布到maven私服和本地maven资源库中。
命令执行控制台输出:
Maven私服库:
Maven本地库:
2. 子项目单独配置时的发布
写到这里,其实流程和旧版用Task的步骤差不多,但是这是在多项目中,各版本用统一的版本号发布的情况,但实际开发中主项目下各子模块项目的版本号不可能一致,之前旧版时,这种情况下就会出现一个比较难受的写法,如下:
为了主配置文件简洁,我引入一个subprojects.gradle文件来专门写子模块的部分。
subprojects.gradle文件具体内容如下:
project(':sub-a') {
version '1.0-SNAPSHOT'
}
project(':sub-b') {
version '2.0-SNAPSHOT'
}
然后再build.gradle中,去掉子项目的版本配置,在文件尾部加上
apply from: 'subprojects.gradle'
即可。
用旧版本的方式发布一下看看:
首先修改build.gradle,注释掉publish的部分,加上upload的代码:
// 打包
/*publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}*/
// 如果是发行版本,则上传到发行库。否则上传到快照库。
def postfixUrl = "repository/maven-snapshots"
if (project.version.endsWith("-RELEASE")) {
postfixUrl = "repository/maven-releases"
}
// 发布到本地Maven库和远程Maven服务器
/*publishing {
repositories {
mavenLocal()
maven {
credentials {
username ossUserName
password ossPwd
}
url "$ossHost/$postfixUrl/"
}
}
}*/
uploadArchives.repositories.mavenDeployer {
repository(url: "$ossHost/$postfixUrl/") {
authentication(userName: ossUserName, password: ossPwd)
}
pom.version = project.version
pom.artifactId = project.name
pom.groupId = project.group
}
然后执行“upload”(注意:不是3.x版本的“publish”)命令执行发布,结果如下:
纳尼,发生了什么?这就是旧版本的问题所在了,通过截图可以知道版本号的位置变成了“unspecified”,也就是说“pom.version
=
project.version”时拿不到版本号的信息,这原因就在于旧版本中upload的配置是作为一个task进行配置,而在主配置文件中,我是先配置了upload,才引用了子项目的配置文件,因此,要想配置生效则只能改为:
subprojects {
// 之前的其他配置
}
apply from: 'subprojects.gradle'
subprojects {
// upload的配置
}
如此才能正常上传发布(这里就不演示了),这写法对于代码强迫症重症患者简直不能忍啊,所以一度有想换回Maven的念头。直到发现了新版本中的publish之后。
那么新版本的中,只需在原主配置的末尾加上'apply from: 'subprojects.gradle''即可。发布后控制台显示成功,如下图所示:
3. 子项目包含jar、war等不同打包方式时的发布方法
一般子项目中也存在既有纯java的项目,也有web项目的情况。在例子中,比如把子项目2改为web项目,现在做下列的修改。
subprojects.gradle文件内容:
project(':sub-a') {
version '1.0-SNAPSHOT'
// 打包
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
}
project(':sub-b') {
version '2.0-SNAPSHOT'
apply plugin: 'war'
dependencies {
providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: servletApiVer
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.web
}
}
}
}
build.gradle文件内容:
group 'z99'
version '1.0-SNAPSHOT'
subprojects {
group 'z99'
// 引用的插件
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'maven-publish'
// 编译环境
sourceCompatibility = jdkVer
targetCompatibility = jdkVer
// 字符集
tasks.withType(JavaCompile) {
options.encoding = encoding
}
// 资源库
repositories {
mavenLocal()
maven {
// 啊哈,配上阿里云的资源库,速度杠杠的
url "http://maven.aliyun.com/nexus/content/groups/public/"
}
jcenter()
mavenCentral()
}
// 依赖
dependencies {
testCompile group: 'junit', name: 'junit', version: junitVer
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: slf4jLog4j12Ver
// 添加 libs 文件夹下的 jar
compile fileTree(dir: 'libs', include: ['*.jar'])
}
// 如果是发行版本,则上传到发行库。否则上传到快照库。
def postfixUrl = "repository/maven-snapshots"
if (project.version.endsWith("-RELEASE")) {
postfixUrl = "repository/maven-releases"
}
// 发布到本地Maven库和远程Maven服务器
publishing {
repositories {
mavenLocal()
maven {
credentials {
username ossUserName
password ossPwd
}
url "$ossHost/$postfixUrl/"
}
}
}
}
// 引入子项目的配置
apply from: 'subprojects.gradle'
执行结果,如下图:
要点就是一个是“from components.java”,另一个是“from components.web”,目前3.1版官方貌似只给了这两种。
有一点要注意的是publishing这个配置不能覆盖(或者是我没找到方法),我一开始是没有删去打包java的publishing配置,想直接在war的独立配置里直接配一个打包为war的publishing配置,结果报错,说是不能配置多个components。目前尚未找到解决方案,先这么着吧。
有点犯困了,后面写的有点草率。今天就这样吧,明天还得加班 >_<!。引用一句老婆常说的话结尾吧:
哎,苦逼的程序猿。。。
转载自:http://www.jianshu.com/u/c69205324efe
Gradle初探的更多相关文章
- Android热修复之微信Tinker使用初探
文章地址:Android热修复之微信Tinker使用初探 前几天,万众期待的微信团队的Android热修复框架tinker终于在GitHub上开源了. 地址:https://github.com/ ...
- Android studio:Groovy 与 Gradle 基础【三】
转载:http://www.apkbus.com/forum.php?mod=viewthread&tid=255064&extra=page%3D2%26filter%3Dautho ...
- Maven和Gradle中配置单元测试框架Spock
Maven Maven本身不支持其他JVM语言(例如Groovy或Scala).要在Maven项目中使用它,需要使用第三方插件.对于Groovy而言,最好的选择似乎是GMavenPlus(重写不再维护 ...
- Gradle+Groovy基础篇
在Java项目中,有两个主要的构建系统:Gradle和Maven.构建系统主要管理潜在的复杂依赖关系并正确编译项目.还可以将已编译的项目以及所有资源和源文件打包到.war或.jar文件中.对于简单的构 ...
- Gradle+Groovy提高篇
创建自定义任务 打开build.gradle文件,并在末尾添加以下内容: println "1" task howdy { println "2" doLast ...
- Gradle如何在任务失败后继续构建
如果我们运行Gradle构建并且其中一项任务失败,则整个构建将立即停止.因此,我们可以快速反馈构建状态.如果我们不想这样做,并且希望Gradle执行所有任务,即使某些任务可能失败了,我们也可以使用命令 ...
- Android Studio NDK编程初探
继上一篇学习了如何使用NDK编译FFMPEG后,接下来就是要学习如何在Android Studio中使用了. 经过参考和一系列的摸索,记录下具体步骤. 创建C++ Support的Android St ...
- 腾讯IOT安卓开发初探
目录 腾讯IOT 安卓开发初探 Tecent IOT 开发平台的使用 新建项目 创建产品 添加自定义功能 设备开发 微信小程序配置 面板配置 新建设备 使用设备 安卓开发 前置配置 data.json ...
- apijson 初探
apijson 初探 本文试着用 5W1H 方式切入,试图快速建立自己对 apijson 的整体认知,所以这不是一趟快速入门的 demo 之旅,而是显得比较务虚的探索式知识体系整合过程. 持续更新中. ...
随机推荐
- springMVC源码分析--容器初始化(二)DispatcherServlet
在上一篇博客springMVC源码分析--容器初始化(一)中我们介绍了spring web初始化IOC容器的过程,springMVC作为spring项目中的子项目,其可以和spring web容器很好 ...
- const引用
在C++中可以声明const引用 const Type& name = var: const引用让变量拥有只读属性 const int &a = b const int &a ...
- 听说你又一次放弃了Dagger2,来听老夫说道说道
关于Dagger2是啥,用法网上已经有很多了.不过听说你已经很多次Dagger2从入门到放弃了,来来,让我这个老中医给你治一治.老夫手法纯熟,不会让你有任何痛苦的,放心读下去吧. 本文同步自 博主的私 ...
- RAMCloud:内存云存储的内存分配机制
现在全闪存阵列已经见怪不怪了,EMC的XtremIO,还有VNX-F(Rockies),IBM FlashSystem.全闪存真正为效率而生,重新定义存储速度.凭借极致性能,高可用性,为您极大提高企业 ...
- MacTalk·人生元编程 - 读书笔记
简介 <MacTalk·人生元编程>是一本随笔文集,主要内容来自作者的微信公众平台"MacTalk By 池建强".本书撰写于2013年,书中时间线却不止于此.作者以一 ...
- C#之DirectoryInfo操作
在C#中的System.IO命名空间下有大量的库供我们使用,下面一起来看一下DirectoryInfo的使用吧. code: using System; using System.Collection ...
- ROS_Kinetic_01 在ubuntu 16.04安装ROS Kinetic 2017.01更新
ROS_Kinetic系列学习(一),在ubuntu 16.04安装ROS Kinetic. Celebrating 9 Years of ROS! ubuntu16.04已经发布半年多了,ROS的K ...
- 敦泰FT6X06单层自容调屏
总的概括来说,自电容调屏在配置好通道个数和顺序后,只需调整AFE相关的设置参数使各通道的Raw Data和CI值符合定义的标准即可.– AFE是模拟前端的缩写-Analog Front End• Ra ...
- 经过一段的努力,终于成为CSDN博客专家,感谢大家支持
感谢CSDN提供这么好的一个技术学习平台,通过各路大神的博客我成长了许多,同时也感谢支持我的朋友们,我会继续努力,用心去写好博客.还请继续关注我~ 谢谢!
- 智能循迹避障小车&抢答器
智能循迹避障小车 →视频链接← 抢答器