[Gradle tutorial] getting started with Gradle

This article is the address of the live room where I share the documents in the learning group in station B http://live.bilibili.com/22263819

PS: ask me, is there any good conference software under Linux? Thank you for your comments

00. Introduction

Gradle is an open source automation construction tool, which supports multi language environment. Influenced by Ant and Maven's ideas, it integrates the two. Compared with Ant's non-standard, Maven's configuration is complex and life cycle is severely limited. Gradle is both standard and more flexible. It can use DSL (domain specific language, such as Groovy or Kotlin) to write construction scripts, which are shorter and more concise

Its features are:

  • Highly customized: modular, scalable and more flexible
  • Rapid construction: support parallel construction, and automatically reuse the results of previous task construction to improve efficiency
  • Powerful function: support multi language environment, including the construction of Java, Android, C + +, Groovy, Javascript and other projects

Ant and Maven have Gradle, but they don't necessarily have Gradle;

Ant, Maven can do it, Gradle can do it, and do it better

01. Installation

Installation process of Gradle binary package:

  • Make sure the JDK is installed correctly
  • Download the latest version of Gradle https://gradle.org/releases/
  • Extract to the specified directory
  • Set path
  • Gradle-v test

Take Linux for example:

cd /opt
wget https://services.gradle.org/distributions/gradle-6.4.1-bin.zip
sudo unzip -oq gradle-6.4.1-bin.zip #Unzip to / opt/gradle-6.4.1
#Switch root permission and set environment variable
sudo su -
cat >> /etc/profile <<EOF
export PATH=\$PATH:/opt/gradle-6.4.1/bin
export GRADLE_USER_HOME=/opt/gradle-6.4.1 #The cache of Gradle will exist in the caches in this directory
EOF
exit
source /etc/profile

#test
hellxz@debian:~$ gradle -v

------------------------------------------------------------
Gradle 6.4.1
------------------------------------------------------------

Build time:   2020-05-15 19:43:40 UTC
Revision:     1a04183c502614b5c80e33d603074e0b4a2777c5

Kotlin:       1.3.71
Groovy:       2.5.10
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.7 (Debian 11.0.7+10-post-Debian-3deb10u1)
OS:           Linux 4.19.0-9-amd64 amd64

02.Hello World

build.gradle

task hello {
    println 'Hello world!'
}
gradle -q hello

-q is used for silent output, making the output clearer

What's going on here? This build script defines a separate task, called hello, and adds an action. When you run gradle hello, Gradle executes a task called hello, that is, the action you provide. This action is a closure that contains some Groovy code

Extended reading:

In the task block, you can define the methods (closures) doFirst and doLast for pre and post execution, which can be understood literally. However, it should be noted that defining multiple doLast or doFirst cannot guarantee the execution order

03. Building the foundation

projects and tasks

projects and tasks are the two most important concepts in Gradle.

Any Gradle build consists of one or more projects. Each project may be a jar package or a web application, or it may be a zip package composed of jars generated in many other projects.

Each project consists of multiple tasks. Each task represents an atomic operation in the build execution process. Such as compiling, packaging, generating javadoc, publishing to a warehouse and other operations.

In short, project is a module of a construction project, and task is an operation of one module

Call Groovy

At build.gradle (it can be called build script, build configuration script) can call Groovy's class library (including Java class library). The following is an example:

build.gradle

task upper {
  String str = 'this is a simple test'
  println "Original value:" + str
  println "After capitalization:" + str.toUpperCase()
}

Execute the command gradle -q upper

In this example, THIS IS A SIMPLE TEST is simply converted to THIS IS A SIMPLE TEST, in which the toUpperCase() method of String is used

Groovy is compatible with Java syntax. We can do the desired operation by calling Groovy or Java in task.

Define project version/group

In maven, you can clearly define the project version, which will be included in the file names of war or jar products when you build it. When you push it to Maven private server, you need to set the group artifactId version information, so how to define it in Gradle?

In Gradle, the three parameters corresponding to Maven change the artifactId to rootProject.name , only group and version need to be defined additionally

At build.gradle Setting in

version = "0.0.1"
group = "com.cnblogs.hellxz"

There is also a special configuration file in the Gradle configuration, gradle.properties , we can configure variables in the build.gradle read

version=0.0.1
group=com.cnblogs.hellxz

04. Getting started with Java building

Generate Java project

