高效软件工程的核心:自动化
自动化构建类型及其进化史:请求式构建 -> 触发式构建 -> 计划式构建
自动化构建工具要素 :任务(DAG - Directed Acyclic Graph,即一段可工作的构件单元 + 依赖)、依赖管理
Gradle 箴言
- 让不可行变得可行,让可行变得易行,让易行变得简洁
- Maven VS Gradle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany.app</groupId> <artifactId>my-app</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
|
1 2 3 4 5 6 7 8 9 10
| apply plugin: 'java' group = 'com.mycompany.app' archivesBaseName = 'my-app' version = '1.0-SNAPSHOT' repositories { mavenCentral() } dependencies { testCompile 'junit:junit:4.11' }
|
Gradle API

与其它构建构建集成
- Gradle Script -> import -> Ant Scripts
- Gradle Script -> use -> Ant tasks
- Maven POM -> generate via converter -> Gradle Script
- Gradle Script -> publish artifact -> Maven/Ivy repository -> download dependency -> Gradle Script
持续交付
- 提交阶段 :编译和单元测试 -> 集成测试 -> 代码评审 -> 构件
- 可行阶段 ;部署 -> 烟雾及可行性测试
- UAT 阶段 :即用户验收,部署 -> 烟雾测试
- PRD 阶段 :即运行上线,部署 -> 烟雾测试
安装 Gradle
- 安装 Java
- 下载 Gradle
- 配置 :export GRADLE_HOME=/opt/gradle 和 export PATH=$PATH:$GRADLE_HOME/bin
- 验证 :$ gradle -v
- 其它可选配置 :GRADLE_OPTS=”-Xmx1024m”,更改 JVM 堆大小
一个简单的例子
1 2 3 4 5
| task helloWorld { doLast { println 'Hello world!' } }
|
1 2
| $ gradle –q helloWorld Hello world!
|
一个简单依赖的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| task startSession << { chant() } def chant() { ant.echo(message: 'Repeat after me...') } 3.times { task "yayGradle$it" << { println 'Gradle rocks' } } yayGradle0.dependsOn startSession yayGradle2.dependsOn yayGradle1, yayGradle0 task groupTherapy(dependsOn: yayGradle2)
|
1 2 3 4 5 6 7 8 9 10
| $ gradle groupTherapy :startSession [ant:echo] Repeat after me... :yayGradle0 Gradle rocks :yayGradle1 Gradle rocks :yayGradle2 Gradle rocks :groupTherapy
|
更多命令
1 2 3 4
| $ gradle -q tasks $ gradle -q tasks --all $ gradle yayGradle0 groupTherapy $ gradle groupTherapy -x yayGradle0
|
案例(一):ToDo App 工程

- 默认情况下,java 插件会在 src/main/java 中搜索源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ├── build.gradle └── src └── main └── java └── com └── manning └── gia └── todo ├── ToDoApp.java ├── model │ └── ToDoItem.java ├── repository │ ├── InMemoryToDoRepository.java │ └── ToDoRepository.java └── utils │ ├── CommandLineInput.java │ └── CommandLineInputHandler.java ├── build │ ├── libs │ │ └── todo-app.jar
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| $ gradle build :compileJava :processResources UP-TO-DATE :classes :jar :assemble :compileTestJava UP-TO-DATE :processTestResources UP-TO-DATE :testClasses UP-TO-DATE :test :check :build $ java -cp build/classes/main com.manning.gia.todo.ToDoApp
|
- use below : $ java –jar build/libs/todo-app-0.1.jar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apply plugin: 'java' version = 0.1 sourceCompatibility = 1.6 sourceSets { main { java { srcDirs = ['src'] } } test { java { srcDirs = ['test'] } } } buildDir = 'out' // Changes project output property to directory out jar { manifest { attributes 'Main-Class': 'com.manning.gia.todo.ToDoApp' } }
|
配置和使用外部依赖
1 2 3 4 5 6
| repositories { mavenCentral() } dependencies { compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' }
|
案例(二):ToDo Web App 工程

1 2 3 4 5 6 7 8 9 10 11 12
| apply plugin: 'java' apply plugin: 'war' apply plugin: 'jetty' repositories { mavenCentral() } dependencies { providedCompile 'javax.servlet:servlet-api:2.5', 'javax.servlet.jsp:jsp-api:2.1' runtime 'javax.servlet:jstl:1.1.2', 'taglibs:standard:1.1.2' }
|
1 2 3 4 5 6 7 8 9
| ├── build.gradle └── src └── main ├── java └── webapp ├── WEB-INF │ └── web.xml ├── css └── jsp
|
- 运行 $ jar tf todo-webapp-0.1.war,其 WAR 包目录结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ├── META-INF │ └── MANIFEST.MF ├── WEB-INF │ ├── classes │ │ └── com │ │ └── manning │ │ └── gia │ │ └── todo │ │ ├── model │ │ │ └── ToDoItem.class │ │ ├── repository │ │ │ ├── InMemoryToDoRepository.class │ │ │ └── ToDoRepository.class │ │ └── web │ │ └── ToDoServlet.class │ ├── lib │ │ └── jstl-1.1.2.jar │ └── web.xml ├── css │ ├── base.css │ └── bg.png └── jsp ├── index.jsp └── todo-list.jsp
|
定制工程布局(unconventional web project layouts)
- 在置入的容器中运行 :$ gradle jettyRun
1 2 3 4 5 6 7 8 9 10 11 12 13
| ├── build.gradle ├── src │ └── main │ └── java │ └── ... ├── static │ └── css └── webfiles ├── WEB-INF │ └── web.xml └── jsp ├── index.jsp └── todo-list.jsp
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| apply plugin: 'java' apply plugin: 'war' apply plugin: 'jetty' repositories { mavenCentral() } dependencies { providedCompile 'javax.servlet:servlet-api:2.5', runtime 'javax.servlet:jstl:1.1.2', } webAppDirName = 'webfiles' war { from 'static' }
|
定制 jetty : http://localhost:9090/todo
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| apply plugin: 'java' apply plugin: 'war' apply plugin: 'jetty' repositories { mavenCentral() } dependencies { providedCompile 'javax.servlet:servlet-api:2.5', runtime 'javax.servlet:jstl:1.1.2', } jettyRun { httpPort = 9090 contextPath = 'todo' }
|
Gradle wrapper
- 包装器 :运行 Gradle 脚本而无需事先安装 Gradle,同时还能选择 Gradle 版本。
- 运行 :$ gradle wrapper 或 $ gradlew jettyRun
1 2 3 4 5 6 7 8 9 10 11 12 13
| apply plugin: 'java' apply plugin: 'war' apply plugin: 'jetty' repositories { mavenCentral() } dependencies { providedCompile 'javax.servlet:servlet-api:2.5', runtime 'javax.servlet:jstl:1.1.2', } task wrapper(type: Wrapper) { gradleVersion = '1.7' }
|
1 2 3 4 5 6 7 8
| ├── build.gradle ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew └── gradlew.bat └── src
|
定制 Wrapper
1 2 3 4 5
| task wrapper(type: Wrapper) { gradleVersion = '1.2' distributionUrl = 'http://myenterprise.com/gradle/dists' distributionPath = 'gradle-dists' }
|