本文介绍Gradle常用配置,本人很早就开始使用Gradle代替Maven作为项目构建工具,Gradle相较于Maven繁琐的XML配置来说,确实更为先进,依托于Groovy脚本的强大,也更加灵活。

1、Jetbrains IDEA设置Gradle不自动创建模块

在IDEA某个版本之后,创建或导入Gradle项目的时候,无法再取消勾选Create separate module per source set,多少有点强加的意思,因为自动为每个资源文件夹创建一个目录,模块多了以后,会出现意料之外的错误,比如某个依赖无法加载等问题

编辑.idea/gradle.xml,加上一行<option name="resolveModulePerSourceSet" value="false" />就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="true" />
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$PROJECT_DIR$/../../../../DevTools/Gradle/gradle-6.8.3" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

然后重新导入Gradle项目

2、使用阿里云Maven仓库加速依赖下载

Gradle 6.8.3即以上适用

编辑settings.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pluginManagement {
repositories {
mavenLocal()
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/public/' }
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
mavenLocal()
maven { url = uri("https://maven.aliyun.com/repository/central") } // central
maven { url = uri("https://maven.aliyun.com/repository/public") } // jcenter & public
maven { url = uri("https://maven.aliyun.com/repository/google") } // google
maven { url = uri("https://maven.aliyun.com/repository/spring") } // spring
maven { url = uri("https://maven.aliyun.com/repository/spring-plugin") } // spring plugin
maven { url = uri("https://maven.aliyun.com/repository/grails-core") } // spring plugin
}
}
rootProject.name = 'my-prject'

3、maven-publish.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// jar添加以下插件
//plugins {
// id 'java-library'
// id 'maven-publish'
//}
// bom添加以下插件
//plugins {
// id 'java-platform'
// id 'maven-publish'
//}

def artifactory = 'https://packages.aliyun.com/maven/repository/'
def releasePath = "xxx"
def snapshotsPath = "xxx"
def mavenName = 'my-project'
afterEvaluate { Project project ->
if (project.plugins.hasPlugin("maven-publish")) {
if (project.plugins.hasPlugin("java")) {
java {
withSourcesJar()
}
}
publishing {
repositories {
maven {
name "${mavenName}"
url = "${artifactory}${(version.endsWith('SNAPSHOT') ? snapshotsPath : releasePath)}"
credentials {
username "${maven_username}"
password "${maven_password}"
}
authentication {
basic(BasicAuthentication)
}
}
}

publications {
omac(MavenPublication) {
from components.java
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
}
}
}
}
}

build.gradle引入即可

1
apply from: "${rootDir}/gradle/maven-publish.gradle"

4、docker.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
afterEvaluate {
if (pluginManager.hasPlugin("application")) {
task archiveDeps(type: Tar) { task ->
def dependencies = task.project.configurations.runtimeClasspath.fileCollection { true }
from dependencies.sort()
compression = Compression.GZIP
archiveFileName = "dep-libs.tar.gz"
from jar.archiveFile
destinationDirectory = file("$buildDir/docker")
}

task copyDeps(type: Copy) {
dependsOn(archiveDeps)
from tarTree(resources.gzip("$buildDir/docker/dep-libs.tar.gz"))
into "$buildDir/docker/libs/"
}

task copyApp(type: Copy) {
dependsOn(jar, startScripts)
from "$buildDir/scripts/"
from jar.outputs
into "$buildDir/docker/"
}

task prepare() {
dependsOn(copyApp, copyDeps)
}

}
}

添加插件application

1
2
3
plugins {
id "application"
}

并配合以下Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# First stage: complete build environment
FROM registry.cn-shanghai.aliyuncs.com/halmawork/gradle:6.8.3-jdk11-openj9 AS builder

ARG MAVEN_USERNAME
ARG MAVEN_PASSWORD
ARG MODULE

RUN echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties \
&& echo "org.gradle.parallel=true" >> ~/.gradle/gradle.properties \
&& echo "maven_username=$MAVEN_USERNAME" >> ~/.gradle/gradle.properties \
&& echo "maven_password=$MAVEN_PASSWORD" >> ~/.gradle/gradle.properties

WORKDIR /builder
COPY . /builder

# package jar
RUN gradle :$MODULE:clean :$MODULE:prepare

# Second stage: minimal runtime environment
FROM adoptopenjdk/openjdk11:jre

ENV MODULE ""

ENV TZ=Asia/Shanghai

LABEL name=$MODULE