When using Maven, we can create a simple Java project with the following command

mvn archetype:generate -DgroupId=xxx -DartifactId=yyy -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeCatalog=local -DinteractiveMode=false

Some of Maven's gradles will not fall naturally. We can use init task to initialize a Java project

$ gradle init
> Task :wrapper

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Swift
Enter selection (default: Java) [1..5] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit 4) [1..4]

Project name (default: demo):

Source package (default: demo):


> Task :init
Get more help with your project: https://docs.gradle.org/5.4.1/userguide/tutorial_java_projects.html

BUILD SUCCESSFUL
2 actionable tasks: 2 executed

The structure of the generated code is as follows:

When init task is executed, wrapper task is called first to generate gradlew gradlew.bat And the code structure required for the new project

Read the document https://guides.gradle.org/building-java-applications/

Plug in: war

  • Role: print the current project as a war package
  • use:
    1. build.gradle Add apply plugin: 'war' in or add id: 'war' in plugins block
    2. gradle build, generate war to the root build/libs of the current project directory

Generate the SpringBoot2 project

Take you to read and Practice https://guides.gradle.org/building-spring-boot-2-projects-with-gradle/

Due to the domestic network problems, the domestic source and plug-in source need to be configured. Here, the main part of my test is put out

The project structure is the same as in the official documents

gradle.spring.boot Under the. Project package APP.java :

/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package gradle.spring.boot.project;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class App extends SpringBootServletInitializer {

    @GetMapping("/greet")
    public String getGreeting() {
        return "Hello world.";
    }

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return super.configure(builder);
    }
}

build.gradle :

plugins {
    id 'java'
    id 'application'
    id 'org.springframework.boot' version '2.0.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'war'
}

repositories {
    maven { url 'https://maven.aliyun.com/repository/public/' }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedCompile 'org.springframework.boot:spring-boot-starter-tomcat'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    components {
        withModule('org.springframework:spring-beans') {
            allVariants {
                withDependencyConstraints {
                    // Need to patch constraints because snakeyaml is an optional dependency
                    it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } }
                }
            }
        }
    }
}
application {
    mainClassName = 'gradle.spring.boot.project.App'
}

settings.gradle :

pluginManagement {
    resolutionStrategy {
    }
    repositories {
        maven { url "http://maven.aliyun.com/nexus/content/groups/public" }
        gradlePluginPortal()
    }
}

rootProject.name = 'gradle-spring-boot-project'

Make the SpringBoot project a war package

  • Step:

    • Add war plug-in

    • Execute gradle build or gradle bootwar (many operations will be performed for build, only war package will be printed after booWar compilation)

      • Package out war (embedded tomcat) that can be started directly

      • Mask tomcat dependency, inherit SpringBootServletInitializer, override configure method

        build.gradle

        dependencies{
        	providedCompile 'org.springframework.boot:spring-boot-starter-tomcat'
        }
        

        App.java

        @SpringBootApplication
        public class App extends SpringBootServletInitializer{
        	public static void main(String[] args){
            	SpringApplication.run(App.class, args);
            }
            protected SpringApplicationBuilder configure(SpringApplicationBuilder app){
            	return app.sources(App.class)
            }
        }
        

        gradle build Executed task A lot, put the output down here

        4 pm:26:33: Executing task 'build'...
        
        > Task :compileJava
        > Task :processResources NO-SOURCE
        > Task :classes
        > Task :bootWar
        > Task :bootStartScripts
        > Task :bootDistTar
        > Task :bootDistZip
        > Task :jar SKIPPED
        > Task :startScripts
        > Task :distTar
        > Task :distZip
        > Task :war SKIPPED
        > Task :assemble
        > Task :compileTestJava
        > Task :processTestResources NO-SOURCE
        > Task :testClasses
        > Task :test
        > Task :check
        > Task :build
        
        Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
        Use '--warning-mode all' to show the individual deprecation warnings.
        See https://docs.gradle.org/6.4.1/userguide/command_line_interface.html#sec:command_line_warnings
        
        BUILD SUCCESSFUL in 2s
        10 actionable tasks: 10 executed
        //4:26:35 PM: task execution finished 'build'
        

