Java build tools: Maven vs. Gradle

In the world of Java programmers, build tools have always been an indispensable element. In the beginning, there was only one build tool in the world, which was Make, which later developed into GNU Make. However, due to the continuous emergence of demand, other strange construction tools have gradually emerged in this small circle.

The most influential character in this small circle is Maven. It uses XML as the configuration file, which improves the complex build configuration of its predecessor Ant and provides some ready-made targets without requiring us to list each command of the build task one by one. In addition, it provides a killer feature, which is dependency management. It can automatically download the dependencies required for the project from the network through simple configuration, which has revolutionized the way we develop software. You can imagine that if you are a member of a large software development project team, using a code warehouse to manage dependent jar packages will make the warehouse huge! Maven's product warehouse design realizes the decoupling between products and code, providing the possibility for product-based collaboration.

However, the speed of the replacement of old and new in the software industry is often staggering. It doesn't take long for you to find that the once popular technology has become a thing of the past. In the field of Java construction, we can see some emerging tools emerging. For example, Gradle based on Groovy. Hibernate migrated its project from Maven to Gradle, and Android Studio, Google's official Android development IDE, also uses Gradle for building by default. These events have attracted a lot of attention to Gradle. Is Gradle really going to replace Maven? Of course not, Maven is still the de facto standard for Java build technology today. Gradle also still uses Maven's artifact library for dependency management. But from Gradle, we do see progress. The concise Groovy syntax and flexible configuration make our eyes shine.

So what is the difference between Maven and Gradle? I invite readers to explore with me.

Installation
: Both are similar in terms of installation. We all need to download and extract it from the official website to a local directory. Configure the MAVEN_HOME or Gradle_Home environment variable and add it to the PATH environment variable. We can use maven and gradle from the command line.

Mainstream Java IDE: Eclipse can install Maven and Gradle plug-ins. Intellij has built-in Gradle and Maven for use.

Both have detailed documentation for user reference. Even though gradle is a newcomer, its documentation also has 70 chapters and more than 500 pages of content!

Attached here are the download addresses for Maven and Gradle:

maven: Maven – Welcome to Apache Maven
gradle: https://gradle.org
The configuration file for dependency management
Maven is a .pom file. POM is the abbreviation of Project Object Model. It is a file in the Maven project and is represented by XML. It contains basic information of the project, construction process, environment information, dependency information, etc. We can look at the following simple example:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.vs</groupId>
    <artifactId>com.vs.maven.gradle</artifactId>
    <version>1.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa
            </artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

This example builds a simple spring-boot project and initially defines some basic information about the project, including group name, product name, version, etc. The parent tag indicates that we inherit the configuration of a product defined by spring, so that we can introduce dependencies without configuring many dependent versions. Configure other artifacts that the project depends on between the dependencies tags, and configure the groupId, artifactId and version of each dependent artifact respectively. When we execute mvn insall, maven will automatically download the dependency and help us compile and package it into the local warehouse. We can find our products in the .m2 folder in the user directory.

So if we use Gradle to build this project, how should we do it?

