Gradle 依赖管理-ApiHug准备-工具篇-004

news2024/12/23 4:45:43

 🤗 ApiHug × {Postman|Swagger|Api...} = 快↑ 准√ 省↓

  1. GitHub - apihug/apihug.com: All abou the Apihug   
  2. apihug.com: 有爱,有温度,有质量,有信任
  3. ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace

ApiHug 整个工具链基于 Gradle, 使用 ApiHug 准备工作最先需要学习的就是 gradle. 工欲善其事,必先利其器

依赖管理

通俗来讲,依赖管理由如下两部分组成。

首先,Gradle 需要知道项目构建或运行所需要的一些文件,以便于找到这些需要的文件, 这些输入的文件为项目的依赖。

其次,你可能需要构建完成后自动上传到某个地方。这些输出为发布。

大部分工程都不太可能完全自给自足,一般你都会用到其他工程的文件。

比如我工程需要 Hibernate 就得把它的类库加进来,比如测试的时候可能需要某些额外 jar 包,例如 JDBC 驱动或 Ehcache 之类的 Jar 包。

这些文件就是工程的依赖。Gradle 需要你告诉它工程的依赖是什么,它们在哪,然后帮你加入构建中。依赖可能需要去远程库下载,比如 Maven 或者 Ivy 库。也可以是本地库,甚至可能是另一个工程。我们称这个过程叫依赖解决。

通常,依赖的自身也有依赖。例如,Hibernate 核心类库就依赖于一些其他的类库。所以,当 Gradle 构建你的工程时,会去找到这些依赖。我们称之为依赖传递

大部分工程构建的主要目的是脱离工程使用。例如,生成 jar 包,包括源代码、文档等,然后发布出去。

这些输出的文件构成了项目的发布内容。Gralde 也会为你分担这些工作。

你声明了发布到到哪,Gradle 就会发布到哪。“发布”的意思就是你想做什么。比如,复制到某个目录,上传到 Maven 或 Ivy 仓库。或者在其它项目里使用,这些都可以称之为发行。

#简单例子


plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter:2.3.4.RELEASE'
    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.3.4.RELEASE'
}

看这个最基础项目里面包含什么:

#插件

插件表面这个是个java 项目, java 项目都有哪些功能呢? java_pluginopen in new window, 当然最新的有 java_libraryopen in new window。

#仓库

Gradle 是在一个被称之为仓库的地方找寻所需的外部依赖。

仓库即是一个按 group,name 和 version 规则进行存储的一些文件。

Gradle 可以支持不同的仓库存储格式,如 Maven 和 Ivy,并且还提供多种与仓库进行通信的方式,如通过本地文件系统或 HTTP。

默认情况下,Gradle 没有定义任何仓库,你需要在使用外部依赖之前至少定义一个仓库,例如 Maven 中央仓库。

复杂如:


repositories {
        mavenLocal()
        maven { url "https://maven.aliyun.com/repository/public" }
        maven { url "https://maven.aliyun.com/repository/spring" }
        maven { url "https://maven.aliyun.com/repository/spring-plugin" }
        maven { url "https://repo.spring.io/release" }
        maven { url "https://repo.spring.io/milestone" }
        mavenCentral()
}

重头戏是依赖管理和声明Declaring dependenciesopen in new window

#依赖

#依赖配置

一个依赖配置包含 4 个部分:

  1. group – organization, company, project 标识
  2. name – 具体依赖的功能标识
  3. version – 版本
  4. classifier – 上面 group, name, version无法区分的, 比如不同OS分不同的包, 可以看netty的针对不同操作系统poll 实现包。

implementation 'org.springframework.boot:spring-boot-starter:2.3.4.RELEASE'

当然grovvy语法也如此操作:

implementation group:'org.springframework.boot', name: 'spring-boot-starter', version: '2.3.4.RELEASE'

#依赖类型

除我们日常接触比较多的 implementation testImplementation 其实 gradle 支持的更多。

名词描述
api显式的依赖声明, 运行时候classpath 依赖, 有接口在打包中依赖
implementation内部引用需要, 打包不暴露到外界环境
compileOnly编译时候需要, 比如JSR 标准协议,或者annotation 处理
compileOnlyApi编译时候需要, 但是在运行时classpath 也需要
runtimeOnly运行时候需要, 编译时候不需要
testImplementation在编译测试时候需要
testCompileOnlytest compile 时期需要
testRuntimeOnlytest runtime 时期需要

重点参数下 api vs implementation 理解起来比较拗口, 举个例子:


dependencies {
    implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.2'
}

如下依赖, 如果我们通过 ./gradlew dependencies 可以查看:

