【Android辟邪】之:gradle——在项目间共享依赖关系版本

翻译和简单修改自:https://docs.gradle.org/current/userguide/platforms.html#sec:sharing-catalogs

建议看原文(有能力的话)

现在 Gradle 脚本可以使用两种语法编写:Kotlin 和 Groovy
本文只使用kotlin脚本语法,更详细请查看Gradle官网(上面的网址)

在项目间共享依赖关系版本

  1. 集中声明依赖关系
  2. 共享目录
  3. 使用平台控制传递版本
  4. 导入 Maven BOM
  5. 我应该使用平台还是目录?

1. 集中声明依赖关系

1.1 使用版本目录

版本目录是一个以依赖关系坐标表示的依赖关系列表,用户在构建脚本中声明依赖关系时可从中挑选。

例如,可以从版本目录中选择依赖关系坐标,而不是使用字符串符号来声明依赖关系:

例 1. 使用版本目录中声明的库 build.gradle.kts

dependencies {implementation(libs.groovy.core)
}

在这里,libs 就是一个目录,而 groovy 则代表该目录中的一个依赖项。与直接在构建脚本中声明依赖关系相比,版本目录有很多优点:

对于每个目录,Gradle 都会生成类型安全的访问器,这样就可以在集成开发环境中通过自动补全轻松添加依赖关系。每个目录对构建过程中的所有项目都可见。它是声明依赖项版本的中心位置,可确保对该版本的修改适用于每个子项目。目录可以在多个依赖项之间共享版本声明。目录可以将依赖项的组和名称与其实际版本分开,并使用版本引用来代替,这样就可以在多个依赖项之间共享一个版本声明。

使用 libs.someLib 符号添加依赖关系的效果与直接在构建脚本中硬编码组、工件和版本的效果完全相同。
依赖关系目录并不强制执行依赖关系的版本:就像普通的依赖关系符号一样,它声明所请求的版本或丰富的版本。该版本并不一定是冲突解决时选择的版本。

1.2 声明版本目录

版本目录可以在 settings.gradle(.kts) 文件中声明。在上面的例子中,为了让 groovy 可以通过 libs 目录使用,我们需要将别名与 GAV(组、工件、版本)坐标关联起来:

示例 2. 声明版本目录 settings.gradle.kts

dependencyResolutionManagement {versionCatalogs {create("libs") {library("groovy-core", "org.codehaus.groovy:groovy:3.0.5")library("groovy-json", "org.codehaus.groovy:groovy-json:3.0.5")library("groovy-nio", "org.codehaus.groovy:groovy-nio:3.0.5")library("commons-lang3", "org.apache.commons", "commons-lang3").version {strictly("[3.8, 4.0[")prefer("3.9")}}}
}

1.3 别名及其与类型安全访问器的映射

别名必须由一系列标识符组成,中间用破折号 (-,推荐使用)、下划线 (_) 或点 (.)隔开。标识符本身必须由 ascii 字符(最好小写)组成,最后跟上数字。

例如

guava 是一个有效别名groovy-core 是一个有效的别名commons-lang3 是一个有效的别名androidx.awesome.lib 也是一个有效别名
但这 #is.not!

然后为每个子组生成类型安全访问器。例如,在名为 libs 的版本目录中给出以下别名:

guava、groovy-core、groovy-xml、groovy-json、androidx.awesome.lib

我们将生成以下类型安全的访问器:

libs.guavalibs.groovy.corelibs.groovy.xmllibs.groovy.jlibs.androidx.awesome.lib

其中 libs 前缀来自版本目录名称。

如果想避免生成子组访问器,我们建议使用大小写来区分。例如,别名 groovyCore、groovyJson 和 groovyXml 将分别映射到 libs.groovyCore、libs.groovyJson 和 libs.groovyXml 访问器。

在声明别名时,值得注意的是-、_和.字符都可以用作分隔符,但生成的目录将全部规范化为.:例如,foo-bar 作为别名会自动转换为 foo.bar。

有些关键字是保留的,因此不能用作别名。下一个词不能用作别名:

扩展类约定

下一个单词 c

捆绑包版本插件