RUN ln -fs /usr/share/zoneinfo/$TZ /etc/localtime \
&& dpkg-reconfigure -f noninteractive tzdata

WORKDIR /app

COPY --from=builder /builder/build/docker/libs/*.jar /app/lib/
COPY --from=builder /builder/build/docker/$MODULE /app/bin/run
COPY --from=builder /builder/build/docker/$MODULE-*.jar /app/lib/

EXPOSE 8080

CMD ["/app/bin/run"]

打包docker镜像

1
$ docker build -f gradle/Dockerfile -t gcdd1993/demo:latest-snapshot .

5、支持kotlin

gradle.properties

1
kotlin_version=1.5.10

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
plugins {
id "org.jetbrains.kotlin.jvm" version "${kotlin_version}" apply false // jvm 插件
id "org.jetbrains.kotlin.plugin.spring" version "${kotlin_version}" apply false // spring 插件,allopen 插件
id "org.jetbrains.kotlin.kapt" version "${kotlin_version}" apply false // kapt,代替annotationProcessor
id "org.jetbrains.kotlin.plugin.noarg" version "${kotlin_version}" apply false // 用于自定义注解生成no arg constructor
}

apply plugin: "org.jetbrains.kotlin.jvm"
apply plugin: "org.jetbrains.kotlin.plugin.spring"
apply plugin: "org.jetbrains.kotlin.kapt"
apply plugin: "org.jetbrains.kotlin.plugin.noarg"

compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=warn"]
jvmTarget = "11"
}
}

noArg {
annotation("io.github.gcdd1993.NoArg") // 该注解注释的class,会生成NoArg Constructor
}

6、限制项目JDK版本

对于多人协同时,很有用,避免因为JDK版本不一导致的各种问题

1
2
3
4
def javaVersion = System.getProperty("java.version")
if (!javaVersion.startsWith("11")) {
throw new RuntimeException("Incompatible JRE version: " + javaVersion + ". Use JRE 11 instead.")
}

7、为项目编译jar文件添加项目编译信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
plugins {
id "org.springframework.boot" version "${spring_boot_version}" apply false
id "com.gorylenko.gradle-git-properties" version "2.2.4"
}

apply plugin: "io.spring.dependency-management"
apply plugin: "org.springframework.boot"

jar {
enabled = true
manifest {
attributes(
"Implementation-Title": project.name,
"Implementation-Version": project.version,
"Built-By": System.properties["user.name"],
"Build-Timestamp": new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
"Created-By": "Gradle ${gradle.gradleVersion}",
"Build-Jdk": "${System.properties["java.version"]} (${System.properties["java.vendor"]} ${System.properties["java.vm.version"]})",
"Build-OS": "${System.properties["os.name"]} ${System.properties["os.arch"]} ${System.properties["os.version"]}"
)
}
}

springBoot {
buildInfo()
}

如果是Spring Boot项目,还可以通过以下方法,在程序启动时,打印出编译信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 在应用启动时,打印应用基本信息
*
* @author gcdd1993
* @date 2021/2/20
* @since 1.0.0
*/
class AppInfoPreviewAutoConfiguration {
private val log = LoggerFactory.getLogger(javaClass)

@Autowired(required = false)
private val gitProperties: GitProperties? = null

@Autowired(required = false)
private val buildProperties: BuildProperties? = null

@Value("\${spring.application.name}")
private val name: String? = null

@EventListener(ApplicationStartedEvent::class)
fun onBootUp(event: ApplicationStartedEvent?) {
log.info("{} Started.", name)
if (buildProperties != null) {
log.info("build.name : {}", buildProperties.name)
log.info("build.artifact : {}", buildProperties.artifact)
log.info("build.group : {}", buildProperties.group)
log.info("build.version : {}", buildProperties.version)
log.info("build.time : {}", buildProperties.time.atZone(ZoneId.systemDefault()).toLocalDateTime())
} else {
log.warn("cannot find any build properties file from this project. please reference: https://stackoverflow.com/questions/47283048/how-to-capture-build-info-using-gradle-and-spring-boot.")
}
if (gitProperties != null) {
log.info("commit.branch : {}", gitProperties.branch)
log.info("commit.commit.id : {}", gitProperties.commitId)
log.info("commit.commit.time : {}", gitProperties.commitTime.atZone(ZoneId.systemDefault()).toLocalDateTime())
} else {
log.warn("cannot find any git properties file from this project. please add gradle plugin: https://plugins.gradle.org/plugin/com.gorylenko.gradle-git-properties.")
}
}
}

未完待续。。。