Gradle
常年搞.net,脚本构建工具是绝对没有用过的,虽然也知道如何用命令行编译 csproj : ## 命令行编译 devenv *.csproj /build msbuild *.sln 但个人对于java的整体结构还是很不了解的,作为有编程基础的同学,自然希望能够更加的融入java的环境里,所以第一步就是学习构建工具。 根据搜索引擎,java的构建工具主要有 ant+ivy,maven,gradle三种。其中我最先了解的应该还是gradle,因为最开始学android的时候遇到过,不过因为用的是idea,所以也只是知道而已,后来想学习大数据,于是看了一下hadoop等,愈发的发现一个叫maven的东西应用广泛,让我非常想学习一下。今天又了解了一下,还是决定学新不学旧,还是先学习一下gradle。
安装 gradle
java世界里的安装基本上都是下载,解压,配置环境变量三步,gradle也不例外。
- 下载gradle
- 配置环境变量 GRADLE_HOME 指向解压后的程序目录。
- 添加 %GRADLE_HOME%\bin 到PATH变量。 打开一个cmd,输入 gradle -v 看一下输出,问题应该不大,不再多言。
了解gradle
下面参考了gradle入门系列 感谢大大们的辛勤付出 ^_^ ,侵删。 首先是gradle的基本结构。 如同csproj和sln文件,java系的构建工具也是需要一个配置文件的,ant的build.xml,maven的pom.xml 而gradle的是 build.gradle,如你所见这是一个gradle文件,里面用的是一种叫 graoovy的脚本语言,不需要了解太多,理解成一种约定好了格式的配置文件就好了(术语叫DSL领域特定语言),顿时觉得好高大上。
下面是几个概念:
-
项目project 我们的构建产物(如jar包)或实施产物(如war)
-
任务task 不可分割的最小工作单元,即一个操作,如编译,执行测试。个人理解上这里的任务说的就是某个操作/命令,跟maven的生命周期里的build,test这种有点像,gradle的不一样之处在于gradle的task是由插件提供的,不同的插件提供不同的task,你也可以直接在build.gradle中定义自己的task。
-
一个项目可以执行多个任务
-
既然提到了插件,那也简单的说明一下,gradle的功能其实都是由插件提供的,在build.gradle文件中注册插件之后就可以对本项目使用插件中的提供的命令,这里是gradle默认自带的插件介绍。
下面详细介绍gradle的相关文件:
-
build.gradle 指定一个项目和它的任务
-
gradle.properities 构建属性文件
-
gradle.settings 指定多项目构建时候各个项目的关系,只有一个项目的时候可以省略
基本上来说,知道这些概念就差不多了,直接开始实践,开始构建项目喽。
gradle 实战
创建项目
今天的目标就是新建一个java项目,引用apache的httpclient包访问一个地址,程序类型是控制台。 首先,新建一个文件夹, MyCrawl,新建一个文件 build.gradle,最好先打开一个vs code或者sublime等然后新建,因为右键新建的txt默认是gbk编码的,我现在对编码问题很是头疼。 输入内容:
apply plugin: 'java'
如上面的介绍,现在我们添加了叫java的插件。 然后shift+右键打开命令窗口,输入
gradle tasks
可以见到很多绿色的task命令。就是我们可以执行 gradle assemble 这样的意思。但现在文件夹是空的,所以先不管。 这时候想到如何创建项目及文件,大家知道java的项目一般是有固定格式的,比如 src/main/java/package 或 src/main/scala/package 等,所以我们最开始也希望项目能够这么组织。可是找了一下好像并没有创建项目结构的task,所以是时候体验gradle的强大之处了,打开 build.gradle,添加一下代码。
// 在gradle中自定义一个task
// 没错,这个代码是我网上copy下来的,所以不要指望博主能懂 [@_](https://my.oschina.net/u/2505668)@
task "create-dirs" << {
sourceSets*.java.srcDirs*.each { it.mkdirs() }
sourceSets*.resources.srcDirs*.each { it.mkdirs() }
}
保存之后,再次运行 gradle tasks 会发现多了一个 task。
好了,运行
gradle create-dirs
看一下,文件夹下面是不是多出了 src 目录?
编译项目
虽然上面确实新建目录,但是包也还是需要我们自己建立的,不过我想gradle应该是有项目生成插件的,晚上时间紧迫,先不探讨了。继续写项目。 在src/main/java下新建文件及目录 com/cppor/mycrawl/Main.java 输入一个常见的hello world程序,保存。
package com.cppor.mycrawl;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
上面提到gradle是用task来运行操作的,也通过tasks命令来查看了java插件提供了什么命令。下面简要的再次介绍一下几个要用到的命令:
-
assemble 编译源码,打包jar文件,跳过单元测试
-
build 构建完整项目
-
clean 删除构建目录
-
compileJava 编译源码 所以这时候我们先编译源码试一下。
gradle compileJava
然后看一下文件夹下,多出了 build 目录,其中 \build\classes\main\Main.class 应该就是我们刚才写的 Main class了。 然后打开 cmd ,用java命令运行一下 class文件。
不过我们更常用的是jar包,所以执行
gradle build
然后发现在 \build\libs\ 下发现了生成的java包,但是执行后报错:
所以这时候我们要利用gradle制定jar包的Main方法。 打开 build.gradle 添加一下代码:
jar {
manifest {
attributes 'Main-Class':'com.cppor.mycrawl.Main'
}
}
重新编译jar包,看下是不是可以了?
边查资料边写博还挺累,快十一点了,明天继续吧
** 2016-06-28 **
添加依赖
之前提到要使用HttpClient来访问一个url,我们来添加一下apache的http组件依赖。 如果你打开过csproj文件或者pom.xml文件,都可以看到定义的依赖信息,基本上就是文件位置,组件名称之类的内容,其中maven的依赖只有名字和版本号,因为maven会自动从网上下载依赖的jar包(想想也是蛮人性化的,.net有个叫nuget的工具好像类似,不过还没用过),当然gradle的依赖也是可以自动从网上下载的,而且可以直接使用ivy或者maven的依赖仓库。 首先,添加一下maven的默认仓库,然后添加httpclient的依赖,在build.gradle 中添加以下代码:
repositories {
mavenCentral()
maven {
url "https://mavenrepository.com/artifact/org.apache.httpcomponents/httpclient"
}
}
dependencies {
compile 'org.apache.httpcomponents:httpclient:4.5.2'
}
然后重新运行 gradle build,发现已经自动下载了依赖。
然后在Main里添加一点代码,重新编译运行即可。这里就不多写了,自己想写什么都可以。
发现一个问题,编译出来的jar包直接运行会报错httpclient不存在,应该是依赖没有被打进包里,晚上来再看吧
中午又看了一下大大的gradle教程,发现其实他们是提到了“胖”jar包的问题的。 所以需要继续设置。 修改build.gradle
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes 'Main-Class': 'com.cppor.mycrawl.Main'
}
}
排版乱了点,大家凑合着看。 然后重新build,结果就可以啦。
测试项目
其实.net界也是支持单元测试的,vs还提供了一起建立单元测试项目的选项,只是我呆的这两家公司都没有写单元测试的要求。所以我也就没有写单元的习惯。。 而且我们是做项目的并不是产品,所以苦逼之处大家懂的。 所以现在开始写java的话,养成写单元测试的好习惯。TDD(测试驱动开发)也值得一试。 所以首先考虑一下把功能从Main函数中拆出来,写到一个类里,因为刚开始所以不要纠结,新建一个类把这个函数独立处理吧。 首先把访问一个 url 提取成一个类,然后添加 junit 的依赖。 修改 build.gradle
dependencies {
compile 'org.apache.httpcomponents:httpclient:4.5.2'
testCompile 'junit:junit:4+'
}
然后在test\java\com\cppor\mycrawl 下添加一个 MainTest 类。基本代码类似:
public class MainTest {
private HttpTools tools ;
@Before
public void setUp() {
tools = new HttpTools();
}
[@Test](https://my.oschina.net/azibug)
public void testHttpTools() {
try {
String html = tools.getUrlHtml("http://www.cppor.com");
assertFalse(html == null || "".equals(html));
} catch (IOException e) {
e.printStackTrace();
}
}
}
我对junit的操作也不甚了解,看来框架会自动调用 @Before 和 @Test 的函数。然后使用 assert语句进行判断。测试用例写的很牵强,莫怪。
完成之后,可以使用 gradle test 进行测试啦 我的建议是test之前最好先build一下,我好像遇到了直接运行test的时候class没更新的情况。结果就不贴了,大家脑补或自己操作吧。
IntelliJ IDEA
细心的童鞋可能已经发现上面编辑器是很熟悉的idea... 这个号称最好的java IDE,不过我用它主要是因为他的界面比eclipse漂亮 /摊手。 idea当然是支持gradle的,直接用打开文件夹的形式打开项目,然后在 View->Tool Window -> Gradle 下面就可以打开项目的gradle管理界面。
可以见到右边就是之前见到的task列表了。 右键直接执行某个任务就可以了。 虽然能直接上ide,但还是有了cmd基础用起来才更安心了呢。