compileClasspath 依赖如下:


compileClasspath - Compile classpath for source set 'main'.
\--- com.fasterxml.jackson.core:jackson-databind:2.10.2
     +--- com.fasterxml.jackson.core:jackson-annotations:2.10.2
     \--- com.fasterxml.jackson.core:jackson-core:2.10.2

runtimeClasspath 依赖如下:


runtimeClasspath  - Compile classpath for source set 'main'.
\--- com.fasterxml.jackson.core:jackson-databind:2.10.2
     +--- com.fasterxml.jackson.core:jackson-annotations:2.10.2
     \--- com.fasterxml.jackson.core:jackson-core:2.10.2

可以看到 编译 和 运行 时候的 path 一样, jackson-databind 将他的 dependencies 也声明为 compile 期的依赖; mvnrepository 下面已经标注open in new window。

如下一个项目依赖, 项目 依赖 Library A , A 依赖 Library B Library C:

  1. 项目使用了 Library A 里面的类
  2. Library A 使用了 Library B 和 Library C 里面的类。
  3. Library A 暴露了 Library B 里面的接口 (比如某个接口里面使用 Library B 里面的类或者接口)
  4. Library C 只在 Library A 内部使用 (比如内部方法)

背景知道了, 然后看看这个例子给我们的 jar 依赖管理带来什么样的挑战:

上面的 3&4 是分歧点, LBI (Library binary interface), ABI(Application binary interface) 之分。

ABI:

  1. public method 参数
  2. 返回类型
  3. 父类, 接口类

NO-ABI:

  1. 方法内的类型
  2. 私有方法内使用的类型

如此看来再编译时和运行时我们的lib 有什么不同。

Lib编译compile运行runtime
A需要需要
B需要需要
C不需要需要

这么多的铺垫其实就是为了和你解释 api 和 implementation 不一样地方。 如此分析上面的例子我们可以如此定义依赖关系:


dependencies {
    api 'library-b'
    implementation 'library-c'
}

官方文档: Recognizing API and implementation dependenciesopen in new window,再看一个官方例子:


// The following types can appear anywhere in the code
// but say nothing about API or implementation usage
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class HttpClientWrapper {

    private final HttpClient client; // private member: implementation details

    // HttpClient is used as a parameter of a public method
    // so "leaks" into the public API of this component
    public HttpClientWrapper(HttpClient client) {
        this.client = client;
    }

    // public methods belongs to your API
    public byte[] doRawGet(String url) {
        HttpGet request = new HttpGet(url);
        try {
            HttpEntity entity = doGet(request);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            entity.writeTo(baos);
            return baos.toByteArray();
        } catch (Exception e) {
            ExceptionUtils.rethrow(e); // this dependency is internal only
        } finally {
            request.releaseConnection();
        }
        return null;
    }

    // HttpGet and HttpEntity are used in a private method, so they don't belong to the API
    private HttpEntity doGet(HttpGet get) throws Exception {
        HttpResponse response = client.execute(get);
        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            System.err.println("Method failed: " + response.getStatusLine());
        }
        return response.getEntity();
    }
}

可以看到 HttpClientWrapper 构造函数依赖 HttpClient, 同时对于 ExceptionUtils 的依赖只是内部方法。 所以 httpclient 是API 依赖, commons-lang 只是实现依赖。


dependencies {
    api 'org.apache.httpcomponents:httpclient:4.5.7'
    implementation 'org.apache.commons:commons-lang3:3.5'
}

#其他依赖关系

文件、项目:

implementation project(':shared') 
runtimeOnly files('libs/sampleOne.jar', 'libs/sampleTwo.jar')
runtimeOnly fileTree("libs") { include "*.jar" }

#Spring

好像在java世界, 逃避不了 spring 操作方式: Dependency Management Pluginopen in new window & 源码open in new window & Example projectopen in new window。

io.spring.dependency-management 是可以独立使用的 spring 提供的依赖管理plugin。

plugins {
  id 'org.springframework.boot' version '2.7.1'
  id 'io.spring.dependency-management' version '1.0.11.RELEASE'
  id 'java'
}

dependency-management (dependencyManagement) 有两个功能:

  1. DSL 配置依赖管理
  2. 导入Maven POM

依赖管理:

dependencyManagement {
    dependencies {
        dependency 'org.springframework:spring-core:4.0.3.RELEASE'
    }
}

这个配置会导致所有依赖 spring-core(直接或者间接)的都固定到版本 4.0.3.RELEASE, 如果在依赖管理中声明了, 那么depedencies 中无需再制定版本:

dependencies {
    implementation 'org.springframework:spring-core'
}

