工具版本:Gradle:2.2.1 Groovy:2.3.6 JVM:1.6.0_43
maven已经成为java web开发的标配,下面是一个常见的java web工程:
usercenter
包含两个工程,app
是web工程,common
是公共模块,但是app
的main目录下除了java、resources、webapp之外又多了一个native2ascii
的资源目录,严格来说这不符合maven
约定,不过没关系,gradle
除了支持maven
的约定外还允许自定义java或者resources目录
下面是gradle
主配置文件(删除了大部分无关紧要的依赖,能说明问题即可)
// gradle插件buildscript { repositories { jcenter { url "http://jcenter.bintray.com/" } } dependencies { // 远程布署插件 classpath 'org.hidetake:gradle-ssh-plugin:1.0.1' // web容器,支持jetty和tomcat classpath 'org.akhikhl.gretty:gretty:1.2.0' }}// 全局配置,对所有工程有效allprojects { apply plugin: "java" apply plugin: "idea" apply plugin: "eclipse" apply plugin: "maven" group = "com.test" version = "1.0" // 全局属性设置 ext { junitVersion = "4.11" springVersion = "3.0.5.RELEASE" // java文件编码方式设置为utf-8 compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' }}// 所有子工程共有的配置subprojects { // 配置多个maven源 repositories { mavenLocal() mavenCentral() maven { url "http://mirrors.ibiblio.org/pub/mirrors/maven2" } } // 默认情况下gradle会选用版本最高的那个依赖,有时候会带来问题 configurations.all { // 有版本冲突的时候强制使用指定的版本,对于相关依赖也同样有效 resolutionStrategy.force( "org.springframework:spring-core:${springVersion}", ) } // 公共依赖配置 dependencies { compile( "org.springframework:spring-core:${springVersion}", ) testCompile( "junit:junit:${junitVersion}", ) }}// app工程配置project(':app'){ apply plugin: 'war' apply from: 'gretty' // 使用gretty插件运行web工程 gretty { httpPort = 8080 debugPort = httpPort + 1 servicePort = httpPort + 2 statusPort = httpPort + 3 httpsPort = httpPort + 4 httpsEnabled = true contextPath = '/' jvmArgs = ['-Xmx1024M', '-XX:PermSize=128M', '-XX:MaxPermSize=256M'] servletContainer = 'jetty7' scanInterval = 0 inplaceMode = 'hard' debugSuspend = false } // 自定义resource文件夹 sourceSets { main { resources.srcDirs = ['src/main/resources', 'src/main/native2ascii'] } } dependencies { compile( // 依赖common工程 project(":common"), "javax.servlet.jsp:jsp-api:2.1", "javax.servlet:servlet-api:2.5", ) }}// common工程配置project(':common'){ // 设置resource文件目录,引入java文件夹下的xml文件 sourceSets { main { resources.srcDirs = ['src/main/resources', 'src/main/java'] resources.includes = ['src/main/java/**.xml'] } } dependencies { compile( "org.mongodb:mongo-java-driver:2.10.1", fileTree(dir: 'lib' , include: '*.jar' ) ) }}
settings.gradle
中记录子工程,内容只有一行
include 'app','common'
可以把gradle
配置写到多个文件夹下,每个子工程都下都新建一个build.gradle
,如果工程比较简单,也可以像上面样,所有子工程的配置都写到主工程的build.gradle
中
运行的时候只需要在主工程的目录下执行一个命令即可
> gradle app:jettyRun
与maven
相似,gradle
也是以插件的形式来扩展功能,新增插件 apply plugin: 'jetty'
,每个插件有配置都是以代码块的形式提供,上面的配置中使用的gretty
配置web容器,gretty
的配置块是:
gretty { httpPort = 8080 debugPort = httpPort + 1 servicePort = httpPort + 2 statusPort = httpPort + 3 httpsPort = httpPort + 4 httpsEnabled = true contextPath = '/' jvmArgs = ['-Xmx1024M', '-XX:PermSize=128M', '-XX:MaxPermSize=256M'] servletContainer = 'jetty7' scanInterval = 0 inplaceMode = 'hard' debugSuspend = false }
配置简单易懂,无需多讲
这里gretty
配置了jetty7
做为web容器,gradle
自带jetty
插件(不支持java代码热布署,只能更新jsp等),配置如下:
// jetty启动配置jettyRun { httpPort = 8080 contextPath = "" reload = "automatic" scanIntervalSeconds = 1}
上面是简单的替代maven
,显然gradle
能做的不只这些,得益于groovy
的轻巧,gradle
提供了强大的灵活性。下面看一个应用场景。
使用 org.hidetake.ssh
插件,可以把本地的war包发布到远程服务器。在 build.gradle
头部加入如下配置
// 在gradle脚本build之前起作用buildscript { repositories { jcenter() } dependencies { classpath 'org.hidetake:gradle-ssh-plugin:1.0.1' }}
buildscript
用于配置不在maven
仓库的插件,它在gradle
脚本运行之前执行。
在ext
块中配置服务器:
// 远程服务器地址tomcatPath = '/opt/tomcat'// 远程服务器地址remotes { server { host = '192.168.1.1' user = 'root' password = 'root' }}
通常本地开发环境与服务器环境是不一致的,比如本地开发用的端口号是8080,远程服务器使用的域名和端口都不一样(由nginx
转发请求),如果要在发布到远程服务器的时候替换配置文件中的域名,就可以这样。
先在ext
块中配置域名对应关系
replaceUrl = [ 'myapp:8080' : 'myapp:7654', 'mypartner:9090' : 'mypartner:7655',]
再在project(':common')
块中配置执行jar包阶段替换*.properties
配置文件中的域名
// 如果是deploy到远程服务器,打包的时候替换域名jar { def replace = false project.gradle.startParameter.taskNames.each{ command -> if(command.contains('deploy')){ replace = true } } if(replace){ filesMatching('**/*.properties') { filter{ // it变量是filter迭代器中的默认名称,这里代表每一行 def result = it replaceUrl.each{ key,value -> if(it.contains(key)){ result = result.replaceAll key, value } } result } } }}
这段代码是原生的groovy
代码了,gradle
的灵活性就体现在这里了,关于groovy
语言,大家自行脑补。
project.gradle.startParameter.taskNames
是gradle命令行参数,如gradle clean app:deploy
,那么命令行参数就是['clean', 'app:deploy']
filesMatching('**/*.properties')
是过滤所有的以properties
结尾的文件,**
是递归查找。接下来是布署代码了:
// 布署至远程服务器,上传的war名为app.wartask deploy(dependsOn: war) << { ssh.run { session(remotes.server) { put "$war.archivePath.path", "$tomcatPath/webapps/app.war" execute "$tomcatPath/bin/shutdown.sh" execute "rm -rf $tomcatPath/webapps/ROOT/*" execute "unzip -oq $tomcatPath/webapps/app.war -d $tomcatPath/webapps/ROOT" execute "rm -f $tomcatPath/webapps/app.war" execute "$tomcatPath/bin/startup.sh" } }}
deploy
只是简单的执行shell命令,上传war包,关闭tomcat,解压war,删除war,启动tomcat。 布署命令:gradle clean app:deploy