tasks provided by SpringBoot

  • bootWar: compile and print the war package (the task depends on the war plug-in). Internally, call classes first, and then call itself. There are two tasks

    4 pm:14:07: Executing task 'bootWar'...
    
    > Task :compileJava
    > Task :processResources NO-SOURCE
    > Task :classes
    > Task :bootWar
    
    BUILD SUCCESSFUL in 510ms
    2 actionable tasks: 2 executed
    //4:14:08 PM: task execution finished 'bootwar'
    
  • bootJar: compile and print into jar package. Internally, call classes first, then call itself. There are two task s

    4 pm:15:31: Executing task 'bootJar'...
    
    > Task :compileJava
    > Task :processResources NO-SOURCE
    > Task :classes
    > Task :bootJar
    
    BUILD SUCCESSFUL in 488ms
    2 actionable tasks: 2 executed
    //4:15:32 PM: task execution finished 'bootjar'
    

05. Dependency management

Import dependency

  • Compile: Download and compile from the warehouse, support dependency delivery

  • api: new syntax, equivalent to compile

  • implementation: compared with api, new syntax does not support passing dependency and reduces the efficiency of circular compilation and optimization

    The dependency of compile/api/implementation import is provided by both compile time and run time (into the product)

Extended reading:

implementation scope

Access isolation for implementation works only at compile time.

What do you mean? If lib C depends on lib a version 2.0, lib B implementation depends on lib a version 1.0:

At compile time, libC can access version 2.0 libA, and libB can access version 1.0 libA.

But in the end, version 2.0 (visible through the dependency tree) hit war.

At runtime, both lib B and lib C can access version 2.0 of lib A (only Lib in war can be used)

What are the characteristics of implementation?

For a dependency compiled with this command, any program in the dependency compiled with this command will not be accessible to the project that depends on this command, that is, the dependency will be hidden inside and not exposed outside

What are the benefits of using implementation?

If there are many cascading engineering dependencies in the project, for example, the dependency of lib A B C in the figure above is engineering dependency. If the dependency method used is compile/api, when the libA interface is modified and recompiled, libA B C will be recompiled (even if the modified libA interface is not used in libc). If implementation dependency is used, LIBS that are not directly related will not be recompiled because of compile time isolation.

If the projects are all dependent on aar, the advantage of reducing compilation time is lost (because aar is already compiled bytecode). So what's the use? Take the picture above as an example. Before, we all relied on compile. If lib A already depends on lib B, then in libC build.gradle There is no need to write the dependency of lib A in. But there are problems:

I'm from lib C build.gradle In the dependency list of, we can't fully know which LIBS libC needs to rely on.
Assuming such a situation, I know that the maximum version of libA relied on in the project is 2.0, so the app runtime is the 2.0 version of libA used. At this time, I need to call a aar of libC. If lib C is passed through compile, it depends on libA, so it can be transferred from the build.gradle We do not know which version of lib A lib C depends on when compiling. If libC still relies on libA 1.0 when it hits aar (compile), there may be a problem with this aar.

Shield dependency

  • providedCompile: compile time participates in compilation and runtime does not provide it (but in the generated war package, these dependencies will be incorporated into WEB-INF / lib provided)
  • Provided Runtime: it does not participate in compilation, but is required by the runtime, such as mysql driver package. If this dependency is used in the code, compilation fails

Test period dependence

  • testCompile: compile during test, not during non test
  • testImplementation: same as implementation, only for test cycle

Exclude dependency

  • Exclude: exclude the module of the specified group module

    • Mask when dependency is introduced

      dependencies {
          compile ('org.springframework.boot:spring-boot-starter-web'){
            exclude group:'org.springframework.boot',module:'spring-boot-starter-logging'
          }
      }
      
    • Global shielding

      configurations.all {
      	exclude group:'org.springframework.boot', module:'spring-boot-starter-logging'
      }
      

      or

      configurations {
       all*.exclude group:'org.springframework.boot',module:'spring-boot-starter-logging'
      }
      

Dependency management

  • Dependency management: unified multi module dependency version

    • You can define the dependencies block in it and specify the dependent version

      dependencyManagement {
          dependencies {
              api 'mysql:mysql-connector-java:5.1.39'
          }
      }
      
    • BOM can be introduced, similar to Maven's parent

      dependencyManagement {
          imports {
              mavenBom 'io.spring.platform:platform-bom:1.1.1.RELEASE'
          }
      }
      

06. More

Refer to official documents:

07. Citations

Tags: Gradle Spring Maven Java

Posted on Sat, 30 May 2020 22:53:43 -0400 by DrJonesAC2