Maven vs. Gradle
There are three main building tools in the Java World: Ant, maven, and Gradle. After several years of development, Ant almost disappeared, Maven also died, and Gradle's development is at the zenith. I was fortunate to witness the decline of MAVEN and the rise of Gradle. The main functions of Maven are divided into 5 points, which are dependent management system, multi-module construction, consistent project structure, consistent building model and plug-in mechanism. We can analyze the five aspects of Gradle compared to Maven's advanced point.
Dependency Management System
Maven introduced a new dependency management system for the Java world. In the Java world, a dependency can be uniquely identified by a coordination (coordinate) consisting of GroupID, Artifactid, and version. Any maven-built project itself must also define these three properties, and the resulting package can be either a jar package or a war package or an ear package. A typical dependency reference is as follows:
123456789 |
<dependency> <groupid>junit</groupid> <artifactid> Junit</artifactid> <version>4.12 </version> <scope>test</ Scope></dependency>< Dependency> <groupid>org.springframework</ Groupid> <artifactid>spring-test</artifactid ></DEPENDENCY>
|
It can be seen from the above that when a dependency is referenced, version can be omitted so that the latest version is selected when the dependency is obtained. The warehouses that store these components have remote warehouses and local warehouses. The remote repository can use the world's public central repository, or it can use the Apache Nexus to build a private repository, while the local repository is on the local computer. The path to the local repository and the address of the remote warehouse being used can be configured through the settings.xml file in the MAVEN installation directory.
Gradle in the design of the basic use of MAVEN's this set of dependency management system. However, it has made some improvements when it comes to referencing dependencies. The first reference to dependency has become very concise.
1234 |
dependencies { compile ' org.hibernate:hibernate-core:3.6.7.final ' testcompile ' junit:junit: 4.+ "} |
Second, MAVEN and gradle differ in scope for dependencies. In the Maven world, there are 6 scopes for a dependency, namely Complie (default), provided, runtime, test, System, import. and grade to simplify it for 4 kinds, compile, runtime, Testcompile, Testruntime. So what if you want to use a scope similar to provided in Gradle? Don't worry, thanks to the powerful expressiveness of the Gradle language, we can easily write code to implement a concept similar to provided scope (such as how to use the provided scope for JAR file in Gradle build?).
The 3rd is that Gradle supports dynamic version dependencies. Dynamic versioning can be achieved by using the + sign after the version number.
4th, the implementation mechanism of Gradle in the settlement of conflict-dependent conflicts is more explicit. Dependency management using MAVEN and Gradle is a transitive dependency, and a dependency conflict can occur if multiple dependencies point to different versions of the same dependency. Maven's handling of this dependency is usually a nightmare. And Gradle is relatively clear in resolving the conflict of dependence. In Chapter 23. The 23.2.3 section in Dependency Management explains in detail how Gradle handles version conflicts.
Multi-Module construction
In the wave of SOA and microservices, splitting a project into multiple modules is already a common approach. In Maven, you need to define a parent pom as an aggregate pom for a set of module. Labels can be used in this pom <modules>
to define a set of sub-modules. The parent Pom does not have any actual build output. The build configuration and dependency configuration in the parent Pom are automatically inherited to the child module.
Gradle also supports multi-module construction. In the parent's build.gradle, you can use allprojects and subprojects code blocks to define, respectively, whether the configuration is applied to all projects or sub-projects. The definition of a submodule is placed in the Setttings.gradle file. In the design of Gradle, each module is an object instance of project. In the parent build.gradle, these objects can be manipulated in various ways by allprojects or subprojects. This is undoubtedly more flexible than Maven.
For example, in the parent's build.gradle, there is the following code:
123 |
allprojects { task hello << { task -> println "I‘m $task.project.name" }}
|
The Execute command gradle -q hello
prints out the parent module and the project name of each submodule in turn. This powerful capability allows the Gradle to be more customized for each module.
Consistent project Structure
When you create a Java project directory in the Ant age, you are more casual, and then you specify which of the source, which belongs to Testsource, through the ant configuration. The idea of Maven at the beginning of the design is conversion over configuration (the contract is larger than the config). It developed a set of project directory structures as standard Java project structure. A typical MAVEN project structure is as follows:
Gradle also follows this standard directory structure. If you are using the standard MAVEN project structure in the Gradle project, you do not need to make redundant configuration in the Gradle, just include in the file apply plugin:‘java‘
, the system will automatically recognize the source, resource, test srouce, test Resource and other corresponding resources. However, as a build tool on the JVM, Gradle also supports the building of source code such as groovy and Scala, and even supports a hybrid build of Java, groovy, and Scala languages. Although Maven can achieve the same goal through some plugins (such as Maven-scala-plugin), the configuration aspect is obviously gradle to be more elegant.
A consistent build model
To address the lack of standardization of project building activities in Ant, Maven has deliberately set up a standard project build cycle with the default build cycle as follows:
123456789-ten-19 from |
<phases> <phase>validate</phase> <phase>initialize</phase> <phase>generate-sources</phase> <phase>process-sources</phase> <phase>generate-resources</phase> <phase>process-resources</phase> <phase>compile</phase> <phase>process-classes</phase> <phase>generate-test-sources</phase> <phase>process-test-sources</phase> <phase>generate-test-resources</phase> <phase>process-test-resources</phase> <phase>test-compile</phase> <phase>process-test-classes</phase> <phase>test</phase> <phase>prepare-package</phase> <phase>package</phase> Span class= "NT" ><phase>pre-integration-test</phase> <phase>integration-test</phase> <phase>post-integration-test</phase> <phase>verify</phase> < Phase>install</phase> <phase>deploy </phase></PHASES>
|
And this build cycle is the place where Maven is most criticized. Because MAVEN limits the project's build cycle too much, you can't add new phase to the build cycle, only bind the plug-in to an existing phase. Now that the construction of the project is becoming more complex and diversified, it is clear that Maven lacks sufficient resilience to this complexity. For example, if you want to do a task of compressing all JavaScript during the project build, then bind to one of MAVEN's existing phase, which is obviously not the right phase. And these phase are serial, and the entire execution is a line, which limits Maven's build efficiency. And Gradle is very flexible in building models. In the Gradle world, you can easily create a task and, at any time, depends
establish a dependency on an existing task through syntax. Even for a Java project to build, Gradle is a java
plug-in that contains a build cycle for a Java project, which equals that the gradle itself is decoupled directly from the project build cycle.
Plug-in mechanism
Both Maven and Gradle are designed with a plug-in mechanism. But obviously Gradle is better. The main reason is that MAVEN is configured based on XML. So its configuration syntax is too limited by XML. Even small functionality requires designing a plug-in that is associated with the XML configuration. For example, to execute a shell command in Maven, it is configured as follows:
123456789-ten-19 the |
<plugin> <groupid>org.codehaus.mojo</groupId> <artifactid>exec-maven-plugin</artifactId> <version>1.2</version> <executions> <execution> <id>drop DB = db_name</id> <phase>pre-integration-test</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>curl</executable> <arguments> <argument>-s</ Argument> <argument>-s</argument> <argument>-x</argument> Span class= "NT" ><argument>delete</argument> <argument>http://${db.server}:${db.port}/db_name</argument> Span class= "NT" ></arguments> </configuration> </execution> </executions>< Span class= "NT" ></PLUGIN>
|
And in the gradle, everything becomes very simple.
123 |
task dropdb (type: exec { CommandLine ' curl ' , ' -s ' , ' s ' , ' -x Span class= "o" >, ' delete ' , ' Http://${db.server}:{db.port}/db_name "}
|
In terms of creating custom plug-ins, both Maven and Gradle have similar mechanisms, all inheriting from the plug-in base class and then implementing the required method. The description is not unfolded here.
The main differences between MAVEN and Gradle can be seen from the above five aspects. MAVEN's design core Convention Over Configuration
is Gradle more, and Gradle is 配置即代码
beyond maven. Any configuration in Gradle can be executed as code, and we can always use an existing ant script (ant task is a one-time citizen in Gradle), Java class Library, groovy class library to assist in the writing of the build task.
The example of a DSL that uses its own language to build and manage its own language projects is ubiquitous. such as Rake and Ruby, Grunt and JavaScript, SBT, and Ruby ... while Gradle uses the groovy language, it is because groovy is more expressive than the Java language, with more grammatical features and functional features. Languages that have risen over the years (such as Scala, Go, Swift) are strongly-typed languages, with both object-oriented and functional features.
The last Gradle command line is much more powerful than Maven's. Previously wrote an article dedicated to Gradle command-line operations, see Gradle command line black magic for details.
Maven and Gradle