因此,对于依赖项来说,别名 versions-dependency 是无效的,而 versionsDependency 或 dependency-versions 则是有效的。

1.4 版本号相同的依赖项

在声明版本目录的第一个例子中,我们可以看到,我们为 groovy 库的不同组件声明了 3 个别名,所有这些别名都共享同一个版本号。

我们可以声明一个版本并引用它,而不是重复相同的版本号:

例 3. 与库分开声明版本 settings.gradle.kts

dependencyResolutionManagement {versionCatalogs {create("libs") {version("groovy", "3.0.5")version("checkstyle", "8.37")library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")library("commons-lang3", "org.apache.commons", "commons-lang3").version {strictly("[3.8, 4.0[")prefer("3.9")}}}
}

例 4. 使用版本目录中声明的版本 build.gradle.kts

单独声明的版本也可通过类型安全访问器获得,这使得它们比依赖版本适用于更多用例,尤其是工具:

checkstyle {// will use the version declared in the catalogtoolVersion = libs.versions.checkstyle.get()
}

例 5. 在有更具体的别名时使用版本目录中的版本 build.gradle.kts

如果已声明版本的别名也是某些更具体别名的前缀,
如 libs.versions.zinc 和 libs.version.zinc.apiinfo,
则可通过类型安全访问器上的 asProvider() 获取更通用版本的值:

scala {zincVersion = libs.versions.zinc.asProvider().get()
}

例 6. 依赖关系符号对应build.gradle.kts

目录中声明的依赖关系会通过与其名称相对应的扩展名暴露给联编脚本。
在上例中,由于在设置中声明的目录名为 libs
因此在当前联编的所有联编脚本中,扩展名都是 libs
所以可以使用以下符号(x.x.x)声明依赖关系:

dependencies {implementation(libs.groovy.core)implementation(libs.groovy.json)implementation(libs.groovy.nio)
}

例 7. 依赖关系符号对应 build.gradle.kts

这个(x.x.x)与上面编写的效果完全相同:

dependencies {implementation("org.codehaus.groovy:groovy:3.0.5")implementation("org.codehaus.groovy:groovy-json:3.0.5")implementation("org.codehaus.groovy:groovy-nio:3.0.5")
}

目录中声明的版本是丰富版本。有关完整的版本声明支持文档,请参阅版本目录生成器 API。

1.5 依赖关系包

由于在不同的项目中经常会同时使用某些依赖包,因此版本目录提供了 "依赖包 "的概念。

例 8. 使用依赖关系包 build.gradle.kts

依赖包基本上是多个依赖项的别名。
例如,你可以这样写,而不是像上面那样声明 3 个单独的依赖项:

dependencies {implementation(libs.bundles.groovy)
}

例 9. 声明依赖包 settings.gradle.kts

目录中需要声明名为 groovy 的 bundle:

dependencyResolutionManagement {versionCatalogs {create("libs") {version("groovy", "3.0.5")version("checkstyle", "8.37")library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")library("commons-lang3", "org.apache.commons", "commons-lang3").version {strictly("[3.8, 4.0[")prefer("3.9")}bundle("groovy", listOf("groovy-core", "groovy-json", "groovy-nio"))}}
}

语义也是等同的:添加一个单独的捆绑包相当于单独添加属于该捆绑包的所有依赖项

1.6 插件

外,版本目录还支持声明插件版本。

是通过组、工件和版本坐标(group, artifact and version)来表示的,

例 10. 声明插件版本 settings.gradle.kts

Gradle 插件只通过 id 和版本来标识。因此,它们需要单独声明:

提示:您不能在settings 文件或settings 插件中使用版本目录中声明的插件(因为目录本身是在settings 中定义的,这将是一个鸡和蛋的问题)。

dependencyResolutionManagement {versionCatalogs {create("libs") {plugin("versions", "com.github.ben-manes.versions").version("0.45.0")}}
}

例 11. 使用在目录中声明的插件 build.gradle.kts

然后,该插件可在插件块中访问,并可在构建过程中的任何项目中使用:

plugins {`java-library`checkstylealias(libs.plugins.versions)
}

1.7 使用多个目录

除了传统的 lib 目录,您还可以通过设置 API 声明任意数量的目录。
这样,您就可以将多个源中的依赖关系声明分开,从而使您的编译过程更加高效。

例 12. 使用自定义目录 settings.gradle.kts

dependencyResolutionManagement {versionCatalogs {create("testLibs") {val junit5 = version("junit5", "5.7.1")library("junit-api", "org.junit.jupiter", "junit-jupiter-api").versionRef(junit5)library("junit-engine", "org.junit.jupiter", "junit-jupiter-engine").versionRef(junit5)}}
}

每个目录都会生成一个扩展名,应用于所有项目以访问其内容。因此,选择一个能减少潜在冲突的名称来降低碰撞的几率是有意义的。例如,可以选择以 Libs 结尾的名称。

1.8 libs.versions.toml 文件

除了上述的设置 API,Gradle 还提供了一个常规文件来声明目录。如果在根编译gradle 子目录中找到 libs.versions.toml 文件,那么目录就会根据该文件的内容自动声明。

声明 libs.versions.toml 文件并不能使其成为依赖关系的唯一来源:它只是一个可以声明依赖关系的常规位置。一旦开始使用目录,强烈建议在目录中声明所有依赖关系而不是构建脚本中硬编码组/工件/版本字符串。请注意,插件可能会添加依赖项,而这些依赖项是在此文件之外定义的。

就像 src/main/java 是查找 Java 源代码的约定一样,它并不妨碍其他源代码目录的声明(无论是在联编脚本中还是在插件中),libs.version.toml 文件的存在也不妨碍在其他地方声明依赖关系。

不过,该文件的存在表明,大多数依赖项(即使不是全部依赖项)都将在该文件中声明。因此,对于大多数用户来说,更新依赖版本只需修改该文件中的一行即可。

默认情况下,libs.version.toml 文件将作为 libs 目录的输入。您可以更改默认目录的名称,例如您已经有了一个同名的扩展名:

例 13. 更改默认扩展名 settings.gradle.kts

dependencyResolutionManagement {defaultLibrariesExtensionName = "projectLibs"
}

1.9 libs.versions.toml 文件的格式

TOML 文件由 4 个主要部分组成:

[版本]部分:用于声明可被依赖项引用的版本[库]部分:用于声明坐标别名[捆绑包]部分:用于声明依赖捆绑包[插件]部分:用于声明插件

例如 libs.versions.toml 文件

[versions]
groovy = "3.0.5"
checkstyle = "8.37"[libraries]
groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" } # 注释:version.ref = "groovy" 是解析 [versions] 下的 groovy 变量为 version
groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "groovy" }
groovy-nio = { module = "org.codehaus.groovy:groovy-nio", version.ref = "groovy" }
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer="3.9" } }[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"][plugins]
versions = { id = "com.github.ben-manes.versions", version = "0.45.0" }

版本既可以以单个字符串的形式声明(在这种情况下,它们被解释为必选版本),

也可以以丰富版本的形式声明:

[versions]
my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" }

版本声明的支持成员有

require:要求版本strictly: 严格版本prefer:首选版本reject:被拒绝版本的列表rejectAll:布尔值,用于拒绝所有版本

依赖关系声明可以是一个简单的字符串,在这种情况下,它们被解释为 group:artifact:version 坐标。

1.10 不同的依赖关系符号

或者将版本声明从组和名称中分离出来:

提示:对于别名,"别名及其与类型安全访问器的映射 "一节中描述的规则同样适用。

[versions]
common = "1.4"[libraries]
my-lib = "com.mycompany:mylib:1.4"
my-other-lib = { module = "com.mycompany:other", version = "1.4" }
my-other-lib2 = { group = "com.mycompany", name = "alternate", version = "1.4" }
mylib-full-format = { group = "com.mycompany", name = "alternate", version = { require = "1.4" } }[plugins]
short-notation = "some.plugin.id:1.4"
long-notation = { id = "some.plugin.id", version = "1.4" }
reference-notation = { id = "some.plugin.id", version.ref = "common" }

如果要引用 [versions] 部分声明的版本,应使用 version.ref 属性:

[versions]
some = "1.4"[libraries]
my-lib = { group = "com.mycompany", name="mylib", version.ref="some" }

TOML 文件格式非常宽松,允许编写 "点 "属性作为完整对象声明的快捷方式。例如

a.b.c="d"
等同于:
a.b = { c = "d" }
或
a = { b = { c = "d" } }

详见 TOML 规范。

1.11 类型不安全 API

版本目录(Version catalogs)可通过类型不安全 API 访问。
该 API 在生成的访问器不可用的情况下可用。
它可通过版本目录扩展访问:build.gradle.kts

val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
println("Library aliases: ${versionCatalog.libraryAliases}")
dependencies {versionCatalog.findLibrary("groovy-json").ifPresent {implementation(it)}
}

查看版本目录 API,了解所有支持的方法。

2. 共享目录

版本目录用于单个构建(Build)(可能是多项目构建),但也可能在不同构建(Build)之间共享。

例如,一个组织可能希望创建一个依赖项目录,供来自不同团队不同项目使用。

2.1 从 TOML 文件导入目录

版本目录生成器 API 支持包含来自外部文件的模型
这样就可以在需要时为 buildSrc 重用主构建的目录。

例 14. 与 buildSrc 共享依赖关系目录settings.gradle.kts

例如,buildSrc/settings.gradle(.kts) 文件可以通过使用

dependencyResolutionManagement {versionCatalogs {create("libs") {from(files("../gradle/libs.versions.toml"))}}
}

使用 VersionCatalogBuilder.from(Object dependencyNotation) 方法时,只接受单个文件
这意味着,Project.files(java.lang.Object…) 等注释必须指向一个文件,否则构建将失败。

如果需要更复杂的结构(从多个文件导入版本目录),建议使用基于代码的方法而不是 TOML 文件

例 15. 声明其他目录 settings.gradle.kts

因此,这种技术可用于从不同文件中声明多个目录:

dependencyResolutionManagement {versionCatalogs {// declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' filecreate("testLibs") {from(files("gradle/test-libs.versions.toml"))}}
}

2.2 版本目录插件(plugins)

虽然从本地文件导入目录很方便,但并不能解决在组织内部或为外部用户共享目录的问题。
共享目录的一种方法是编写一个设置插件,发布到 Gradle 插件门户或内部资源库,然后让用户在他们的设置文件中应用该插件。

另外,Gradle 还提供了版本目录插件,可以声明并发布目录。
要做到这一点,你需要应用版本目录插件:

例 16. 应用版本目录插件 build.gradle.kts

plugins {`version-catalog``maven-publish`
}

然后,该插件将公开目录扩展,你可以用它来声明目录:

例 17. 目录定义 build.gradle.kts

catalog {// declare the aliases, bundles and versions in this blockversionCatalog {library("my-lib", "com.mycompany:mylib:1.2")}
}

应用 maven-publish 或 ivy-publish 插件,并将发布配置为使用 versionCatalog 组件,就可以发布这样的目录:

例 18. 发布目录 build.gradle.kts

publishing {publications {create<MavenPublication>("maven") {from(components["versionCatalog"])}}
}

发布此类项目时,会自动生成(并上传)libs.version.toml 文件,其他 Gradle 版本可以使用该文件。

2.3 导入已发布的目录

版本目录插件生成的目录可以通过设置 API 导入:

例 19. 使用发布的目录 settings.gradle.kts

dependencyResolutionManagement {versionCatalogs {create("libs") {from("com.mycompany:catalog:1.0")}}
}

2.4 覆盖目录版本

如果目录声明了版本,则可以在导入目录时覆盖该版本:

例 20. 覆盖已发布目录中声明的版本 settings.gradle.kts

dependencyResolutionManagement {versionCatalogs {create("amendedLibs") {from("com.mycompany:catalog:1.0")// overwrite the "groovy" version declared in the imported catalogversion("groovy", "3.0.6")}}
}

在上例中,任何使用 groovy 版本作为参考的依赖关系都将自动更新为使用 3.0.6。
再次重申,覆盖版本并不意味着实际解析的依赖关系版本也会相同:这只是改变了导入的版本,即声明依赖关系时使用的版本。如果有冲突,实际版本将采用传统的冲突解决方式。

3. 使用平台控制传递版本

平台是一种特殊的软件组件,可用于控制跨依赖关系版本。在大多数情况下,它完全由依赖关系约束组成,这些约束会建议依赖关系版本或强制执行某些版本。因此,在需要在项目间共享依赖版本时,这是一个完美的工具。在这种情况下,项目通常是这样组织的:

一个平台项目,为不同子项目中的各种依赖关系定义约束条件若干依赖于平台并声明无版本依赖关系的子项目

在 Java 生态系统中,Gradle 为此提供了一个插件。

平台作为 Maven BOM 发布也很常见,Gradle 本身也支持这些平台。

使用 platform 关键字可以创建对平台的依赖关系:

例 21. 获取平台声明的版本 build.gradle.kts

dependencies {// get recommended versions from the platform projectapi(platform(project(":platform")))// no version requiredapi("commons-httpclient:commons-httpclient")
}

这个平台符号是一个简写符号,实际上在引擎盖下执行了几个操作:

它将 org.gradle.category 属性设置为 platform,这意味着 Gradle 将选择依赖关系中的平台组件。默认设置 endorseStrictVersions 行为,这意味着如果平台声明了严格的依赖关系,就会强制执行。

这意味着,默认情况下,对某个平台的依赖会触发对该平台定义的所有严格版本的继承,这对平台作者来说非常有用,可以确保所有用户都尊重他们在依赖版本方面的决定。可以通过显式调用 doNotEndorseStrictVersions 方法来关闭此功能。

4. 导入 Maven BOM

Gradle 支持导入物料清单(BOM)文件,这些文件实际上是 .pom 文件,使用 来控制直接依赖和传递依赖的依赖版本。Gradle 中的 BOM 支持与 Maven 中依赖 BOM 时使用 import类似。但在 Gradle 中,它是通过 BOM 上的常规依赖声明来实现的:

例 22. 依赖 BOM 导入其依赖约束 build.gradle.kts

dependencies {// import a BOMimplementation(platform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))// define dependencies without versionsimplementation("com.google.code.gson:gson")implementation("dom4j:dom4j")
}

在示例中,gson 和 dom4j 的版本由 Spring Boot BOM 提供。这样,如果你是为 Spring Boot 这样的平台开发,就不必自己声明任何版本,而可以依赖平台提供的版本。

Gradle 对 BOM 的 块中所有条目的处理方式与 Gradle 的依赖约束类似。这意味着 块中定义的任何版本都会影响依赖关系的解析结果。要成为 BOM,.pom 文件需要设置 pom。

不过,BOM 通常不仅提供版本作为建议,还提供了一种覆盖图中任何其他版本的方法。您可以在导入 BOM 时使用 enforcedPlatform 关键字而不是 platform 来启用这一行为:

例 23. 导入 BOM,确保其定义的版本覆盖找到的任何其他版本 build.gradle.kts

dependencies {// import a BOM. The versions used in this file will override any other version found in the graphimplementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))// define dependencies without versionsimplementation("com.google.code.gson:gson")implementation("dom4j:dom4j")// this version will be overridden by the one found in the BOMimplementation("org.codehaus.groovy:groovy:1.8.6")
}

如果您的软件组件可被其他组件使用,则需要谨慎考虑使用 enforcedPlatform。该声明实际上是传递性的,因此将适用于用户的依赖关系图。不幸的是,如果他们不同意其中一个强制版本,就必须使用排除法。相反,如果你的可重用软件组件对某些第三方依赖版本有强烈的意见,可以考虑使用严格的富版本声明。

5. 我应该使用平台还是目录?

由于平台和目录都会涉及依赖版本,而且都可以用于在项目中共享依赖版本,因此在使用平台和目录时可能会出现混淆,不知道哪一种更好。

简而言之,你应该

使用目录为项目定义依赖关系及其版本,并生成类型安全的访问器使用平台将版本应用于依赖关系图并影响依赖关系的解析

目录有助于集中化依赖关系版本,顾名思义,它只是一个可供挑选的依赖关系目录。我们建议在任何情况下都使用它来声明依赖关系的坐标。Gradle 会使用它来生成类型安全的访问器,为外部依赖关系提供简短的符号,并允许不同项目之间轻松共享这些坐标。使用目录不会对下游用户产生任何影响:这对他们来说是透明的。

平台是一个更重要的

平台中定义的限制不仅会影响项目的直接依赖关系,还会影响传递依赖关系。平台是版本化的,图中的传递依赖关系可能依赖于平台的不同版本,从而导致各种依赖关系升级。平台可以将组件绑定在一起,特别是可以用作调整版本的结构。对平台的依赖关系会被依赖关系的用户 "继承":这意味着对平台的依赖关系会影响用户使用的库版本,即使用户并不直接或间接依赖平台引用的组件。

总之,使用目录总是一种很好的工程实践,因为它可以集中通用定义、共享依赖版本或插件版本,但它只是构建的 “实现细节”:消费者看不到它,目录中未使用的元素也会被忽略。

平台的目的是影响依赖关系解析图,例如通过添加对传递依赖关系的约束:这是一种结构化依赖关系图并影响解析结果的解决方案。

实际上,你的项目既可以使用目录,也可以声明一个使用目录的平台:

例 24. 在平台定义中使用目录 build.gradle.kts

plugins {`java-platform`
}dependencies {constraints {api(libs.mylib)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/671828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10.0 Zookeeper 权限控制 ACL

zookeeper 的 ACL&#xff08;Access Control List&#xff0c;访问控制表&#xff09;权限在生产环境是特别重要的&#xff0c;所以本章节特别介绍一下。 ACL 权限可以针对节点设置相关读写等权限&#xff0c;保障数据安全性。 permissions 可以指定不同的权限范围及角色。 …

人工智能:数据分析之数据预处理、分析模型与可视化

在人工智能和数据科学领域&#xff0c;数据分析是一种核心过程&#xff0c;它帮助我们从大量的数据中提取有价值的信息。数据分析的质量和结果直接影响到决策的效率和准确性。在这篇博客中&#xff0c;我们将详细探讨数据分析的关键步骤&#xff0c;包括数据预处理、分析模型和…

Oracle 面试题 | 15.精选Oracle高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

AR人脸106240点位检测解决方案

美摄科技针对企业需求推出了AR人脸106/240点位检测解决方案&#xff0c;为企业提供高效、精准的人脸识别服务&#xff0c;采用先进的人脸识别算法和机器学习技术&#xff0c;通过高精度、高速度的检测设备&#xff0c;对人脸进行快速、准确地定位和识别。该方案适用于各种应用场…

Backtrader 文档学习- Observers - Benchmarking

Backtrader 文档学习- Observers - Benchmarking 1.概述 backtrader包括两种不同类型的对象&#xff0c;可以帮助跟踪&#xff1a; Observers 观察者Analyzers 分析器 在分析器领域中&#xff0c;已有TimeReturn对象&#xff0c;用于跟踪整个组合价值&#xff08;即包括现金…

黑马Java——集合进阶(List、Set、泛型、树)

一、集合的体系结构 1、单列集合&#xff08;Collection&#xff09; 二、Collection集合 1、Collection常见方法 1.1代码实现&#xff1a; import java.util.ArrayList; import java.util.Collection;public class A01_CollectionDemo1 {public static void main(String[] a…

Token、CAS、JWT和OAuth 2.0认证系统认证中心系统设计对比与实践总结

在现代应用开发中&#xff0c;身份认证是一个关键的问题。为了解决身份认证的需求&#xff0c;开发人员可以选择不同的认证系统&#xff0c;如Token、CAS&#xff08;Central Authentication Service&#xff09;和JWT&#xff08;JSON Web Token&#xff09;OAuth 2.0认证系统…

大厂聚合支付系统架构演进(上)

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; 作者简介&#xff1a;魔都国企技术专家兼架构&#xff0c;多家大厂后端一线研发经验&#xff0c;各大技术社区…

1.0 Zookeeper 分布式配置服务教程

ZooKeeper 是 Apache 软件基金会的一个软件项目&#xff0c;它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。 ZooKeeper 的架构通过冗余服务实现高可用性。 Zookeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高…

C++的缺省参数和函数重载

目录 1.缺省参数 1.1缺省参数的概念 1.2缺省参数的分类 1.3缺省参数使用场景 2.函数重载 2.1函数重载的概念 2.2构成函数重载 1.缺省参数 1.1缺省参数的概念 概念&#xff1a;缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时&#xff0c;如果没…

GPTs保姆级教程之实践

GPTs什么 使用GPTs的前提&#xff1a;ChatGPT Plus帐号 GTPs的作用&#xff1a;把我们和GPT对话的prompt&#xff0c;封装起来成为一个“黑匣子”。 主要有两个作用&#xff1a; 1、避免反复输入prompt&#xff0c;“黑匣子”打开&#xff0c;输入问题即可使用 2、在别人可以…

pycharm deployment 灰色 一直无法点击

我的development的配置如下&#xff0c;我看了很多教程一直不知道为什么一直是灰色的&#xff0c; 文件夹配置&#xff1a; 如果你这里 Autodect&#xff0c;那么你Mapping 的文件夹应该是应该省略这个前缀的&#xff0c;例如我下面&#xff0c;我应该将本地文件夹映射到/home…

项目经理怎么处理客户提出的不合理请求?

一、客户不合理请求的定义和特点 客户不合理请求是指客户在项目执行过程中提出的与项目需求、合同约定或者实际情况不符的要求&#xff0c;通常表现为追加要求、频繁的变更、过度的要求等。这些请求可能会导致项目范围膨胀、成本增加、工期延长、甚至影响项目进度和质量。客户…

(29)最小偶倍数

文章目录 每日一言题目解题思路代码结语 每日一言 读书时&#xff0c;我愿在每一个美好思想的面前停留&#xff0c;就像在每一条真理面前停留一样。——爱默生 题目 题目链接&#xff1a;最小偶倍数 给你一个正整数 n &#xff0c;返回 2 和 n 的最小公倍数&#xff08;正整…

C#中的访问权限

在C#中&#xff0c;访问权限用于控制类、成员和其他程序实体的可访问性。C#提供了一些关键字来定义不同级别的访问权限&#xff0c;以确保适当的封装和信息隐藏。 以下是C#中的四个访问权限级别&#xff0c;按照从最高到最低的顺序排列&#xff1a; private&#xff1a;私有访…

【HTML】MDN

文章目录 一、html元素1.1 <a>1.2 <abbr>1.3 <address>1.4<area>1.5 <article>1.6 <aside>1.7 <audio>1.8 <b>1.9 <base>1.10<bdi>1.11 <bdo>1.12 <blockquote>1.13 <body>1.14 <br>1.15…

人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景&#xff0c;本文将介绍关于SKAttention注意力机制模型的搭建&#xff0c;SKAttention机制具有灵活性和通用性&#xff0c;可应用于计算机视…

Makefile 和 Bash 脚本之间区别和联系

目 录 一、Makefile 和 Bash 脚本的定义 &#xff08;一&#xff09;Bash 脚本 &#xff08;二&#xff09;Makefile 二、Makefile 和 Bash 脚本的相同之处 三、Makefile 和 Bash 脚本的不同点 &#xff08;一&#xff09;目的 &#xff08;二&a…

Linux spell命令教程:如何进行拼写检查(附实例详解和注意事项)

Linux spell命令介绍 spell是一个拼写检查程序&#xff0c;它扫描文本文件中的拼写错误&#xff0c;并将每个拼写错误的单词单独打印出来。它基于原始的UNIX拼写检查器&#xff0c;非常简洁。如果一个单词不在spell的字典中&#xff0c;该单词就会被打印出来。 Linux spell命…

一个Vivado仿真问题的debug

我最近在看Synopsys的MPHY仿真代码&#xff0c;想以此为参考写个能实现PWM-G1功能的MPHY&#xff0c;并应用于ProFPGA原型验证平台。我从中抽取了一部分代码&#xff0c;用Vivado自带的仿真器进行仿真&#xff0c;然后就遇到了一个莫名其妙的问题&#xff0c;谨以此文作为debug…