gradle总结实战

概述

gradle跟maven是很类似的,但是他写起来比maven简洁,所以力荐使用gradle来构建我们的项目,而且gradle使用groovy开发的,所以gradle能够书写逻辑,但是maven这方便就很弱了,下面就来看看gradle。

基本

使用java插件

就像maven里的插件一样,gradle也有插件概念,但是这里引入插件就很简洁,只需要一行。

apply plugin:'java' //该插件会去src/main/java下找源代码,并打包生成build文件夹,里面有很多生成的资源

设置gradle支持utf-8

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

web部分

war插件的使用

进行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项目

下面是一个非标准结构的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插件的使用

开发阶段,我们可以使用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

定义任务 关键字 task 【任务名】

--定义任务
task print{
    doFirst {
        println "01"
    }

    doLast {
        println "02"
    }
}

doFirst和doLast正如名字一样,一个先执行,一个后执行。下面是向已经定义的任务里添加动作(doFirst类型的话,会向顶部添加,doLast的话,会向底部添加)。

print.doFirst {
    println "03"
}

print.doLast {
    println "04"
}

将自己的任务加入到gradle生命周期的一个标准任务里。

build.doFirst {
    //...
}

gradle基于SLF4J实现了一个日志

task printVersion<<{
    logger.info("Version:$version")
}

dependsOn任务依赖

可以在一个任务里,依赖多个任务,执行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")

finalizedBy指定下一个任务

上面[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的。

gradle的多项目构建

在一个项目里创建几个子项目

结构为:

rootPrject
|
---sub01
|       |
|       ----src/main/java
---sub02
|       |
|       ----src/main/java
---subWeb
|       |
|       ----src/main/java
---build.gradle
|
---settings.gradle

在settings.gradle文件里设置:

include 'sub01', 'sub02', 'subWeb'

或者

include 'sub01'
include 'sub02'
include 'subWeb'

注意:setings.gradle会在构建初始化阶段执行。

在根项目下配置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和subProjects来构建公共项目块:

allprojects {       //所有的项目都共有,包括根项目和子项目
    group = "com.robin"
    version = "1.0-SNAPSHOT"
}

subprojects {   //所有的子项目包含java插件
    apply plugin: "java"
}

将子项目的构建脚本也写在根build.gradle写显示不是好的选择,可以在每个子项目下创建一个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'
    }
}
  • 子项目subWeb的build.gradle下有:
apply plugin: "war"
apply plugin: "jetty"

dependencies {
    providedCompile "javax.servlet:servlet-api:2.5"

    compile project(":sub02")
    runtime "javax.servlet:jstl:1.1.2"
}

其他的子项目也是类似的。

gretty插件

apply plugin: 'org.akhikhl.gretty'

gretty {
    servletContainer = 'tomcat8'
    httpPort = 80
    contextPath = ""
    debugSuspend = false
}
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.akhikhl.gretty:gretty:+'
    }
}

gradle打包常用任务

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")
}

gradle插件开发

开发工具: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'
    }
}

新建子工程

新建gradle groovy的plugin01子工程,其build.gradle为:

//插件坐标
group 'com.nxin'
version '1.2'

apply plugin: 'maven'

uploadArchives {
    repositories {
        mavenDeployer {
            //测试,打包到本地
            repository(url: uri('../repo'))
        }
    }
}

dependencies {
    compile gradleApi()
}

在src/main/groovy下新建com.robin.demo.HelloPlugin.groovy类:

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

新建测试子模块 testHelloPlugin,build.gradle为:

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

你可能感兴趣的:(web后端,gradle,插件,java)