引入BOM:


dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
  implementation 'org.springframework.cloud:spring-cloud-starter-config'  //不需要指定版本
  annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' 
  testImplementation 'org.springframework.boot:spring-boot-starter-test'
  testImplementation 'org.testcontainers:junit-jupiter' //不需要指定版本
}

dependencyManagement {
  imports {
    mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}"
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
  }
}

dependencyManagement 也可以用来组织自己的 pom 是 java-platform 外一个解决方案。

java-platformopen in new window 方式:


description = "Spring Framework (Bill of Materials)"

apply plugin: 'java-platform'
apply from: "$rootDir/gradle/publications.gradle"

group = "org.springframework"

dependencies {
	constraints {
		parent.moduleProjects.findAll{ it.name != 'spring-core-graalvm' }.sort { "$it.name" }.each {
			api it
		}
	}
}

publishing {
	publications {
		mavenJava(MavenPublication) {
			artifactId = 'spring-framework-bom'
			from components.javaPlatform
		}
	}
}

dependencyManagement 方式:

dependencyManagement {
    imports {
        mavenBom 'io.spring.platform:platform-bom:1.1.1.RELEASE'
    }
    dependencies {
        dependency 'com.google.guava:guava:18.0'
    }
}


<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.spring.platform</groupId>
            <artifactId>platform-bom</artifactId>
            <version>1.1.1.RELEASE</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

#参考

  1. Gradle API and implementation separation open in new window
  2. Dependency Management in Gradleopen in new window
  3. Dependency management in Gradleopen in new window
  4. Dependency Management Pluginopen in new window
  5. The Java Platform Pluginopen in new window
  6. How to use Gradle api vs. implementation dependencies with the Java Library pluginopen in new window
  7. gradle-dependency-management github example

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

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

相关文章

比特币革命:刚刚开始

作者&#xff1a;Marius Farashi Tasooji 编译&#xff1a;秦晋 要充分理解比特币及其含义&#xff0c;首先必须理解什么是价值&#xff0c;什么是货币。以及是什么赋予资产价值&#xff1f; 这个问题看似愚蠢&#xff0c;但实际上非常有趣。我们的生活是由我们消费或出售的物品…

每日OJ题_两个数组dp④_力扣44. 通配符匹配

目录 力扣44. 通配符匹配 解析代码 力扣44. 通配符匹配 44. 通配符匹配 难度 困难 给你一个输入字符串 (s) 和一个字符模式 (p) &#xff0c;请你实现一个支持 ? 和 * 匹配规则的通配符匹配&#xff1a; ? 可以匹配任何单个字符。* 可以匹配任意字符序列&#xff08;包…

计算机网络 网络命令的使用

一、实验内容 1.PING网络命令的实验 ping 127.0.0.1(内部回环测试)ping 本主机的IP地址ping 默认网关地址ping远端目的地的IP地址ping localhostping域名 2.其他网络命令实验 命令用途ipconfig/all 显示当前系统网络配置&#xff0c;包括IP地址、子网掩码、默认网关等trace…

四级作文模板——议论文——现象解释

议论文类型 现象解释 第一句 with the rapid development of society / economy / education / technology / culture / medical / service(任选) , it is of great necessity for youngster / students to improve our speaking ability.随着社会/经济/教育/科技/文化/医疗…

生产车间图纸无纸化,生产车间图纸无纸化解决方案

生产车间图纸无纸化是指通过采用数字化设备和技术&#xff0c;将传统的纸质图纸转化为电子文档&#xff0c;并在生产过程中实现图纸的电子化、网络化和自动化管理。这一转变旨在提高工作效率、降低成本、提高安全性&#xff0c;并推动生产车间的现代化和智能化。 实现生产车间图…

选择排序解读

在计算机科学中&#xff0c;排序算法是一种将数据元素按照某种顺序排列的算法。今天&#xff0c;我们要探讨的是选择排序&#xff08;Selection Sort&#xff09;&#xff0c;这是一种简单直观的排序方法&#xff0c;通过不断选择剩余元素中的最小&#xff08;或最大&#xff0…

【算法统治世界】动态规划 个人笔记总结

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

Ubuntu20.04连接不了无线网

1.首先查看网卡型号 lspci Network controller显示的就是网卡型号 也可以使用如下命令 lspci -nnk | grep 0280 -A3 2.找到对应的驱动并下载安装 我的电脑的网卡型号为Realtek Semiconductor Co., Ltd. Device b852&#xff0c;则采用如下命令安装&#xff1a; sudo ap…

langchain-chatchat加载Azure Open AI

