gradle跟maven是很类似的,但是他写起来比maven简洁,所以力荐使用gradle来构建我们的项目,而且gradle使用groovy开发的,所以gradle能够书写逻辑,但是maven这方便就很弱了,下面就来看看gradle。
就像maven里的插件一样,gradle也有插件概念,但是这里引入插件就很简洁,只需要一行。
apply plugin:'java' //该插件会去src/main/java下找源代码,并打包生成build文件夹,里面有很多生成的资源
gradle版本的差异,有可能存在不支持汉字,所以这里配置支持UTF-8,最好每次构建项目,都配置上。
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
项目编译jdk版本设置,有了这个属性,更换不同版本jdk进行编译就变得非常简单,比如:我电脑安装的是jdk8,但是我为了打成jar包兼容低版本的项目,以前我们的做法是,在电脑上安装多个jdk然后修改环境变量进行切换,现在不用那么麻烦,你只需要讲下面的两个属性sourceCompatibility,targetCompatibility都设置1.7,这样即使真是环境是jdk8,但是编译后的class是jdk7的环境的。
version = 0.1 //项目版本
//设置java版本
sourceCompatibility = 1.7
targetCompatibility = 1.7
jar{
manifest {
attributes 'Main-Class':'com.robin.demo' //在jar包的MANIFEST.MF里添加属性(这里是运行的主类)
}
}
maven 的标准目录结构,大家应该有一定印象吧!src/main/java/* , src/main/resources/, src/test/java/ 等等,但是有些项目的特殊性,这里支持结构的定制(一般不要修改,按照默认的标准就可以)。
//改变默认的目录结构
sourceSets {
main{
java{
srcDirs = ['src'] //默认的源码结构是src/main/java,这里修改成了src
}
}
test{
java{
srcDirs = ['test'] //默认的源码结构是src/test/java,这里修改成了test
}
}
}
将src/main下的generated文件夹修改为类路径,如何在geadle里设置脚本?马上想到的解法:
sourceSets {
main {
java {
srcDirs = ['src/main/generated']
}
}
}
上面的写法是错误的,为何?因为这样设置,会将源码的目录设置成了generated,而原来的src/main/java目录就失效了,不是资源目录了。正确的写法是:
sourceSets {
main {
java {
srcDirs += 'src/main/generated'
}
}
}
解释:srcDirs这个属性的类型是数组,如果要改变的话就直接=[’ ‘],这样就改变整个数组的值,而 +=’ ’ 是向数组里添加值。
某些class不想打进jar包里去,或者war包里去,如何做?
sourceSets {
main {
java {
exclude 'com/robin/demo' //这样com.robin.demo包下的所有类都不会打进jar下
}
}
}
我们在src/main/java/**.xml的mybatis映射文件打包到war包下的classes下会失败,如何将解决?
1. 方式一:
在resources资源目录下新建com/robin/**.xml文件,这样打包会打到classes下的。
2. 方式二:将src/main/java/**.xml配置成资源目录,在build.gradle里添加:
sourceSets {
main {
resources {
//这里的srcDir是方法,上面的是属性
srcDir 'src/main/java' //可以将java目录下的所有非.java资源打包到classes下
}
}
}
输出定义:
buildDir = 'out' //定义输出路径,原来的是build文件夹下的
默认使用的maven仓库下载jar,但是速度就…这里给出如何配置私服,下面的给出的是配置aliyun的私服地址。
repositories{
jcenter()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public'--修改成阿里云的仓库
}
mavenCentral()
}
重头戏来了,开始怎么引入jar包了,也就是配置依赖。下面的第一行compile是完整写法,第二个compile是简写。
dependencies {
compile group:'org.apache.commons', name:'comcc', version:'3.1'
compile 'org.apache.commons:comcc:3.1' --上下等价,下面是简写
}
在项目构建的时候经常发生jar冲突问题,此时如何消除依赖了,下面给出消除依赖的方法。
compile ("com.alibaba:dubbo:${dubboVersion}") {
exclude group: "org.springframework"
exclude module: "comcc" // name所对应的
exclude group: "", module: "" //可以更加详细
}
# exclude group: groupName
进行war包构建相关的逻辑,需要引入war这个插件。
apply plugin: 'war' --这个插件主要应用与web下开发的,并且自扩展java插件
一个web项目的标准结构,如下:
|
---build.gradle
|
---src
|
--main
|
---java/..
|
---resources/..
|
----webapp
|
---WEB-INF/web.xml
|
---css/..
有的依赖是不需要跟war打在一起的,那么就可以使用providedCompile.
dependencies {
providedCompile 'javax.servlet:servlet-api:2.5' --这个依赖由容器(例如tomcat)提供,这里会有jetty提供,他不会打包到war包里面
runtime 'javax.servlet:jstl:1.1.2' --jstl这种依赖,编译时不需要,运行时需要,会成为war包的一部分
}
--运行后会在build/libs下有个war包
下面是一个非标准结构的web项目,我们如何对下面的结构进行定制了?
|
--build.gradle
|
--src
| |
| --main/java
|
|
---static
| |
| --css
|
----webfile
|
--WEB-INF/web.xml
|
---jsp/..
写法:
webAppDirName = 'webfile' --默认属性是src/main/webapp
war{
from 'static'
}
添加多个war资源目录,由于from的参数是from(Object…obj),所以用可变参数结构来添加:
war {
from 'static01', 'static02', ...
}
开发阶段,我们可以使用jetty作为web容器,进行开发,速度快,便捷。下面通过插件引入,很简洁
apply plugin: 'jetty'
运行指令:
gradle jettyRun (即使没有jar包也能跑起来)
给jetty配置属性:
jettyRun {
httpPort = 80 --修改jetty运行的端口号
contextPath = 'todo' --修改应用名
}
// http://localhost:80/todo
我们在使用Project和Task类时,这里已经为我们提供了默认的对象,我们只需要调用方法即可
version '1.0' --调用Project里的setVersion(..)方法的
当然我们可以在build.gradle里定义自己的外部属性,然后直接引用自己定义属性,通过ext命名空间:
ext {
vertxVersion = "3.1.2"
}
使用:
compile "io.vertx:vertx-core:${vertxVersion}" --这里一定要用""来引起字符串,不要用'',否则${vertxVersion}就变成了字符串而不会被转义
建议:
尽量使用” “而少使用’ ‘
--定义任务
task print{
doFirst {
println "01"
}
doLast {
println "02"
}
}
doFirst和doLast正如名字一样,一个先执行,一个后执行。下面是向已经定义的任务里添加动作(doFirst类型的话,会向顶部添加,doLast的话,会向底部添加)。
print.doFirst {
println "03"
}
print.doLast {
println "04"
}
将自己的任务加入到gradle生命周期的一个标准任务里。
build.doFirst {
//...
}
task printVersion<<{
logger.info("Version:$version")
}
可以在一个任务里,依赖多个任务,执行run之前,会先执行[two, first] ,这里two, first这两个任务执行没有顺序。
task first<<{
println "one"
}
task two<<{
println "two"
}
task run(dependsOn:[two, first]) {
}
另一种添加依赖的方式:
task third {
println "third"
}
third.dependsOn("run")
上面[two, first]没有顺序,可以使用finalizedBy强行指定顺序。
task first<<{
println "one"
}
task two<<{
println "two"
}
two.finalizedBy first
task run {
print("hello")
}
随便运行gradle build/gradle clean…都会执行run这个任务块,这就是任务配置块
为何他总会执行?
要从gradle的构建生命周期来解释,每个任务执行都会经历:初始化、配置、执行,三个阶段,
所以配置块在第二阶段会执行
配置任务快执行是有一定顺序的,当任务A依赖任务B,则A->B的。
结构为:
rootPrject
|
---sub01
| |
| ----src/main/java
---sub02
| |
| ----src/main/java
---subWeb
| |
| ----src/main/java
---build.gradle
|
---settings.gradle
include 'sub01', 'sub02', 'subWeb'
或者
include 'sub01'
include 'sub02'
include 'subWeb'
注意:setings.gradle会在构建初始化阶段执行。
ext.projectIds = [group:"com.robin", version:"1.0-SNAPSHOT"]
group = projectIds.group;
version = projectIds.version
project(":sub01") { //每个子模块也是一个项目,:是路径,我们可以申明sub/sub001下的sub001位一个子项目,此时写法是project(:sub:sub001)
group = projectIds.group;
version = projectIds.version
apply plugin: "java"
}
project(":sub02") {
group = projectIds.group;
version = projectIds.version
apply plugin: "java"
}
project(":subWeb") {
group = projectIds.group;
version = projectIds.version;
apply plugin: "war"
apply plugin: "jetty"
repositories {
mavenCentral();
}
dependencies {
providedCompile "javax.servlet:servlet-api:2.5"
runtime "javax.servlet:jstl:1.1.2"
}
}
每个项目都有group和versin属性,上面的做法是将group和version的值放入list集合然后添加到ext域里去,这样才能被其他模块引用。一般我们将其他模块需要引用的变量,我们会放入到ext里去的。
一般子项目sub01和sub02会打成jar包的,而subWeb的子项目会打成war包的,并且subWeb项目会依赖sub01、sub02这两个项目。下面我们来生命项目之间的依赖:
project(":sub01") {
...
apply plugin: "java"
}
project(":sub02") {
apply plugin: "java" //一定要加上这个,否则项目之间的依赖会出错
dependencies {
compile project(':sub01'); //编译时依赖sub01
}
}
project(":subWeb") {
apply plugin: "war"
apply plugin: "jetty"
repositories {
mavenCentral();
}
dependencies {
providedCompile "javax.servlet:servlet-api:2.5"
compile project(":sub02")
runtime "javax.servlet:jstl:1.1.2"
}
}
allprojects { //所有的项目都共有,包括根项目和子项目
group = "com.robin"
version = "1.0-SNAPSHOT"
}
subprojects { //所有的子项目包含java插件
apply plugin: "java"
}
将子项目的构建脚本也写在根build.gradle写显示不是好的选择,可以在每个子项目下创建一个build.gradle文件。
allprojects { //所有的项目都共有,包括根项目和子项目
group = "com.robin"
version = "1.0-SNAPSHOT"
// apply plugin: "java" //若是这里加了java插件,那么跟项目下的src目录也是起作用,所以不建议添加在此处
}
subprojects {
apply plugin: "java"
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
}
apply plugin: "war"
apply plugin: "jetty"
dependencies {
providedCompile "javax.servlet:servlet-api:2.5"
compile project(":sub02")
runtime "javax.servlet:jstl:1.1.2"
}
其他的子项目也是类似的。
apply plugin: 'org.akhikhl.gretty'
gretty {
servletContainer = 'tomcat8'
httpPort = 80
contextPath = ""
debugSuspend = false
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.akhikhl.gretty:gretty:+'
}
}
def replace(fileName, map) {
def fl = file(fileName)
def content = fl.getText("UTF-8")
map.each { k, v -> content = content.replace(k, v) }
fl.write(content, "UTF-8")
}
def cp(source, dest) {
file(dest).write(file(source).getText("UTF-8"), "UTF-8")
}
开发工具:idea, gradle
在idea里新建root工程plugins, 修改build.gradle
allprojects {
group 'com.robin'
version '1.0-SNAPSHOT'
}
subprojects {
apply plugin: 'groovy'
repositories {
maven {
url "http://nexus.nxin.com/nexus/content/groups/public/"
}
mavenCentral()
jcenter()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
}
//插件坐标
group 'com.nxin'
version '1.2'
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
//测试,打包到本地
repository(url: uri('../repo'))
}
}
}
dependencies {
compile gradleApi()
}
package com.robin.demo
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* Created by robin on 2017/1/12.
*/
class HelloPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('hello') {
println "HelloWorld";
}
}
}
方便 apply plugin: shortName r;在resources下新建META-INF/gradle-plugins/hello.properties,hello就是shortNmae,hello.properties里的内容为:
implementation-class=com.robin.demo.HelloPlugin
然后在子工程下打包,执行:
gradle -q upload //打包成jar
group 'com.robin'
version '1.0-SNAPSHOT'
buildscript {
repositories {
maven {
url uri('../repo')
}
}
dependencies {
classpath 'com.nxin:plugin01:1.2'
}
}
apply plugin: 'hello'
repositories {
mavenCentral()
}
dependencies {
// compile 'org.codehaus.groovy:groovy-all:2.3.11'
// testCompile group: 'junit', name: 'junit', version: '4.11'
}
在子模块中运行 gradle hello