下载Gradle地址:Gradle Build Tool
gradle init
使用gradle init即可创建一个gradle项目的骨架
文件说明 可以看到一共创建了2个目录和6个文件,其中2个目录和4个文件都跟wrapper有关: gradlew:linux或者Unix下用于执行wrapper命令的Shell脚本 gradlew.bat:Windows下用于执行wrapper命令的批处理脚本 gradle-wrapper.jar:用于下载Gradle的相关代码实现 gradle-wrapper.properties:wrapper所使用的配置信息,比如gradle的版本等信息
详细的信息可参看前文的说明:
https://blog.csdn.net/liumiaocn/article/details/84232536
另外就是settings.gradle和build.gradle:
build.gradle: 用于存放构建相关的Task
settings.gradle: 用于存放设定相关的信息
详细的信息可参看前文的说明:
https://blog.csdn.net/liumiaocn/article/details/84192318
内容确认
- settings.gradle
通过内容确认可以看到,settings.gradle中只设定了rootProject.name
- build.gradle
而build.gradle则没有任何设定,只有注释,这也正是初始化的意义所在。
init & wrapper
init的任务是依赖于wrapper的,执行init的时候同时会执行wrapper,因为wrapper是gradle官方推荐的方式,自然在初始化的时候也会将wrapper集成进去。
https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/maven/MavenDeployer.html
打包
>
jar 包会出现在这里 \build\libs
预装个eclipse的插件,方便对build.gradle编译,Minimalist Gradle Editor 1.0.1
指令
gradle -version 查看版本 ------------------------------------------------------------ Gradle 4.4.1 ------------------------------------------------------------ Build time: 2017-12-20 15:45:23 UTC Revision: 10ed9dc355dc39f6307cc98fbd8cea314bdd381c Groovy: 2.4.12 Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017 JVM: 1.8.0_66 (Oracle Corporation 25.66-b17) OS: Windows 10 10.0 amd64 gradle projects 查看工程信息 gradle tasks 查看任务信息 gradle task name 执行task任务
Gradle 工作流程
以multi-project build为例,Gradle工作流程如下:
初始化阶段:首先解析settings.gradle
Configration阶段:解析每个Project中的build.gradle,解析过程中并不会执行各个build.gradle中的task。
经过Configration阶段,Project之间及内部Task之间的关系就确定了。一个 Project 包含很多 Task,每个 Task 之间有依赖关系。Configuration 会建立一个有向图来描述 Task 之间的依赖关系, 所有Project配置完成后,会有一个回调project.afterEvaluate,表示所有的模块都已经配置完了。
执行Task任务
subprojects 和 allprojects 的区别
allprojects是对所有project的配置,包括Root Project。而subprojects是对所有Child Project的配置
Task内部执行顺序
当我们执行Task的时候,就是执行其拥有的actions列表,是一个List。把Task执行之前、Task本身执行、Task之后执行分别称为doFirst、doSelf、doLast
buildscript代码块的作用
其实答案非常简单。buildscript中的声明是gradle脚本自身需要使用的资源。可以声明的资源包括依赖项、第三方插件、maven仓库地址等。
而在build.gradle文件中直接声明的依赖项、仓库地址等信息是项目自身需要的资源。
gradle是由groovy语言编写的,支持groovy语法,可以灵活的使用已有的各种ant插件、基于jvm的类库,
这也是它比maven、 ant等构建脚本强大的原因。虽然gradle支持开箱即用,但是如果你想在脚本中使用一些第三方的插件、类库等,
就需要自己手动添加对这些插件、类库的 引用。而这些插件、类库又不是直接服务于项目的,而是支持其它build脚本的运行。
所以你应当将这部分的引用放置在buildscript代码块中。 gradle在执行脚本时,会优先执行buildscript代码块中的内容,
然后才会执行剩余的build脚本。
如何升级?
我们提供了一个文档来帮助你从Gradle 4.x升级到Gradle 5.0。在升级之前,我们建议你:
使用Gradle包装器升级到Gradle 6.5.1:gradle wrapper --gradle-version = 6.5.1
运行gradle help --scan列出已弃用的Gradle API以及使用了这些API的地方(包括插件)。
更新Gradle插件,尤其是构建扫描报告中列出的已启用的插件。
如何查看废弃的打印信息
gradle --warning-mode all
dependencies里的依赖变化
当我们升级gradle 时,默认的依赖由之前的compile更改为implementation了。
3.0 以下版本build.gradle中依赖的写法:
compile fileTree(dir: 'libs', include: ['*.jar'])
但在3.0后的写法为
implementation fileTree(dir: 'libs', include: ['*.jar'])
二、区别
在3.X版本中,compile 指令被标注为过时方法,而新增了两个依赖指令,一个是implementation和api,这两个都可以进行依赖添加,但是有什么区别呢?
api
完全等同于compile指令,没区别,你将所有的compile改成api,完全没有错。
implementation
这个指令的特点就是,对于使用了该命令编译的依赖,对该项目有依赖的项目将无法访问到使用该命令编译的依赖中的任何程序,也就是将该依赖隐藏在内部,而不对外部公开。
示例
比如我在一个library中使用implementation依赖了gson库,然后我的主项目依赖了library,那么,我的主项目就无法访问gson库中的方法。这样的好处是编译速度会加快,推荐使用implementation的方式去依赖,如果你需要提供给外部访问,那么就只能使用api方式了。
在Google IO相关话题的中提到了一个建议,就是依赖首先应该设置为implementation的,如果没有错,那就用implementation,如果有错,那么使用api指令,这样会使编译速度增快。
如何生成pom.xml文件和子项目?
gradle install
成功后,会在 build目录下的 poms 文件夹下生成 pom-default.xml,将其改名为 pom.xml 拷贝到项目的根目录下即可。
打包
gradle jar
发布全部项目
gradle publish
发布单独一个子项目
gradle gamioo-game:publish
发布的仓库除了nexus,还可以选择github自身的,具体请参考
签名:
2.gpg秘钥安装
2.1 安装gpg
gpg(GunPG)是一款用于生成秘钥的加密软件。
Windows下载地址:
https://www.gpg4win.org/download.html
下载完成后安装,windows
会自带可视化工具Kleopatra
,后续操作会相对简单
创建密钥
- 安装完成后,运行
Kleopatra
,点击文件
> New OpenPGP key Pair
,弹出如下创建向导, - 出现下图时,建议选中
使用密码句保护生成的密钥
,选中后,导出密钥等操作需要输入密码确认,更加安全些。 - 并建议打开高级设置,将加密算法改为
RSA,有效期改为永久
认证,发布
- 密钥创建成功后,邮件出现如下选想,先认证,后发布。发布成功后,点击
服务器上查找...
,输入名称可以查到已上传的密钥。 - 按照我的理解,经过上述操作,密钥申请上传就完事了,但是后续步骤时仍然出现服务器找不到密钥的情况,所以我使用如下命令(
CMD运行即可
),重新上传了密钥。
# 将公钥发布到GPG密钥服务器 gpg --keyserver keyserver.ubuntu.com --send-keys 0320B80E497B1B5B16C75CBA8F7A2D11B0678161 gpg: sending key B79702E4216EAD45 to hkp://keyserver.ubuntu.com # 查询是否已将公钥发布到服务器 gpg --keyserver keyserver.ubuntu.com --recv-keys 0320B80E497B1B5B16C75CBA8F7A2D11B0678161 gpg: key B79702E4216EAD45: "gamioo <********@qq.com>" not changed gpg: Total number processed: 1 gpg: unchanged: 1
生成gpg文件
- 如果创建密钥时,设置了密码保护,此部需要输入密码。
gpg --export-secret-keys -o E:/stone/happy/server/trunk/tool/key/0320B80E497A1B5B16C75CBA8F7A2D11B0678161.gpg
配置发布脚本
上述密钥操作成功后,需要到项目中配置相关脚本,并将密钥、maven帐号等相关信息配置好。下面直接贴出我的配置
gradle.properties
- 新建名为
gradle.properties
的文件,内容如下,注意填写自己的信息
sonatypeUsername= # 最开始注册测sonatype帐号 sonatypePassword= # sonatype密码 signing.keyId= # 密钥ID(指纹)后8位 signing.password= # 密钥保护密码 signing.secretKeyRingFile=E:/gamioo/key/0320B80E497B1B5B16C75CBA8F7A2D11B0678161.gpg # 创建密钥最后一步生成的gpg文件目录
其中密钥ID(指纹)后8位就是 0320B80E497B1B5B16C75CBA8F7A2D11B0678161的最后八位:
B0678161
发布到maven中央库,每次发布的版本号要不一样,否则会release 不成功,需要在staging repository先close在release
build.gradle
- 要发布的项目,的配置文件关键脚本
publishing { repositories { maven { if (project.version.endsWith('-SNAPSHOT')) { //快照版本的nexus仓库地址 name 'snapshots'; url 'https://oss.sonatype.org/content/repositories/snapshots/'; } else { name 'releases'; url 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'; } credentials { username = System.getenv("NEXUS_USERNAME"); password = System.getenv("NEXUS_PASSWORD"); } } } publications { mavenJava(MavenPublication) { groupId project.group; artifactId project.name; version project.version; //若是war包,就写components.web,若是jar包,就写components.java from components.java; artifact sourcesJar; artifact javadocJar; suppressAllPomMetadataWarnings();//屏蔽所有编译时的WARNING pom { name = project.name; description = 'This is a game server framework.'; url = 'https://gamioo.io'; packaging = 'jar'; scm { connection = 'scm:git@github.com:jiangguilong2000/gamioo.git'; developerConnection = 'scm:git@github.com:jiangguilong2000/gamioo.git'; url = 'https://github.com/jiangguilong2000/gamioo/'; } licenses { license { name = 'Apache-2.0 License'; url = 'https://github.com/jiangguilong2000/gamioo/blob/master/LICENSE'; distribution = 'repo'; } } developers { developer { id = 'Allen'; name = '阿星'; email = '********@qq.com'; url = 'https://blog.gamioo.io'; } } } // pom.withXml { // asNode().appendNode('description','A demonstration of maven POM customization'); // } } } } ext."signing.keyId" = System.getenv('SIGNING_KEYID') ext."signing.password" = System.getenv('SIGNING_PASSWORD') ext."signing.secretKeyRingFile" = System.getenv('SIGNING_SECRETKEYRINGFILE') signing { //sign configurations.archives; sign publishing.publications.mavenJava; }
- 双击
publish
即可自动发布。发布成功后,出现如下信息
下午 4:46:19: Executing 'publish'... > Configure project : > Task :gamioo-log:compileJava UP-TO-DATE > Task :gamioo-cache:compileJava NO-SOURCE > Task :gamioo-cache:processResources NO-SOURCE > Task :gamioo-cache:classes UP-TO-DATE > Task :gamioo-cache:jar > Task :gamioo-cache:generateMetadataFileForMavenJavaPublication > Task :gamioo-cache:generatePomFileForMavenJavaPublication > Task :gamioo-cache:javadoc NO-SOURCE > Task :gamioo-cache:javadocJar UP-TO-DATE > Task :gamioo-cache:sourcesJar UP-TO-DATE > Task :gamioo-cache:signMavenJavaPublication > Task :gamioo-cache:publishMavenJavaPublicationToReleasesRepository > Task :gamioo-cache:publish BUILD SUCCESSFUL in 56s 8 actionable tasks: 5 executed, 3 up-to-date 下午 4:47:16: Execution finished 'publish'.
Close
运行完脚本后,项目还没真正公开,需要到个人仓库中完成发布。
打开如下网址,并使用sonatype帐号登录。
https://oss.sonatype.org/#welcome
依次点击Staging Repostories - 勾选项目 - close。成功后状态Activity会改变为Operation in progress正在运行,其实他正在检测你发布的程序。
Close失败
- 点击
close
后,他会运行一段时间,验证你发布的项目是否符合规范,不符合规范会报错,如下图,我第一次发布时报的错。
javadoc 不能省,否则会报错
Release
把Close报错全部解决后,重新运行上传脚本publish,然后重新Close,如果还报错,就重复以上步骤,直到Close成功后,Release亮起!
点击Release
- Release成功后,可以搜索到自己的项目了!
但是此时可能还无法立即根据坐标引用自己的依赖,需要过
几个小时才能真正发布到中央
镜像仓库。
所以我们如果马上去https://mvnrepository.com/ 搜索的话其实还是搜索不到,需要等上一段时间。
发布10分钟~2小时后,Central Repository: io/gamioo
应该就能搜到你发布的版本了。
要不要每次在JIRA单子上回复,这个不大清楚,观察一下!
https://mvnrepository.com/artifact/io.gamioo/
然后就可以在仓库页面查看了,要查看编译时的日志,可以做一下指令
gradle build --info
每次发布正式版,都需要去做close和release的操作
默认新建一个gradle项目,并不会新建java,resource文件夹,需要自己手工来写,那么,可否由脚本创建呢?答案是可以。
创建task
/**创建java和resource目录*/ task createDirs { sourceSets*.java.srcDirs*.each { it.mkdirs() } sourceSets*.resources.srcDirs*.each { it.mkdirs() } }
执行 gradle createDirs ,就创建好了
如何进行一次编译并能看到日志
gradle -b build.gradle release -x test --info --stacktrace
如何打印临时日志
logger.info("allen " + 'git rev-parse --short HEAD'.execute().text.trim());
在test里设置环境变量
tasks.withType(Test) { systemProperty "project.name", project.name; }
读取环境变量
logger.info(System.getProperty("project.name"))
用jenkins 调用gradle ,然后通过gradle调用git会导致版本号取不到的问题
用以下方式获取,关键是
[], project.rootDir 这个
manifest.attributes["Implementation-Version"] = project.version + "-" + 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim() + "[" + 'git rev-list HEAD --count'.execute([], project.rootDir).text.trim() + "]-S" + new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+08:00")) + "R1";
用CI工具蓝盾/jekins 在gradle打包编译时,会遇到编译失败,日志会有如下异常:
----- End of the daemon log ----- FAILURE: Build failed with an exception. * What went wrong: Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed) * Try: Run with --debug option to get more log output. Run with --scan to get full insights. * Exception is: org.gradle.launcher.daemon.client.DaemonDisappearedException: Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed) at org.gradle.launcher.daemon.client.DaemonClient.handleDaemonDisappearance(DaemonClient.java:249) at org.gradle.launcher.daemon.client.DaemonClient.monitorBuild(DaemonClient.java:222) at org.gradle.launcher.daemon.client.DaemonClient.executeBuild(DaemonClient.java:184) at org.gradle.launcher.daemon.client.DaemonClient.execute(DaemonClient.java:147) at org.gradle.launcher.daemon.client.DaemonClient.execute(DaemonClient.java:98) at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:57) at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:212) at org.gradle.launcher.cli.DefaultCommandLineActionFactory$ParseAndBuildAction.execute(DefaultCommandLineActionFactory.java:275) at org.gradle.launcher.cli.DefaultCommandLineActionFactory$ParseAndBuildAction.execute(DefaultCommandLineActionFactory.java:247) at org.gradle.launcher.cli.DebugLoggerWarningAction.execute(DebugLoggerWarningAction.java:82) at org.gradle.launcher.cli.DebugLoggerWarningAction.execute(DebugLoggerWarningAction.java:30) at org.gradle.launcher.cli.WelcomeMessageAction.execute(WelcomeMessageAction.java:92) at org.gradle.launcher.cli.WelcomeMessageAction.execute(WelcomeMessageAction.java:38) at org.gradle.launcher.cli.NativeServicesInitializingAction.execute(NativeServicesInitializingAction.java:44) at org.gradle.launcher.cli.NativeServicesInitializingAction.execute(NativeServicesInitializingAction.java:26) at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:41) at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:26) at org.gradle.launcher.cli.DefaultCommandLineActionFactory$WithLogging.execute(DefaultCommandLineActionFactory.java:240) at org.gradle.launcher.Main.doAction(Main.java:35) at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:50) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:67) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60) at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37) at org.gradle.launcher.GradleMain.main(GradleMain.java:31) * Get more help at https://help.gradle.org
是因为CI工具并发执行会将gradle杀掉,
只要在gradle指令后追加 --no-daemon 就行
开发环境开启 gradle daemon 可以极大的提高编译速度
touch ~/.gradle/gradle.properties && echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties
正式打包环境和 Continuous Integration 环境不建议开启 daemon。
打 release 包时可通过 --no-daemon
命令暂时关闭 daemon。
也可以通过调整gradle运行时的内存处理此问题,毕竟3.0后,默认开始这个配置的,
在项目的根目录下建立gradle.properties,里面加
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.parallel=true
然后在执行gradle命令时,加上
gradle -Dorg.gradle.jvmargs="-Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError" release -x test --info --stacktrace
也可以把gradle.properties放到gradle根目录下/home/cnc_build/svr_pkg/gradle-6.8.3
如何在gradle test 时也能把异常信息输出到 gradle r日志中
如何调用?
gradle :gamioo-game:test --tests io.gamioo.game.ResourceManagerTest
build.gradle 里如何设置
test { useJUnitPlatform(); testLogging { showStandardStreams true; } }
并且要让异常控制台打印输出,像这种方式,log4j2配置没法起效果,
try{ ... ... } catch (Exception e) { e.printStackTrace(); throw e; }
这个感觉还可以改进,不知网友们有什么好的办法?
编译的时候,有时候会遇到以下的告警:
警告: HotspotThreadMBean是内部专用 API, 可能会在未来发行版中删除 import sun.management.HotspotThreadMBean
如果想要屏蔽,只要在build.gradle里添加
compileJava { options.compilerArgs << '-XDignore.symbol.file' options.fork = true options.forkOptions.executable = 'javac' }
遇到如下异常:
Cannot change dependencies of dependency configuration ':implementation' after it has been included in dependency resolution.
可能你把jar节点放在了repositories 和dependencies之间,试着把jar节点移动到dependencies下面
如何将maven项目改造成gradle项目
Gradle官方非常贴心的内置了插件,可以一键将Maven POM转换为Gradle配置。只需要在项目目录内执行:
gradle init
然后,按照提示,将该Maven项目转换为一个Gradle项目即可。Gradle会自动为我们生成根项目的build.gradle、settings.gradle和gradle wrapper文件夹,当然,还有每个子项目的build.gradle文件(太强大了,笔芯Gradle♥️)
然鹅,光是这样当然是不够的,自动生成的Gradle配置是无法通过编译的...我们还需要继续按照原有的编译配置继续调整Gradle配置文件。
---------------------------------
如何在命令行运行gradle指定 JDK 版本?
可以在项目的根目录下创建文件 gradle.properties,里面设置JDK目录:
org.gradle.java.home=D:\\Program Files\\Java\\TencentKona-11.0.16.b2
环境变量设置:
task bootRunProd { dependsOn 'clean' group = "application" description = "Runs the Spring Boot application with the prod profile" doFirst { tasks.bootRun.configure { System.setProperty("spring.active", "prod"); System.setProperty("config.server-addr", "215.159.87.608:8848"); System.setProperty("config.namespace", "public"); System.setProperty("config.group", "DEFAULT_GROUP"); System.setProperty("discovery.server-addr", "215.159.87.608:8848"); System.setProperty("sentinel.port", "8719"); System.setProperty("sentinel.dashboard", "127.0.0.1:8088"); } } finalizedBy("bootRun") } task bootRunDev { dependsOn 'clean' group = "application" description = "Runs the Spring Boot application with the dev profile" doFirst { tasks.bootRun.configure { System.setProperty("spring.active", "dev") System.setProperty("config.server-addr", "215.159.87.608:8848"); System.setProperty("config.namespace", "public"); System.setProperty("config.group", "DEFAULT_GROUP"); System.setProperty("discovery.server-addr", "215.159.87.608:8848"); System.setProperty("sentinel.port", "8719"); System.setProperty("sentinel.dashboard", "127.0.0.1:8088"); } } finalizedBy("bootRun") }
如果想在执行错误后还能继续执行其他任务,就加 --continue
gradle publish --continue
查找JAR包的依赖关系,到底是哪个第三方包引入的某个包:
gradle gamioo-config:dependencies +--- com.alibaba.nacos:nacos-client:2.2.1-RC | +--- com.alibaba.nacos:nacos-auth-plugin:2.2.1-RC | +--- com.alibaba.nacos:nacos-encryption-plugin:2.2.1-RC | +--- commons-codec:commons-codec:1.15 | +--- com.fasterxml.jackson.core:jackson-core:2.12.6 -> 2.12.7 | | \--- com.fasterxml.jackson:jackson-bom:2.12.7 | | +--- com.fasterxml.jackson.core:jackson-annotations:2.12.7 (c) | | +--- com.fasterxml.jackson.core:jackson-core:2.12.7 (c) | | \--- com.fasterxml.jackson.core:jackson-databind:2.12.7 -> 2.12.7.1 (c) | +--- com.fasterxml.jackson.core:jackson-databind:2.12.7.1 | | +--- com.fasterxml.jackson.core:jackson-annotations:2.12.7 | | | \--- com.fasterxml.jackson:jackson-bom:2.12.7 (*) | | +--- com.fasterxml.jackson.core:jackson-core:2.12.7 (*) | | \--- com.fasterxml.jackson:jackson-bom:2.12.7 (*) | +--- org.apache.httpcomponents:httpasyncclient:4.1.3 | | +--- org.apache.httpcomponents:httpcore:4.4.6 -> 4.4.16 | | +--- org.apache.httpcomponents:httpcore-nio:4.4.6 | | | \--- org.apache.httpcomponents:httpcore:4.4.6 -> 4.4.16 | | +--- org.apache.httpcomponents:httpclient:4.5.3 -> 4.5.14 (*) | | \--- commons-logging:commons-logging:1.2 | +--- io.prometheus:simpleclient:0.12.0 | | +--- io.prometheus:simpleclient_tracer_otel:0.12.0 | | | \--- io.prometheus:simpleclient_tracer_common:0.12.0 | | \--- io.prometheus:simpleclient_tracer_otel_agent:0.12.0 | | \--- io.prometheus:simpleclient_tracer_common:0.12.0 | \--- org.yaml:snakeyaml:1.32 -> 2.0 \--- org.yaml:snakeyaml:2.0
Q1:如何重新加载依赖包,有可能同一版本维护人员刚在仓库更新过?
gradle clean build --refresh-dependencies