In the previous article, we talked about the basic use of gradle. The ultimate purpose of using gradle is to build Java projects. Today, this article will explain in detail how to build a java project in gradle.
Two plug-ins for building java projects
The purpose of installing a java project is different. There are two plug-ins for building a java project. One is application, which means building a Java application; One is java library, which means that a Java library is built for use by other projects.
Whether building applications or java libraries, we can easily use gradle init to innovate a new gradle project:
$ gradle init 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: Scala 6: Swift Enter selection (default: Java) [1..6] 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): BUILD SUCCESSFUL 2 actionable tasks: 2 executed
The difference between application and library lies in the selection in the second step.
Both are in build The difference in gradle lies in the plugins. The plugins of application are:
plugins { id 'application' }
The library plugin is:
plugins { id 'java-library' }
Another difference is the dependency. First look at the dependency of an application:
dependencies { testImplementation 'junit:junit:4.13' implementation 'com.google.guava:guava:29.0-jre' }
Let's take another look at the dependency of library:
dependencies { testImplementation 'junit:junit:4.13' api 'org.apache.commons:commons-math3:3.6.1' implementation 'com.google.guava:guava:29.0-jre' }
Because the library needs to be used by third-party applications, an api is used here. The api indicates that the third-party applications also need to rely on the package, and the implementation indicates that the package is only dependent within the project.
When building libary, you can also customize the information of manifest:
tasks.named('jar') { manifest { attributes('Implementation-Title': project.name, 'Implementation-Version': project.version) } }
The above example will be in meta-inf / manifest MF generation:
Manifest-Version: 1.0 Implementation-Title: lib Implementation-Version: 0.1.0
We can also specify the compiled java version number and lib version:
java { toolchain { languageVersion = JavaLanguageVersion.of(11) } } version = '1.2.1'
Management dependency
java's dependencies are generally libraries composed of jar packages. Like maven, we need to specify the name and version number of dependencies in gradle. The scope of dependencies: runtime dependency or compile time dependency. Another important thing is where we can find this library.
We can find the first two attributes in dependencies and the last one in repositories. Take an example:
repositories { mavenCentral() } dependencies { implementation 'org.hibernate:hibernate-core:3.6.7.Final' }
You can also use this form of maven:
repositories { maven { url "http://repo.mycompany.com/maven2" } }
Or Ivy:
repositories { ivy { url "http://repo.mycompany.com/repo" } }
You can even use local dir:
repositories { flatDir { dirs 'lib' } flatDir { dirs 'lib1', 'lib2' } }
A maven central repository is defined above. We can find the jar package that hibernate core depends on in this repository.
In the dependencies section, we can define the work scope of the dependent package:
-
compileOnly: it means that the dependent package is only used to compile code, not in the running of the program.
-
implementation: indicates that dependent packages are used at compile and run time.
-
runtimeOnly: used only at run time.
-
testCompileOnly: only used when compiling test.
-
Test implementation: used when compiling and running test.
-
testRuntimeOnly: used when test runs.
We can also add dynamic dependencies:
dependencies { implementation 'org.springframework:spring-web:5.+' }
Use items as dependencies:
dependencies { implementation project(':shared') }
Compile code
Generally, your source code needs to be placed in the src/main/java directory, and the test code needs to be placed under src/test/java. Then add compileOnly or implementation dependencies. If you need to test, add testCompileOnly or testImplementation dependencies.
Then you can run compile Java and compile test Java to compile the code.
Of course, if you have a custom source file directory, you can also specify it manually as follows:
sourceSets { main { java { srcDirs = ['src'] } } test { java { srcDirs = ['test'] } } }
In the above code, we reassign srcDirs. If we just want to add a new path to the existing code path, we can use srcDir:
sourceSets { main { java { srcDir 'thirdParty/src/main/java' } } }
In addition to the path of the source code, we can also configure the compiled parameters and specify the compiled JDK version number:
compileJava { options.incremental = true options.fork = true options.failOnError = false options.release = 7 }
Note that gradle must be above JDK8 to run, but we can specify gradle to compile the source code using Java 6 or Java 7.
We can also specify the properties of the preview version:
tasks.withType(JavaCompile) { options.compilerArgs += "--enable-preview" } tasks.withType(Test) { jvmArgs += "--enable-preview" } tasks.withType(JavaExec) { jvmArgs += "--enable-preview" }
Manage resource s
In addition to source code files, java also has some resource files, such as configuration files, image files, language files, and so on. We need to copy these configuration files to a specific target directory.
By default, gradle copies the files in src/[sourceSet]/resources to the target folder.
Let's look at a complex copy action:
task copyDocs(type: Copy) { from 'src/main/doc' into 'build/target/doc' } //for Ant filter import org.apache.tools.ant.filters.ReplaceTokens //for including in the copy task def dataContent = copySpec { from 'src/data' include '*.data' } task initConfig(type: Copy) { from('src/main/config') { include '**/*.properties' include '**/*.xml' filter(ReplaceTokens, tokens: [version: '2.3.1']) } from('src/main/config') { exclude '**/*.properties', '**/*.xml' } from('src/main/languages') { rename 'EN_US_(.*)', '$1' } into 'build/target/config' exclude '**/*.bak' includeEmptyDirs = false with dataContent }
Packaging and publishing
We can package the corresponding files according to different build types. For example, for java lib, we can upload source code and java doc files at the same time:
java { withJavadocJar() withSourcesJar() }
For example, we can also package it into a fat jar package:
plugins { id 'java' } version = '1.0.0' repositories { mavenCentral() } dependencies { implementation 'commons-io:commons-io:2.6' } task uberJar(type: Jar) { archiveClassifier = 'uber' from sourceSets.main.output dependsOn configurations.runtimeClasspath from { configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } } }
Generate javadoc
gradle's java library plug-in has a javadoc task that can generate documents for java projects. It supports standard javadoc and other types of documents, such as Asciidoc. Let's take an example of generating Asciidoc:
configurations { asciidoclet } dependencies { asciidoclet 'org.asciidoctor:asciidoclet:1.+' } task configureJavadoc { doLast { javadoc { options.doclet = 'org.asciidoctor.Asciidoclet' options.docletpath = configurations.asciidoclet.files.toList() } } } javadoc { dependsOn configureJavadoc }