buildscript {
    
    
    repositories {
    
    
        mavenCentral()
    }
    dependencies {
    
    
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.6.RELEASE")
    }
}
dependencies {
    
    
    compile("org.springframework.boot:spring-boot-starter-web") {
    
    
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    testCompile("mysql:mysql-connector-java:5.1.25")
}

Huh? Why is there so much less lengthy code all of a sudden? ^?

If you read it carefully, you will find that it turns out that the configuration length required for dependency management has become shorter. In pom.xml, when we need to introduce a dependency, we need to quote its groupId, artifactId and version with tags. But in build.gradle, you will find that you only need to connect the three values ​​​​with: and "call the compile function".

For example, if we want to reference spring-boot's starter-security, the maven configuration is written like this:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
</dependencies>

The configuration in gradle is like this:

dependencies {
    
    
    compile("org.springframework.boot:spring-boot-starter-security")
}

how do you feel? Anyway, I feel as refreshed as writing code! Gradle uses groovy as its DSL, which is very easy to use. If you have used Maven for a long time, you may find that Gradle configuration is so fun to write!

Build Lifecycle Management
In addition to dependency management, another major use of build tools is build lifecycle management.

Maven has three life cycles, and each life cycle is divided into multiple stages:

Clean: Contains 3 stages, related to cleaning the files generated by the last build.
Default: Maven's core life cycle, including multiple stages such as preprocessing, compilation, testing, packaging, installation to local warehouse, publishing to remote warehouse, etc.
Site: Contains 4 stages, related to generating project reports, sites, and publishing sites.
These life cycles are customized by the system. If we need to modify the existing build life cycle, we have to write a Maven plug-in. Because Maven completes most of the build tasks through plug-ins. Each plug-in can be bound to a life cycle. After configuring the binding life cycle, we need to define the tasks of the plug-in. In Maven, the goal of each task is called Mojo. For each Mojo, we need to implement the org.apache.maven.plugin.Mojo interface. That is, we need to define a class to implement this interface. When using it, we need to introduce this plug-in and configure the goals that need to be executed.

For example, if we want to complete the requirement of outputting Hello world, we need:

Create a new GreeingMojo class:

package sample.plugin;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;

/**
 * Says "Hi" to the user.
 *
 */
@Mojo( name = "sayhi")
public class GreetingMojo extends AbstractMojo
{
    
    
    public void execute() throws MojoExecutionException
    {
    
    
        getLog().info( "Hello, world." );
    }
}

Define pom file:

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>sample.plugin</groupId>
  <artifactId>hello-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>maven-plugin</packaging>

  <name>Sample Parameter-less Maven Plugin</name>

  <dependencies>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-plugin-api</artifactId>
      <version>2.0</version>
    </dependency>

    <!-- dependencies to annotations -->
    <dependency>
      <groupId>org.apache.maven.plugin-tools</groupId>
      <artifactId>maven-plugin-annotations</artifactId>
      <version>3.4</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

Run the install command in the project pom file directory to install the plug-in into the local warehouse.
Add configuration to the project using the plug-in:

 <build>
    <plugins>
      <plugin>
        <groupId>sample.plugin</groupId>
        <artifactId>hello-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
      </plugin>
    </plugins>
  </build>

implement:

mvn groupId:artifactId:version:goal

This completes the output of Hello and world.

So how do we do it in Gradle? There is a basic concept in Gradle called Task. We can use Task to complete this requirement:

task hello << {
    
    
    println "hello world"
}

Execute Gradle hello to complete the output of Hello, World. Is not it simple? Just like writing code~

Of course, the construction tasks we have to complete in actual projects are not just as simple as outputting an info. We are likely to do some other complex operations, such as initializing files, databases, detecting system environments, etc. However, since Gradle uses Groovy as the configuration file, it is much more flexible than Maven's xml configuration when used, and is more suitable for us coders to use.

Product Release
In terms of product release, Maven has to make a comeback. Maven natively supports the maven jar format, and publishing is very simple; while Gradle supports both Maven and Gradle, it requires us to do a lot of extra work ourselves. For example, if Maven wants to publish a product, it only needs to configure the parameters of the remote warehouse:

  <distributionManagement>
    <repository>
      <id>internal</id>
      <name>Internal Release Repository</name>
      <url>http://repository.springsource.com/maven/bundles/release</url>
    </repository>
  </distributionManagement>

When gradle publishes products, it also needs to generate a pom file:

uploadArchives {
    
    
    repositories {
    
    
        mavenDeployer {
    
    
            //为Pom文件做数字签名
            beforeDeployment {
    
     MavenDeployment deployment -> signing.signPom(deployment) }

            repository(url: "http://repository.springsource.com/maven/bundles/release") {
    
    
                authentication(userName: username, password: password)
            }
            //构造项目的Pom文件
            pom.project {
    
    
                name project.name
                packaging 'jar'
                description 'description'

            }
        }
    }
}

Summary:
Due to time constraints, I have briefly introduced so much. Maybe readers also have some understanding of the differences between Gradle and Maven. Gradle is more flexible and simpler than Maven. But is Maven's inflexibility compared to Gradle also its advantage? This requires readers to think about it themselves during the project.

In addition, the official website of Gradle has a special column to talk about the difference between Gradle and Maven: Maven vs Gradle: Feature Comparison.

Patient readers can take a look at these comparisons. If you want to say that I don't have the patience to read this, I just want to quickly pick a construction job and start my project! So what I want to say is: Just have a try! Maven and Gradle are both very good build tools, and it is not a bad thing to increase your experience in using them. Of course, if you want to develop Android applications, it is recommended that you use Gradle as the build tool, because the Android Studio officially promoted by Google uses Gradle as the native build tool, which makes Gradle better support the construction of various versions of Android software. For other projects, choose one of the two~

Guess you like

Origin blog.csdn.net/lqzixi/article/details/132558442