第一章:Gradle 创建可执行 jar 文件
1.1 概述
- 如果要想创建可执行的 jar 文件,一般需要考虑将第三方的组件保存在 jar 文件之中,所以除了基本的程序打包之外,还需要考虑到将第三方的 jar 文件一起打包的操作。
1.2 依赖的配置
- 在项目中引入 druid 的组件,修改
build.gradle
文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
sourceCompatibility = 1.8 // 源代码版本
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
1.3 启动类
- 为了方便 jar 文件的执行,一般都会定义有一个程序启动类:
package com.github.fairy.era;
/**
* @author 许大仙
* @version 1.0
* @since 2021-12-24 15:36
*/
public class GradleMain {
public static void main(String[] args) {
System.out.println("你好啊,Gradle");
}
}
1.3 Gradle 配置
- 如果现在要想项目打包成一个可执行的 jar 文件,就需要修改
build.gradle
文件,加入各种配置项:
// 定义一个公共的变量描述当前使用的 JDK 版本
def jdkVersion = 1.8
sourceCompatibility = jdkVersion // 源代码版本
targetCompatibility = jdkVersion // 目标版本
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes(['Manifest-Version' : getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class' : "$mainClassName", // 程序主类名称
'Implementation-Title' : 'hello-gradle', // 实现标题
'Implementation-Version': archiveVersion // 实现的内部版本号
])
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
1.4 打包
- 通过 Gradle 对当前的项目进行打包处理。
- 程序执行命令:
gradle clean build
- 程序执行结果:
- 在使用 build 进行项目构建的时候会自动找到里面的 jar 任务进行项目的构建处理,当构建成功后会得到一个 gradle-1.0.jar 文件,这是一个可执行的 jar 文件。
1.5 执行 jar
- 既然生成的是一个可执行的 jar 文件,那么直接通过本地的 JDK 提供的命令执行当前的程序:
java -jar gradle-1.0.jar
第二章:Gradle 依赖库打包范围
2.1 概述
- 在 Maven 中所有的依赖库并不是最终都会直接进行打包,会根据不同的范围有着不同的作用,同理对于 Gradle 来说,也是一样。
- 对于当前使用的 build.gradle 配置文件来说,引入了如下的几个依赖:
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
}
- 此时的程序一共提供了 2 个依赖库,但是最终在打包生成 jar 包的时候里面只有一个 druid.jar 文件,那么主要的原因在于 druid 使用了 implementation 打包范围,而对于 testImplementation 由于只是工作在测试环境,所以没有必要将其打包在最终的程序文件中。
2.2 Gradle 支持的打包范围
打包范围(老版本) | 打包范围(新版本 | ||
---|---|---|---|
compile | 依赖的库文件在编译及运行时都需要,前提:apply plugin: ‘war’ 或 apply plugin: ‘java’ | implementation | A 依赖 B ,B 依赖 C ,如果 B 依赖 C 使用的是 implementation ,那么在 A 中是访问不到 C 中的方法的,如果需要访问,请使用 api 依赖。 |
compile | 依赖的库文件在编译时需要,但是在运行时不需要,前提:apply plugin: ‘war’ | api | 此配置的行为类似于 compile (现已弃用) |
provided | 依赖的库文件在编译时需要,但是在运行时不需要,前提:apply plugin: ‘war’ | compileOnly | 此配置的行为类似于 provided (现已弃用) |
runtime | 依赖的库文件在编译时需要,但是在编译时不需要,前提:apply plugin: ‘java’ | runtimeOnly | 此配置的行为类似于 runtime (现已弃用) |
testCompile | 依赖库在测试的时候需要 | testImplementation | 此配置的行为类似于 testCompile (现已弃用) |
debugCompile | 依赖文件在 debug 模式下生效 | debugImplementation | 此配置的行为类似于 debugCompile (现已弃用) |
releaseCompile | 赖文件在最终 Release 模式下生效 | releaseImplementation | 此配置的行为类似于 releaseCompile (现已弃用) |
2.3 本地 jar
- 默认情况下所有项目中需要使用到的 Gradle 依赖全部都是通过网络下载的,但是如果说现在某些依赖已经在本地了,不希望再去网络进行引用,Gradle 也是支持这一功能的。
- ① 在项目中添加一个新的目录 libs 。
- ② 将本地需要导入的 jar 文件保存在此目录之中。
- ③ 修改 build.gradle 配置文件,在依赖配置上进行本地的引用:
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
/* 进行本地的引用 */
implementation fileTree(dir: 'libs', includes: ['*.jar'])
}
- 程序执行命令:
gradle clean build
- 程序执行结果:
- 完整的
build.gradle
文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
def jdkVersion = 1.8
sourceCompatibility = jdkVersion // 源代码版本
targetCompatibility = jdkVersion // 目标版本
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
implementation fileTree(dir: 'libs', includes: ['*.jar'])
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes(['Manifest-Version' : getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class' : "$mainClassName", // 程序主类名称
'Implementation-Title' : 'hello-gradle', // 实现标题
'Implementation-Version': archiveVersion // 实现的内部版本号
])
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
2.4 api
- 在早期的 Gradle 版本中推荐使用的是 compile ,但是时过境迁,目前的 Gradle 推荐使用的是 implementation,然而 implementation 不会将依赖进行传递,可是我们又需要将依赖进行传递,那么就需要使用 api 了(需要在项目中引入新的插件)。
- 引入新的插件,修改 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library' // 引入一个新的插件
}
- 修改引入,修改 build.gradle 文件:
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
api group: 'com.alibaba', name: 'druid', version: '1.2.8'
implementation fileTree(dir: 'libs', includes: ['*.jar'])
}
- 程序执行命令:
gradle clean build
- 程序执行结果:
2.5 依赖信息
- 在一个项目中肯定会引入大量的第三方的依赖,对于这些依赖信息可以直接通过 gradle 命令查看。
- 程序执行命令:
gradle -q dependencies
- 程序执行结果:
10:52:49: 正在执行 'dependencies -q'…
------------------------------------------------------------
Root project
------------------------------------------------------------
annotationProcessor - Annotation processors and their dependencies for source set 'main'.
No dependencies
api - API dependencies for source set 'main'. (n)
\--- com.alibaba:druid:1.2.8 (n)
apiElements - API elements for main. (n)
No dependencies
archives - Configuration for archive artifacts. (n)
No dependencies
compileClasspath - Compile classpath for source set 'main'.
\--- com.alibaba:druid:1.2.8
compileOnly - Compile only dependencies for source set 'main'. (n)
No dependencies
default - Configuration for default artifacts. (n)
No dependencies
implementation - Implementation only dependencies for source set 'main'. (n)
\--- unspecified (n)
runtimeClasspath - Runtime classpath of source set 'main'.
\--- com.alibaba:druid:1.2.8
runtimeElements - Elements of runtime for main. (n)
No dependencies
runtimeOnly - Runtime only dependencies for source set 'main'. (n)
No dependencies
testAnnotationProcessor - Annotation processors and their dependencies for source set 'test'.
No dependencies
testCompileClasspath - Compile classpath for source set 'test'.
+--- com.alibaba:druid:1.2.8
\--- org.junit.jupiter:junit-jupiter:5.8.2
+--- org.junit:junit-bom:5.8.2
| +--- org.junit.jupiter:junit-jupiter:5.8.2 (c)
| +--- org.junit.jupiter:junit-jupiter-api:5.8.2 (c)
| +--- org.junit.jupiter:junit-jupiter-params:5.8.2 (c)
| \--- org.junit.platform:junit-platform-commons:1.8.2 (c)
+--- org.junit.jupiter:junit-jupiter-api:5.8.2
| +--- org.junit:junit-bom:5.8.2 (*)
| +--- org.opentest4j:opentest4j:1.2.0
| +--- org.junit.platform:junit-platform-commons:1.8.2
| | +--- org.junit:junit-bom:5.8.2 (*)
| | \--- org.apiguardian:apiguardian-api:1.1.2
| \--- org.apiguardian:apiguardian-api:1.1.2
\--- org.junit.jupiter:junit-jupiter-params:5.8.2
+--- org.junit:junit-bom:5.8.2 (*)
+--- org.junit.jupiter:junit-jupiter-api:5.8.2 (*)
\--- org.apiguardian:apiguardian-api:1.1.2
testCompileOnly - Compile only dependencies for source set 'test'. (n)
No dependencies
testImplementation - Implementation only dependencies for source set 'test'. (n)
\--- org.junit.jupiter:junit-jupiter:5.8.2 (n)
testRuntimeClasspath - Runtime classpath of source set 'test'.
+--- com.alibaba:druid:1.2.8
\--- org.junit.jupiter:junit-jupiter:5.8.2
+--- org.junit:junit-bom:5.8.2
| +--- org.junit.jupiter:junit-jupiter:5.8.2 (c)
| +--- org.junit.jupiter:junit-jupiter-api:5.8.2 (c)
| +--- org.junit.jupiter:junit-jupiter-engine:5.8.2 (c)
| +--- org.junit.jupiter:junit-jupiter-params:5.8.2 (c)
| +--- org.junit.platform:junit-platform-commons:1.8.2 (c)
| \--- org.junit.platform:junit-platform-engine:1.8.2 (c)
+--- org.junit.jupiter:junit-jupiter-api:5.8.2
| +--- org.junit:junit-bom:5.8.2 (*)
| +--- org.opentest4j:opentest4j:1.2.0
| \--- org.junit.platform:junit-platform-commons:1.8.2
| \--- org.junit:junit-bom:5.8.2 (*)
+--- org.junit.jupiter:junit-jupiter-params:5.8.2
| +--- org.junit:junit-bom:5.8.2 (*)
| \--- org.junit.jupiter:junit-jupiter-api:5.8.2 (*)
\--- org.junit.jupiter:junit-jupiter-engine:5.8.2
+--- org.junit:junit-bom:5.8.2 (*)
+--- org.junit.platform:junit-platform-engine:1.8.2
| +--- org.junit:junit-bom:5.8.2 (*)
| +--- org.opentest4j:opentest4j:1.2.0
| \--- org.junit.platform:junit-platform-commons:1.8.2 (*)
\--- org.junit.jupiter:junit-jupiter-api:5.8.2 (*)
testRuntimeOnly - Runtime only dependencies for source set 'test'. (n)
No dependencies
(c) - dependency constraint
(*) - dependencies omitted (listed previously)
(n) - Not resolved (configuration is not meant to be resolved)
A web-based, searchable dependency report is available by adding the --scan option.
10:52:49: 执行完成 'dependencies -q'。
2.6 依赖过滤
- 有些时候可能并不需要将所有范围的依赖全部进行列出,只希望列出 implementation 的依赖范围,那么可以在依赖列表的时候进行一些参数的配置。
- 程序执行命令:
gradle -q dependencies --configuration implementation
- 程序执行结果:
8:50:36: 正在执行 'dependencies --configuration implementation -q'…
------------------------------------------------------------
Root project
------------------------------------------------------------
implementation - Implementation only dependencies for source set 'main'. (n)
+--- com.alibaba:druid:1.2.8 (n)
\--- unspecified (n)
(n) - Not resolved (configuration is not meant to be resolved)
A web-based, searchable dependency report is available by adding the --scan option.
8:50:37: 执行完成 'dependencies --configuration implementation -q'。
2.7 依赖查找
- 一个项目中有可能存在有大量的依赖,那么也可以直接利用 gradle 项目进行指定依赖名称的查找。
- 程序执行命令:查找项目中是否存在 druid 的依赖
gradle -q dependencyInsight --dependency druid --configuration implementation
- 程序执行结果:
Execution failed for task ':dependencyInsight'.
> Resolving dependency configuration 'implementation' is not allowed as it is defined as 'canBeResolved=false'.
Instead, a resolvable ('canBeResolved=true') dependency configuration that extends 'implementation' should be resolved.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
- 此时程序会报错,根据提示信息在 build.gradle 中增加如下的配置信息:
configurations {
implementation {
canBeConsumed = true
canBeResolved = true
}
}
- 再次执行程序命令,程序执行结果:
9:11:31: 正在执行 'dependencyInsight --dependency druid --configuration implementation -q'…
com.alibaba:druid:1.2.8
variant "runtime" [
org.gradle.status = release (not requested)
org.gradle.usage = java-runtime (not requested)
org.gradle.libraryelements = jar (not requested)
org.gradle.category = library (not requested)
]
com.alibaba:druid:1.2.8
\--- implementation
A web-based, searchable dependency report is available by adding the --scan option.
9:11:31: 执行完成 'dependencyInsight --dependency druid --configuration implementation -q'。
- 所有的依赖的配置在 Gradle 里面都有其自己的范围,同时也可以通过 Gradle 提供的各种命令进行依赖的查找。
第三章:Gradle 依赖库排除
3.1 概述
- 在进行依赖库引入的时候,由于各个不同的依赖库有可能去引用同一个依赖文件(最为常见的就是日志组件了),这样就会造成各种的包引入不明确的问题,所有就需要进行一些依赖的排除操作。
3.2 日志依赖
- 修改 build.gradle 文件,进行一些日志依赖文件的定义:
dependencies { // 依赖管理
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
/* 日志依赖 */
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30'
implementation group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.30'
implementation group: 'org.slf4j', name: 'log4j-over-slf4j', version: '1.7.30'
implementation group: 'org.slf4j', name: 'slf4j-nop', version: '1.7.30'
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.2'
implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: '2.13.2'
}
3.3 日志文件
- 如果要想进行日志的显示,还需要配置有一个日志文件:logback.xml ,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="d://home" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- 控制台输出 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 按照每天生成日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/Yootk.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<root level="INFO"> <!-- 日志输出级别 -->
<appender-ref ref="STDOUT,FILE" />
</root>
<root level="ERROR"> <!-- 日志输出级别 -->
<appender-ref ref="FILE" />
</root>
<root level="DEBUG"> <!-- 日志输出级别 -->
<appender-ref ref="FILE" />
</root>
</configuration>
3.4 编写程序
- 既然已经配置好了日志相关的依赖以及日志的配置文件,那么就可以直接进行日志的操作了。
package com.github.fairy.era;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author 许大仙
* @version 1.0
* @since 2021-12-24 15:36
*/
public class GradleMain {
private static Logger logger = LoggerFactory.getLogger(GradleMain.class);
public static void main(String[] args) {
logger.info("你好啊,Gradle");
}
}
- 程序执行结果:
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
- 此时的程序执行会出现依赖库重复的问题,因为发现了两个同样的依赖库:log4j-over-slf4j.jar 和 slf4j-log4j12.jar 。
3.5 依赖排除
- 如果要想解决上面的问题,那么就需要进行依赖的排除操作,修改 build.gradle 文件(以下方式任选一种即可,因为两种都是 Groovy 语法):
configurations { // 进行依赖的配置
all*.exclude group: 'org.slf4j', module: 'slf4j-log4j12' // 全局的排除设置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
configurations { // 进行依赖的配置
all.collect {configuration -> // 全局的排除设置
configuration.exclude group: 'org.slf4j', module: 'slf4j-log4j12'
}
implementation {
canBeConsumed = true
canBeResolved = true
}
}
- 此时,引入了一个全局的排除设置,这样就表示在进行依赖引入的时候不在项目中去使用 slf4j-log4j12 的组件包。
3.6 模块排除
- 以上的操作是针对于一个组织中对应的模块编写的排除操作,那么如果有需求也可以针对于一个模块进行排除,修改 build.gradle 文件:
configurations { // 进行依赖的配置
// 模块排除
implementation.exclude module: 'slf4j-log4j12'
implementation {
canBeConsumed = true
canBeResolved = true
}
}
3.7 依赖排除
- 可以直接在进行某个依赖配置的时候进行排除,修改 build.gradle 文件:
dependencies { // 依赖管理
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.8.2'
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: '1.2.8'
implementation fileTree(dir: 'libs', includes: ['*.jar'])
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30'
// 类似于 Maven 的 exclusion 标签
implementation(group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.30') {
exclude module: 'log4j-api'
}
implementation group: 'org.slf4j', name: 'log4j-over-slf4j', version: '1.7.30'
implementation group: 'org.slf4j', name: 'slf4j-nop', version: '1.7.30'
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.2'
implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: '2.13.2'
}
注意:实际开发中一般还是会使用依赖排除。
第四章:Gradle 依赖库版本号统一管理
4.1 概述
- 在任何的构建工具中,由于版本编号经常性的需要进行更新,所以就需要对版本号进行统一的管理操作,在 Gradle 里面为了实现这样的版本号的统一管理,可以专门定义一个配置文件,这个配置文件在需要的地方进行进入即可。
4.2 配置文件
- 在项目中编写一个 config.gradle 的配置文件,内容如下:
ext { // 编写所有的相关扩展操作
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
druidVersion = '1.2.8'
junitJupiterVersion = '5.8.2'
}
4.3 引入配置
- 如果想让配置文件中的配置生效,则必须在 build.gradle 配置文件中进入 config.gradle 的引入,在 plugins 下编写,修改 build.gradle 文件:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
apply from: 'config.gradle' // 引入一个配置文件
- 引入此配置文件就相当于将所有的变量全部引入项目之中,那么后面的项目直接使用变量填充即可。
4.4 Gradle 配置
- 将 config.gradle 中引入的变量直接在 build.gradle 中进行填充处理,修改 build.gradle 文件:
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
dependencies { // 依赖管理
/* junit 5 */
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: junitJupiterVersion
/* druid */
implementation group: 'com.alibaba', name: 'druid', version: druidVersion
}
4.5 程序编译
- 为了检查当前的配置是否生效,可以考虑将代码进行编译操作。
- 程序执行命令:
gradle clean build
- 程序执行结果:
4.6 版本确定
- 现在已经成功的实现了版本号的统一配置,但是如果要想确定当前的配置是否成功,那么就可以查看类的版本信息的方式来完成,而这种方式就需要进入到类所在的目录中进行控制。
- 程序执行命令:
javap -verbose GradleMain.class
- 程序执行结果:
D:\project\gradle-01\build\classes\java\main\com\github\fairy\era>javap -verbose GradleMain.class
Classfile /D:/project/gradle-01/build/classes/java/main/com/github/fairy/era/GradleMain.class
Last modified 2021-12-27; size 582 bytes
MD5 checksum e61e67b8cc83ecad8ccb76f0733acb21
Compiled from "GradleMain.java"
public class com.github.fairy.era.GradleMain
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #21.#22 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #23 // 你好啊,Gradle
#4 = Methodref #24.#25 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #26 // com/github/fairy/era/GradleMain
#6 = Class #27 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/github/fairy/era/GradleMain;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 args
#17 = Utf8 [Ljava/lang/String;
#18 = Utf8 SourceFile
#19 = Utf8 GradleMain.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = Class #28 // java/lang/System
#22 = NameAndType #29:#30 // out:Ljava/io/PrintStream;
#23 = Utf8 你好啊,Gradle
#24 = Class #31 // java/io/PrintStream
#25 = NameAndType #32:#33 // println:(Ljava/lang/String;)V
#26 = Utf8 com/github/fairy/era/GradleMain
#27 = Utf8 java/lang/Object
#28 = Utf8 java/lang/System
#29 = Utf8 out
#30 = Utf8 Ljava/io/PrintStream;
#31 = Utf8 java/io/PrintStream
#32 = Utf8 println
#33 = Utf8 (Ljava/lang/String;)V
{
public com.github.fairy.era.GradleMain();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/github/fairy/era/GradleMain;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String 你好啊,Gradle
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 11: 0
line 12: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
}
SourceFile: "GradleMain.java"
- JDK 版本和 major.minor 版本: | JDK 版本 | major.minor version | | —- | —- | | 1.1 | 45 | | 1.2 | 46 | | 1.3 | 47 | | 1.4 | 48 | | 1.5 | 49 | | 1.6 | 50 | | 1.7 | 51 | | 1.8 | 52 |
第五章:Gradle 依赖库集中管理
5.1 概述
- 虽然可以通过单独的配置文件模式,将所有需要的版本号进行统一的配置,但是从某些严格意义上来讲,如果将所有的依赖都配置在 build.gradle 文件里面,那么随着时间的推移,build.gradle 文件将会变得又臭又长(可以和传统 Maven 项目中的 pom.xml 对比)!!!
- 在 Gradle 中考虑到了传统的 Maven 所带来的各种的维护问题,所以对于依赖库的管理的最佳实践模式 —— 建立一个单独的依赖配置文件,通过这个依赖配置文件定义所有需要用到的依赖,随后在 build.gradle 文件里面去通过这个依赖文件引入相应的依赖库,换言之,build.gradle 文件不直接参与任何版本的操作。
5.2 依赖文件
- 在项目中定义有一个 dependencies.gradle 配置文件,内容如下:
// 定义所有要使用的版本号
ext.versions = [
junitJupiterVersion: '5.8.2',
druidVersion : '1.2.8'
]
// 定义所有的依赖库
ext.libraries = [
/* junit 5 */
'junit-jupiter': "org.junit.jupiter:junit-jupiter:${versions.junitJupiterVersion}",
/* druid */
druid : "com.alibaba:druid:${versions.druidVersion}"
]
5.2 配置引入
- 修改 build.gradle 文件,引入以上的库文件:
apply from :'dependencies.gradle' // 引入所有的依赖文件
5.3 依赖配置
- 所有的依赖配置最终都是在 build.gradle 文件中完成的,修改在 build.gradle 文件中的 dependencies 中配置,内容如下:
dependencies { // 依赖管理
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
- 完整的 build.gradle 内容如下:
plugins {
id 'java' // 配置的是一个 Java 插件(Java 项目)
id 'java-library'
}
ext {
jdkVersion = JavaVersion.VERSION_1_8 // 传统的 JDK 版本都是需要自己编写字符串的,而 Gradle 中提供了这样的操作
}
apply from :'dependencies.gradle' // 引入所有的依赖文件
configurations { // 进行依赖的配置
implementation {
canBeConsumed = true
canBeResolved = true
}
}
group 'com.github.fairy.era' // 组织名称
version '1.0' // 项目版本
// 定义一个公共的变量描述当前使用的 JDK 版本
sourceCompatibility = jdkVersion
targetCompatibility = jdkVersion
repositories { // 仓库配置
mavenCentral()
}
dependencies { // 依赖管理
/* junit 5 */
testImplementation( // 如果有多个依赖,使用 , 隔开
libraries.'junit-jupiter'
)
/* druid */
implementation( // 如果有多个依赖,使用 , 隔开
libraries.'druid'
)
}
tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
options.encoding = "UTF-8"
}
def mainClassName = 'com.github.fairy.era.GradleMain' // 程序的主类名称
jar {
archivesBaseName = 'gradle' // 生成的 jar 文件名称,如果不写此名称则使用项目名称
manifestContentCharset = 'UTF-8' // 设置整个文件的编码
metadataCharset = 'UTF-8' // 元数据设置编码
manifest {
attributes 'Manifest-Version': getArchiveVersion().getOrNull(), // 程序版本号
'Main-Class': "${mainClassName}",// 程序主类名称
'Implementation-Title': 'hello-gradle',// 程序主类名称
'Implementation-Version': archiveVersion // 版本编号
}
into('lib') { // 将程序锁需要的第三方组件包配置到 lib 目录之中
from configurations.compileClasspath
}
}
test { // 进行测试任务的配置
useJUnitPlatform() // 使用 Junit 平台
}
sourceSets { // 建立源代码的目录集合
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources', 'src/main/config']
}
}
}
- 那么,此时的 Gradle 项目就可以通过一个专属的依赖文件进行所有依赖库的管理了,以后如果要维护版本只需要修改专属的依赖配置文件集合,不需要改动 build.gradle 文件了。