1.找到knowledge_base_chat.py文件中的get_ChatOpenAI函数 2.按crtl进入get_ChatOpenAI函数位置 3.注释原先的get_ChatOpenAI函数&#xff0c;修改成以下内容&#xff1a; def get_ChatOpenAI(model_name: str,temperature: float,streaming: bool True,callbacks: List[Ca…

等保2(1),最新出炉

9.密码管理 c)采用硬件密码模块实现密码运算和密钥管理 10.变更管理 11.备份与恢复管理 12.安全事件处置 c&#xff09;应建立联合防护和应急机制&#xff0c;负责处置跨单位安全事件 13.应急预案管理 e&#xff09;应建立重大安全事件的跨单位联合应急预案&#xff0c;并进…

二:什么是RocketMQ

RocketMQ是阿里开源的消息中间件产品&#xff0c;纯Java开发&#xff0c;具有高吞吐量、高可用性、适合大规模分布式系统应用的特点,性能强劲(零拷贝技术)&#xff0c;支持海量堆积,在阿里内部进行大规模使用&#xff0c;适合在互联网与高并发系统中应用。 官方文档&#xff1a…

2024年,AIGC如何渗透我的生活?

本篇博文列举本人最常用的 6 款app中 AIGC 发挥的功能及作用。 Cursor 作为一名科研工作者&#xff0c;平时最常用的软件就是代码编写工具。Cursor内置的Chat功能&#xff0c;可以辅助完成代码编辑&#xff0c;随时随地实现ChatGPT私有化。 Grammarly 可用于Word和Overleaf等…

创建型模式--4.抽象工厂模式【弗兰奇一家】

1. 奔向大海 在海贼世界中&#xff0c;位于水之都的弗兰奇一家是由铁人弗兰奇所领导的以拆船为职业的家族&#xff0c;当然了他们的逆向工程做的也很好&#xff0c;会拆船必然会造船。船是海贼们出海所必备的海上交通工具&#xff0c;它由很多的零件组成&#xff0c;从宏观上看…

41---音频电路设计

视频链接 音频电路设计01_哔哩哔哩_bilibili 音频电路设计 1、音频基本介绍 1.1、设备 1.1.1、音频接口 型号&#xff1a;ABA-JAK-038-K44 电脑主机上的音频输出插口&#xff0c;一个是粉色的&#xff0c;用来连接麦克风或话筒&#xff0c;一个是绿色的&#xff0c;用来连…

item_review获取商品评论API接口采集用户评论数据接入示例

要获取商品评论API接口采集用户评论数据&#xff0c;首先需要了解API的具体请求方式、参数以及返回数据格式。以下是一个示例&#xff08;获取API接入KEY&#xff09;&#xff1a; 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secret…

leetcode之704 二分查找

文章目录 每日碎碎念一、题目要求及测试点704 二分查找测试点提示 二、题解自己上手正经题解二分法之左闭右闭二分法之左闭右开 三、总结 每日碎碎念 苦痛生活今日起 从今天开始LeetCode打卡&#xff0c;一边重新刷题&#xff0c;一边春招等笔面试&#xff0c;人生苦痛… 一、…

可视化大屏的应用(9):设备运行监控的应用案例

通过可视化大屏&#xff0c;监控人员可以更加直观地了解设备的运行情况&#xff0c;及时发现问题并进行处理&#xff0c;提高设备的稳定性和可靠性&#xff0c;大千UI工场本期带来相关利用的案例&#xff0c;欢迎友友们品鉴。 可视化大屏在设备运行监控领域有以下作用&#xf…

数据结构:构建完全二叉查找树

文章目录 1、步骤 1: 对给定数组排序2、步骤 2: 递归构建完全二叉查找树3、注意4、在有序数组中寻找根结点位置5、代码实现6、其他方法&#xff1f;基本思路插入操作删除操作特别考虑 对于一个给定序列的二叉查找树&#xff0c;有很多种&#xff0c;但是完全二叉查找树只有一种…

springboot 整合 mybatis(配置版)

代码及配置整合 创建实体类,与数据库对应 创建 mapper、service 和 controller @AutowiredUserService userService;@ResponseBody@GetMapping("/user")public com.vazquez.bootstudy.model.User getById(@RequestParam("id") Long id) {return userServ…

AI大模型基石:文字与数字的起源与演变

AI大模型基石&#xff1a;文字与数字的起源与演变 1、文字 1.1、起源 我们的祖先在还没有发明文字和语言之前就已经开始使用“咿咿呀呀”的声音来传播信息了&#xff0c;比如在野外活动遇到危险&#xff0c;然后发出“咿咿呀呀”的声音来提醒同伴小心&#xff0c;同伴在接收到…