大家好,一别就是好久啊,我亲爱的博客。今天就介绍这个命令背后的逻辑和应用场景。
- 一、背景
- 二、实践
- 三、应用场景
一、背景
这里假设你已经对Gradle项目及基本命令、对Task有一定了解。这里主要介绍
gradle -x test clean build的作用。
二、实践
gradle -x test ——表明在打包的时候(把通用的类打成jar包供其他服务调用),排除名称为test的Task。
clean build ——这个当然指Task名称。不过项目中并未发现定义这些Task的地方,会在哪里?请继续往下看:
Gradle核心的文件:
1、build.gradle(项目自带)
2、settings.gradle项目自带)
3、gradle.proerties(根据实际情况自行添加)
你在网上看了零碎的信息后,我们可以按照这个方式系统的看一看,前提是:已经安装gralde ,检验是否安装:gradle --version
zjdeMacBook-Air:gradleTest03 dzj$ gradle --version
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Build time: 2017-04-10 13:37:25 UTC
Revision: b762622a185d59ce0cfc9cbc6ab5dd22469e18a6
Groovy: 2.4.10
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_161 (Oracle Corporation 25.161-b12)
OS: Mac OS X 10.13.3 x86_64
==》 本地 mkdir gradleTest03,在此目录对gradle -x test clean build做实验。
build.gradle里面做了什么?这里面会指定引用插件(即引用插件已有的Task)、分组、指定sourceSets、指定repositories、自定义Task、指定publishing
.settting.gradle干嘛的?指定项目中哪些部分需要打包
gradle.properties,存放一些变量。
好,知道这些足够了,下面就实践 。每个详细作用,后面会专门博客做讲解,今天主要是了解透彻:gradle -x test clean build
在新建的目录gradleTest03中检验是否安装好gradle,方法有2种:
法1:
dzjdeMacBook-Air:gradleTest02 dzj$ gradle --version
------------------------------------------------------------
Gradle 3.5
------------------------------------------------------------
Build time: 2017-04-10 13:37:25 UTC
Revision: b762622a185d59ce0cfc9cbc6ab5dd22469e18a6
Groovy: 2.4.10
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_161 (Oracle Corporation 25.161-b12)
OS: Mac OS X 10.13.3 x86_64
法2:
dzjdeMacBook-Air:gradleTest02 dzj$ gradle
:help
Welcome to Gradle 3.5.
To run a build, run gradle <task> ...
To see a list of available tasks, run gradle tasks
To see a list of command-line options, run gradle --help
To see more detail about a task, run gradle help --task <task>
BUILD SUCCESSFUL
Total time: 1.057 secs
法2中可以看到各种命令,我们就围绕这几个看看:
查看所有tasks?
dzjdeMacBook-Air:gradleTest02 dzj$ gradle tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'gradleTest02'.
components - Displays the components produced by root project 'gradleTest02'. [incubating]
dependencies - Displays all dependencies declared in root project 'gradleTest02'.
dependencyInsight - Displays the insight into a specific dependency in root project 'gradleTest02'.
dependentComponents - Displays the dependent components of components in root project 'gradleTest02'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'gradleTest02'. [incubating]
projects - Displays the sub-projects of root project 'gradleTest02'.
properties - Displays the properties of root project 'gradleTest02'.
tasks - Displays the tasks runnable from root project 'gradleTest02'.
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>
BUILD SUCCESSFUL
Total time: 1.145 secs
gradle tasks表示执行一个名为tasks的Task,:tasks表示任务名称。会列出gradle默认的Tasks.
我们分别执行gradle clean 、gradle build看看名称叫做clean 、build的Task背后到底在做什么?
dzjdeMacBook-Air:gradleTest02 dzj$ gradle clean
FAILURE: Build failed with an exception.
* What went wrong:
Task 'clean' not found in root project 'gradleTest02'.
* Try:
Run gradle tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 1.446 secs
可见,默认的clean Task是不存在的。
dzjdeMacBook-Air:gradleTest02 dzj$ gradle build
:buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
BUILD SUCCESSFUL
Total time: 1.098 secs
:buildEnvironment表示的是执行的task,可以通过help中的信息查看具体表示什么:
dzjdeMacBook-Air:gradleTest02 dzj$ gradle help --task build
:help
Detailed task information for build
Path
:buildEnvironment
Type
BuildEnvironmentReportTask (org.gradle.api.tasks.diagnostics.BuildEnvironmentReportTask)
Description
Displays all buildscript dependencies declared in root project 'gradleTest02'.
Group
help
BUILD SUCCESSFUL
Total time: 1.184 secs
很明显:buildEnvironment表示的是Path,我理解的就是taskName.
结论
gradle -x test clean build
这里面的clean并不是gradle在init之后就有的task,而是在
apply plugin: 'java’之后,java插件提供的名为clean的task;而build是gradle init之后默认就有的task。只不过这个task名字叫做: :buildEnvironment,内置的task.
到这里,我们基本明白了一个叫做clean的Task,gradle初始化的时候没有,一定是别处的Task;build有个默认的,不过显然看不出来默认执行了什么,所有也有别处的叫做build的TAsk。
答案:
build.gradle中的这段:
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'maven-publish'
这么引用的话,java插件中自带的task都会出来。后面再详细说,先来了解下gradle的基本目录结构。gradle tasks执行之后,观察下这里:
dzjdeMacBook-Air:gradleTest03 dzj$ gradle tasks
:tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'gradleTest03'.
components - Displays the components produced by root project 'gradleTest03'. [incubating]
dependencies - Displays all dependencies declared in root project 'gradleTest03'.
dependencyInsight - Displays the insight into a specific dependency in root project 'gradleTest03'.
dependentComponents - Displays the dependent components of components in root project 'gradleTest03'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'gradleTest03'. [incubating]
projects - Displays the sub-projects of root project 'gradleTest03'.
properties - Displays the properties of root project 'gradleTest03'.
tasks - Displays the tasks runnable from root project 'gradleTest03'.
init 和 wrapper 2个task .执行后发现目录中初始化了gradle所需要的文件。
dzjdeMacBook-Air:gradleTest02 dzj$ gradle init
:wrapper
:init
BUILD SUCCESSFUL
Total time: 3.713 secs
dzjdeMacBook-Air:gradleTest02 dzj$ ls
build.gradle gradle gradlew gradlew.bat settings.gradle
目录结构:
dzjdeMacBook-Air:gradleTest02 dzj$ tree
.
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
打开看看默认的几个文件,指定了默认的最简洁的配置方式。具体如何配置可以在网上找一个模板看看。
build.gradle
setting.gradle
gradle.properties
到此,我们还是已经知道clean build是apply plugin "java"中自带的Task,如何证明?
很简单,我们在.build.gralde里面增加:apply plugin: ‘java’ 之后,重新执行:
dzjdeMacBook-Air:gradleTest dzj$ gradle build
The Task.leftShift(Closure) method has been deprecated and is scheduled to be removed in Gradle 5.0. Please use Task.doLast(Action) instead.
at build_4smlbhkz6ajzlqndck4jmt9tw.run(/Users/dzj/gradleTest/build.gradle:2)
class org.gradle.api.internal.tasks.DefaultTaskContainer_Decorated
17
:compileJava NO-SOURCE
:processResources NO-SOURCE
:classes UP-TO-DATE
:jar UP-TO-DATE
:assemble UP-TO-DATE
:compileTestJava NO-SOURCE
:processTestResources NO-SOURCE
:testClasses UP-TO-DATE
:test NO-SOURCE
:check UP-TO-DATE
:build UP-TO-DATE
BUILD SUCCESSFUL
Total time: 1.191 secs
结论:这些都是 java plugin中的task,它们之间有明显的依赖关系。
build会去打.jar包,会把哪些打成.jar包?要根据setting.gradle中配置来打包。
好,引申出来setting.gradle
是时候揭露clean build到底做了什么了:
我们来看一下build之后的结果,拿fsc项目举例:
编译时候,首先跳过名称为test的task,然后删除setting.gradle中指定要打包的文件下的build目录=》打包,会在对应指定的需要打包的目录下产生build文件,也就是build之后的结果,看一下build的目录结构
├── build
│ ├── classes
│ │ └── main
│ │ └── com
│ │ └── dzj
│ │ ├── fsc
│ │ │ ├── api
│ │ │ │ ├── command
│ │ │ │ │ ├── BatchBranchCenterDynamicEventCreateCommand.class
│ │ │
│ │ │ │ ├── dto
│ │ │ │ │ ├── BranchCenterDynamicEventDTO.class
│ │ │
│ │ │ │ ├── exception
│ │ │ │ │ └── ErrorCodes.class
│ │ │ │ ├── feed
│ │ │ │ │ ├── dto
│ │ │ │ │ │ └── BranchCenterDynamicEventDTO.class
│ │ │ │ │ └── si
│ │ │ │ │ └── BranchCenterTimelineQueryServiceInterface.class
│ │ │ │ ├── si
│ │ │ │ │ ├── BranchCenterDynamicEventServiceInterface.class
│ │ │ │ │ ├── BranchCenterFollowServiceInterface.class
│ │ │ │ │ ├── UserAttentionRelationInterface.class
│ │ │ │ │ └── UserFollowedDynamicEventServiceInterface.class
│ │ │ │ └── value
│ │ │ │ ├── FollowUserType.class
│ │ │ │ └── UserFollowedOperationType.class
│ │ │ ├── collection
│ │ │ │ └── api
│ │ │ │ ├── command
│ │ │ │
│ │ │ ├── comment
│ │ │ │ └── api
│ │ │ │ ├── command
│ │ │ │ │ ├── CreateCommentCommand.class
│ │ │
│ │ │ └── vote
│ │ │ └── api
│ │ │ ├── command
│ │
│ │ └── influence
│ │ └── api
│ │ ├── command
│ │
│ ├── libs
│ │ ├── feed-service-api-client-1.0-SNAPSHOT-sources.jar
│ │ └── feed-service-api-client-1.0-SNAPSHOT.jar
│ ├── publications
│ │ └── mavenJar
│ │ └── pom-default.xml
│ ├── resources
│ │ └── main
│ │ └── META-INF
│ │ └── exception-config.properties
│ └── tmp
│ ├── compileJava
│ ├── jar
│ │ └── MANIFEST.MF
│ └── sourceJar
│ └── MANIFEST.MF
├── build.gradle
└── src
└── main
├── java
libs下面存放打好的2种.jar包;publications下存放执行Task——publisToMavenLocal 之后产生的pom.default.xml,这个publisToMavenLocal是apply plugin: 'maven-publish’自带的Task,去本地的.m2仓库可以看到gradle已经把本地项目导报后,给.m2仓库放了一份,到时候会把这个推送到远程仓库。
总结:
--------------------------------------------------------------------------------
1、gradle的目录结构
2、build.gradle
这个是整个project的配置文件
1)plugin
2)group
3) sourceSets——默认目录结构
4)ext
5)repositories
6)eclipse ——Eclipse中的问题
7)publishing ——仓库发布位置
3、setting.gradle
这个是指定打包的文件
4、Task
执行顺序和依赖关系
三、应用场景
啰嗦了这么多,有鸟用?当然有用喽,知道了前面的,在解决实际问题时候,才能明白原理。
案例1:
我们在fsc服务里处理了一个SQL错误,然后重新启动了localhost的Tomcat,依旧报错,确定SQL绝对改对了,那么哪里出了问题?
找到问题后,重新部署了fsc,依旧报错,Why?
案例1因为bff里调用的是fsc,调用的是jar包,
/Users/dzj/.m2/repository/com/dzj/feed-service-api-client/1.0-SNAPSHOT/feed-service-api-client-1.0-SNAPSHOT-sources.jar!/com/dzj/fsc/collection/api/si/CollectionServiceInterface.java
所以本地代码更新了,jar包没更新,调用自然是旧的SQL。这个要很清楚。
案例2:
Caused by: com.alibaba.dubbo.remoting.RemotingException: com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote proxy method getByids to registry://172.2181/com.alibaba.dubbo.registry.RegistryService?application=consumer-blob-service&ba
com.alibaba.dubbo.rpc.RpcException: Failed to invoke remote proxy method getByids to registry://17:2181/com.alibaba.dubbo.registry.RegistryService?application=consumer-blob-service&backup=172..8:2181&dubbo=2.8.4.1&export=dubbo%3A%2F%2F172.29.28.9%3A20884%2Fcom.dzj.blob.api
Caused by: com.alibaba.dubbo.common.bytecode.NoSuchMethodException: Not found method "getByids" in class com.dzj.blob.api.si.VideoServiceInterface.
at com.alibaba.dubbo.common.bytecode.Wrapper20.invokeMethod(Wrapper20.java)
at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
... 27 more
bff里面调用了blob中的一个方法,.jar包中getByids(Listids, String … profile),但是blob下面的接口方法是:getByids(Listids),
这里一定要注意根据报错信息,因为方法调用的另一个服务,服务与服务之间是通过.jar包方式调用的,如果没有重新gradle -x test clean build的话,git pull之后的代码虽然是新的,但是jar包还是旧的。
当然还有一种情况:bff里面can’t find symbol,所以自然编译bff的API-client,但是编译过后没效果?因为bff调用的是bdc的接口,所以需要编译bdc,总而言之,这个方法最终从哪来,就依次从底 到 高编译过去即可。
到这里 ,我们对gradle -x test clean build就了解得较为透彻了,后面再实践中灵活运用。
下期再会!