Gradle 基础学习(三) 认识Command-Line Interface

Gradle命令行接口

除了IDE外,我们主要通过Gradle命令行接口来运行Gradle任务和管理Gradle项目。

下面是Gradle命令行使用的一些参考,熟悉后建议实际项目中使用Gradle Wrapper,gradle用法都可以替换为gradlew (macOS / Linux) 或gradlew.bat (windows)。

Gradle命令行格式

gradle [taskName...] [--option-name...]

选项可以在任务名称之前和之后 

gradle [--option-name...] [taskName...] 

多个任务之间用空格分隔 

gradle [taskName1 taskName2...] [--option-name...] 

接受值的选项和参数之间使用=号, 不用=也可以,但不推荐。 

gradle [...] --console=plain 

启用行为的选项具有长格式选项,其反义用--no-指定。 

gradle [...] --build-cache

gradle [...] --no-build-cache

许多长格式选项有等价的简写,比如 

gradle --help

gradle -h

命令行用法 

执行任务(tasks) 

执行任务是Gradle最重要也是最常用的,Gradle项目的整个构建流程就是由多个任务按照正确顺序执行来完成的。

在Gradle多项目构建中,有一个项目路径的概念

项目路径具有以下模式: 它以一个可选的冒号(:)开头,表示根项目。

项目路径的其余部分是项目名称的冒号分隔序列,其中,下一个项目是前一个项目的子项目:

:sub-project-1 

表示的是根项目下的sub-project-1子项目,默认对应的文件布局就是sub-project-1目录。 

现在我们在根项目上执行一个名为myTask的任务:

$ gradle :myTask

 这会执行myTask任务,以及它的所有依赖项。在执行它之前,先执行依赖项。

在根项目上执行子项目中的任务:

$ gradle :subproject:taskName 等效于 $ gradle subproject:taskName

此时,子项目前面的开头冒号可省略。

从根目录执行一个只包含名称的任务,那么整个项目中只要是这个名称的任务都会被执行。

比如我们在根项目和app、app2子项目的构建脚本文件里都注册了myTask任务,从根项目执行下面命令:

$ gradle myTask

> Configure project :

> Configure project :app

> Task :myTask UP-TO-DATE

> Task :app:myTask UP-TO-DATE

> Task :app2:myTask UP-TO-DATE

 可以看到根项目和子项目的myTask都执行了。

所以,如果不确定某个任务是不是唯一的,最好还是使用项目路径的形式,这样我们可以明确知道要执行什么任务。

从子项目里执行任务:

$ cd subproject

$ gradle taskName

$ gradle myTask

> Task :app:myTask UP-TO-DATE

Skipping task ':app:myTask' as it has no actions.

BUILD SUCCESSFUL in 1s

 从子目录使用Gradle Wrapper命令为 ../gradlew taskName 

只执行了子项目中的任务,和在根目录下不同,后者会执行全部子项目中的taskName。

子项目中如果使用冒号开头,比如$ gradle :taskName,执行的则是根项目的taskName,因为前面说过冒号代表根项目。

为任务提供选项

在任务名后加空格,--作为选项的前缀

$ gradle exampleTask --exampleOption=exampleValue 

从内置选项中消除任务选项的歧义

Gradle不会阻止任务使用与内建选项冲突的选项,像 --profile 或 --help。 

但允许我们在命令行中的任务名称前使用--分隔符来消除内置选项和任务选项的冲突:

 $ gradle [--built-in-option-name...] -- [taskName...] [--task-option-name...] 

假如mytask任务会接受一个名为profile的选项:

在gradle mytask --profile中, Gradle接受--profile作为内置的gradle选项

在gradle -- mytask --profile=value中, Gradle传递--profile作为任务选项

执行多个任务

我们可以指定多个任务,任务的依赖关系决定了执行顺序,没有依赖的任务可能会在命令行中列出的顺序之前执行。

比如我们在app的构建脚本中定义taskA,taskB,taskA依赖taskB:

tasks.register("taskB") {
	println("register app taskB")
    doFirst {
        // Task action = Execution code
        // Run before exiting actions
        println("app taskB doFirst")
    }
}

tasks.register("taskA") {
	println("register app taskA")
	dependsOn(tasks.taskB)
    doFirst {
        // Task action = Execution code
        // Run before exiting actions
        println("app taskA doFirst")
    }

}

然后命令行中的任务顺序是taskA taskB,执行:

$ gradle taskA taskB

register app taskA

register app taskB

> Task :app:taskB

app taskB doFirst

> Task :app:taskA

app taskA doFirst

BUILD SUCCESSFUL in 1s

1 actionable task: 1 executed

看到taskB先执行了,因为依赖要求执行taskA之前,先要执行taskB。

如果是相互独立的任务,以下命令会按照他们在命令行中的顺序执行:

$ gradle test deploy 

命令行顺序安全性 

有时候,两个task之间没有依赖关系,但是对两个task的执行顺序却有所要求。

例如,下面的命令中,clean和build分别是负责清理和构建的任务,没有依赖关系,Gradle总是会先执行clean再build,因为build之后执行clean是不对的,clean会删除build的输出。

$ gradle clean build 或者 $ gradle build clean 

Gradle会通过内部规则排序任务来尊重任务顺序的安全性。

任务排序和任务依赖之间的主要区别在于,排序规则不会影响将执行哪些任务,只会影响它们的执行顺序。

任务排序在许多场景中都很有用:

强制执行任务的顺序:比如build 永远不会在clean 之前运行。

在构建的早期运行构建验证:例如,在开始发布构建工作之前验证我是否拥有正确的凭据。

通过在长时间验证任务之前运行快速验证任务来更快地获得反馈:例如,单元测试应该在集成测试之前运行。

聚合特定类型的所有任务的结果的任务:例如测试报告任务组合所有已执行测试任务的输出。

 在 Gradle 中,提供了两个用于控制任务执行顺序的方法mustRunAfter 和 shouldRunAfter 。这两个方法都用于定义任务之间的依赖关系,但它们有不同的行为和语义。

mustRunAfter 

用于确保一个任务在另一个任务之后运行。如果两个任务之间没有直接的依赖关系,并且你希望一个任务在另一个任务之后执行,你可以使用 mustRunAfter。这个方法创建了一个“软依赖”,即如果可能的话,Gradle 会尽量保证这个顺序,但它并不强制要求这个顺序。

如果因为某些原因(比如任务之间的直接依赖关系或其他任务的执行顺序),Gradle 不能保证 mustRunAfter 指定的顺序,它仍然会尝试执行构建。在这种情况下,Gradle 可能会输出一个警告,说明它没有按照预期的顺序执行任务。

shouldRunAfter

shouldRunAfter 与 mustRunAfter 类似,也是用于指定任务执行顺序的。然而,shouldRunAfter 创建的是一个“更软的依赖”。它表达的是一个建议,告诉 Gradle 如果可能的话,尽量按照这个顺序执行任务。但是,如果因为其他原因(如直接依赖关系)导致这个顺序不能实现,Gradle 会忽略这个建议,并且不会输出任何警告。

在实践中,使用 mustRunAfter 和 shouldRunAfter 时需要谨慎,因为过度使用这些软依赖可能会导致构建逻辑变得复杂且难以维护。最好通过明确的依赖关系(使用 dependsOn 或其他依赖配置方法)来定义任务之间的顺序。这样,Gradle 可以更准确地确定任务的执行顺序,并且构建逻辑也更加清晰和可预测。

从执行中排除任务

我们可以使用-x或--exclude-task命令行选项并提供任务名称排除一个任务,排除的任务不会被执行:

$ gradle dist --exclude-task test

> Task :compile

compiling source

> Task :dist

building the distribution

BUILD SUCCESSFUL in 0s

2 actionable tasks: 2 executed

 Figure 1. Simple Task Graph

在这个例子中,我们看到test没有执行,尽管dist依赖它。test任务的依赖项,比如compileTest,也不会被执行。其他任务所依赖的test的依赖项(例如compile)仍然会被执行。

排除test,会排除test自身以及只被test依赖的任务。

强制执行任务

Gradle提供了许多优化方式来加速构建, Gradle会检查这些任务,如果任务能够重用上次执行的输出,就会跳过执行,标记为UP-TO-DATE或FROM-CACHE等。

命令行选项--rerun-tasks可以告诉Gradle忽略这些up-to-date之类的检查, 重新执行任务以及任务的依赖项。

$ gradle test --rerun-tasks

这有点像执行 gradle clean test,但不删除build的输出。

或者使用内置的task选项--rerun告诉Gradle需要重新运行一个特定的任务。

在一个任务失败后继续构建 

默认情况下,当任何任务执行失败时,Gradle 都会立即中止执行并标记构建为失败。这种设计有几个优点:

  1. 快速反馈:当任务失败时立即停止构建,开发者可以更快地得到反馈,从而可以更早地开始调查问题。
  2. 避免级联失败:有些任务可能依赖于其他任务的输出。如果一个任务失败,那么依赖于它的任务也很可能失败。继续执行这些后续任务可能会产生额外的错误,这些错误可能会掩盖原始问题的真正原因。
  3. 简化错误诊断:当构建在第一个失败的任务处停止时,开发者可以更容易地确定问题的根源,而不是在多个失败的任务中迷失。

然而,在某些特殊情况下,开发者可能希望即使某些任务失败,也要继续执行其他任务。例如,他们可能想要收集多个独立任务的输出,或者他们可能正在运行一组测试,并希望即使某些测试失败也继续执行其他测试。

在这种情况下,Gradle 提供了 --continue 或 -C 选项,允许开发者覆盖默认行为。 

使用 --continue 选项,Gradle 会尝试执行每一个任务,前提是该任务所有依赖项都执行成功,失败的,那么依赖它的其他任务不会执行(避免出现上面说的级联失败)。

$ gradle test --continue 

例如,如果被测代码中存在编译错误,则test不会运行,因为测试任务依赖于compilation任务。Gradle会在构建结束时输出每个遇到的失败。

需要注意,即使使用了 --continue,失败的任务仍然会被标记为失败,并且整个构建过程最终也会被标记为失败。

名称缩写

在命令行上指定任务时,我们可以不必提供任务的全名,只提供足够的任务名称来唯一地标识任务。

例如,gradle che就足以让Gradle识别为要执行check任务。

缩写同样可以应用在项目名称上

运行gradle lib:che命令来执行library子项目里的check任务。

对于更复杂的缩写,可以使用驼峰大小写模式。这些模式被扩展以匹配camel case和kebab case名称。例如,模式foBa(或fB)匹配fooBar和foo-bar。

更具体一点,就是您可以使用gradle mAL:cT命令在my-awesome-library子项目中运行compileTest任务。

$ gradle mAL:cT

> Task :my-awesome-library:compileTest

compiling unit tests

BUILD SUCCESSFUL in 0s

1 actionable task: 1 executed

缩写也可以与-x (--exclude-task)命令行选项一起使用。

跟踪名称扩展 

对于复杂的项目,使用缩写名时,一个错别字就可能导致执行意想不到的任务。

使用 INFO 或者 更详细的 日志记录,输出中将包含有关项目和任务名称展开的额外信息。

比如在前面例子中执行的gradle mAL:cT命令,我们将看到以下日志信息:

No exact project with name ':mAL' has been found. Checking for abbreviated names.

Found exactly one project that matches the abbreviated name ':mAL': ':my-awesome-library'.

No exact task with name ':cT' has been found. Checking for abbreviated names.

Found exactly one task name, that matches the abbreviated name ':cT': ':compileTest'.

常见任务 

在Gradle中,有一些常见的任务是经常在构建过程中使用的。这些任务涵盖了编译源代码、运行测试、生成文档、打包发布等构建生命周期的不同阶段。

下面是一些Gradle中常见的任务:

执行构建
这是一个聚合任务,它会根据项目的类型和配置来执行所有必要的构建任务。对于Java项目,这通常包括编译源代码、运行测试、生成文档和打包JAR文件等:

$ gradle build

运行应用程序
该任务组装应用程序并执行一些脚本或二进制文件:

$ gradle run

运行所有检查
该任务执行所有验证任务(包括测试和检查):

$ gradle check

清理输出
这个任务会删除构建目录(通常是build/),移除所有之前构建产生的文件和目录,从而导致后续任务执行需要大量额外构建时间:

$ gradle clean

测试任务
运行项目的单元测试:

$ gradle test

项目报告 

Gradle提供了几个内置任务来显示构建的具体细节,这对我们理解构建结构和依赖关系以及调试问题很有用。

查看项目结构
这个任务会列出当前 Gradle 多项目构建的所有子项目,以层次结构显示:

$ gradle projects

> Task :projects

------------------------------------------------------------

Root project 'HelloGradle'

------------------------------------------------------------

Root project 'HelloGradle'

+--- Project ':app'

\--- Project ':app2'

查看可用任务清单
运行这个任务会列出当前项目的所有可见任务(那些分配了group的任务):

$ gradle tasks

> Task :tasks

Build tasks

-----------

assemble - Assembles the outputs of this project.

Build Setup tasks

-----------------

init - Initializes a new Gradle build.

Distribution tasks

------------------

assembleDist - Assembles the main distributions

Documentation tasks

-------------------

javadoc - Generates Javadoc API documentation for the main source code.

这些任务是按照分组显示的,比如上面的assemble任务属于任务组Build Setup,短横线后面的“Assembles the outputs of this project. ”是这个任务的描述。

对于那些没有指定group的任务,我们称为隐藏任务,通过在tasks任务中使用--all选项可以列举出所有可用任务,包括隐藏任务,这些没有group的任务会列出在Other分组下, 比如myHideTask:

$ gradle tasks --all

> Task :tasks

Build tasks

-----------

assemble - Assembles the outputs of this project.

Build Setup tasks

-----------------

init - Initializes a new Gradle build.

Distribution tasks

------------------

assembleDist - Assembles the main distributions

Documentation tasks

-------------------

javadoc - Generates Javadoc API documentation for the main source code.

Other tasks

-----------

compileJava - Compiles main Java source.

myHideTask

我们可以使用--group选项只显示这个分组的任务:

$ gradle tasks --group="build setup"

> Task :tasks

------------------------------------------------------------

Tasks runnable from root project 'HelloGradle'

------------------------------------------------------------

Build Setup tasks

-----------------

init - Initializes a new Gradle build.

wrapper - Generates Gradle wrapper files.

To see all tasks and more detail, run gradlew tasks --all

To see more detail about a task, run gradlew help --task <task>

BUILD SUCCESSFUL in 4s

1 actionable task: 1 executed

显示任务使用详情
运行 gradle help --task someTask 查看一个特定任务的详细信息:

$ gradle  -q help --task compileJava

Detailed task information for compileJava

Paths

     :compileJava

     :app2:compileJava

     :app:compileJava

Type

     JavaCompile (org.gradle.api.tasks.compile.JavaCompile)

Options

     --rerun     Causes the task to be re-run even if up-to-date.

Description

     Compiles main Java source.

Group

     -

这份信息里包含了完整的任务路劲、任务类型、可能的命令行任务选项、描述等。 

显示项目依赖关系

运行依赖项任务将为您提供所选项目的依赖项列表,该列表按配置细分。对于每个配置,该配置的直接依赖关系和传递依赖关系显示在树状图中。

$ gradle dependencies

> Task :app:dependencies

------------------------------------------------------------

Project ':app'

------------------------------------------------------------

compileClasspath - Compile classpath for source set 'main'.

+--- project :model

|    \--- org.json:json:20220924

+--- com.google.inject:guice:5.1.0

|    +--- javax.inject:javax.inject:1

|    +--- aopalliance:aopalliance:1.0

|    \--- com.google.guava:guava:30.1-jre -> 28.2-jre

|         +--- com.google.guava:failureaccess:1.0.1

|         +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava

|         +--- com.google.code.findbugs:jsr305:3.0.2

|         +--- org.checkerframework:checker-qual:2.10.0 -> 3.28.0

|         +--- com.google.errorprone:error_prone_annotations:2.3.4

|         \--- com.google.j2objc:j2objc-annotations:1.3

+--- com.google.inject:guice:{strictly 5.1.0} -> 5.1.0 (c)

+--- org.json:json:{strictly 20220924} -> 20220924 (c)

+--- javax.inject:javax.inject:{strictly 1} -> 1 (c)

+--- aopalliance:aopalliance:{strictly 1.0} -> 1.0 (c)

+--- com.google.guava:guava:{strictly [28.0-jre, 28.5-jre]} -> 28.2-jre (c)

+--- com.google.guava:guava:{strictly 28.2-jre} -> 28.2-jre (c)

+--- com.google.guava:failureaccess:{strictly 1.0.1} -> 1.0.1 (c)

+--- com.google.guava:listenablefuture:{strictly 9999.0-empty-to-avoid-conflict-with-guava} -> 9999.0-empty-to-avoid-conflict-with-guava (c)

+--- com.google.code.findbugs:jsr305:{strictly 3.0.2} -> 3.0.2 (c)

+--- org.checkerframework:checker-qual:{strictly 3.28.0} -> 3.28.0 (c)

+--- com.google.errorprone:error_prone_annotations:{strictly 2.3.4} -> 2.3.4 (c)

\--- com.google.j2objc:j2objc-annotations:{strictly 1.3} -> 1.3 (c)

Gradle守护进程选项 

使用Gradle守护进程来运行构建
Gradle Daemon是一个后台进程,它在构建过程中为Gradle提供性能优化。当Gradle开始一个构建任务时,默认会启动一个Gradle Daemon(如果没有守护进程在运行或现有守护进程繁忙)来处理构建任务。构建完成后,Daemon进程会在后台保持运行,并处于IDLE空闲状态。这样在下一次构建时,会先尝试重用空闲的Daemon,不必重新创建和配置构建环境,从而大大提高了构建速度。

--daemon                启用(默认行为

 --no-daemon        不启用

可以在gradle.properties文件中设置以下属性禁用Gradle Daemon:

org.gradle.daemon=false 

停止所有正在运行的Gradle Daemons
Gradle Daemon是安全的,并且通常不需要用户干预。然而在某些情况下,如遇到内存泄漏或守护进程异常崩溃,你可能需要手动停止Gradle Daemon:

$ gradle --stop

Stopping Daemon(s)

1 Daemon stopped

查看正在运行和最近停止的gradle守护进程 

$ gradle --status

       PID     STATUS       INFO

 93032      IDLE            8.2

 92212       STOPPED  (stop command received)

日志选项 

设置日志级别

在Gradle构建时,我们在控制台会看到各种日志信息,可以使用以下选项自定义Gradle日志记录的详细程度,依次是最不详细到最详细。

-q, --quiet         只记录错误

-w, --warn         设置日志级别为“警告”

-i, --info             设置日志级别为“信息”

-d, --debug       调试模式(最详细的日志级别,包括正常的堆栈跟踪)

也可以通过Gradle 属性设置:

-Dorg.gradle.logging.level=(quiet,warn,lifecycle,info,debug)

如果不指定,默认日志级别是lifecycle,通常包含了关于构建过程的重要信息,如任务的开始和结束,以及构建过程中的关键事件。

引导创建新项目

在项目目录下运行内置的gradle init任务来创建一个新的Gradle构建:

$ gradle init

运行内置的gradle wrapper任务来创建Gradle Wrapper :

$ gradle wrapper

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【SDN:逻辑上集中的控制平面,路由选择算法,LS路由工作过程,距离矢量路由选择(distance vector routing)】

文章目录 SDN&#xff1a;逻辑上集中的控制平面SDN的主要思路SDN控制平面和数据平面分离的优势SDN 架构: 数据平面交换机 路由选择算法路由(route)的概念最优化原则(optimality principle)路由的原则路由算法的分类LS路由工作过程&#xff08;相当于一个上帝&#xff09;链路状…

保护公司机密:避免员工带着数据说拜拜

公司的核心资产之一就是数据。无论是客户信息、研发代码、内部决议、财务报告、商业合同、设计图纸等都是公司的重要资产。如果这些数据在员工离职时被带走&#xff0c;或在员工在职期间不当行为导致数据泄露&#xff0c;将给公司带来重大损失。 然而&#xff0c;保护这些数据…

Ps中 饱和度 和 自然饱和度 的区别?

1.饱和度&#xff08;Saturation&#xff09;&#xff1a;在Photoshop中&#xff0c;饱和度是一个全局性调整&#xff0c;它影响图像中所有颜色的鲜艳程度。当你增加饱和度时&#xff0c;所有的颜色都会变得更浓烈、更鲜艳&#xff1b;相反&#xff0c;减小饱和度会使图像整体变…

暗区突围国际服pc端海外版新手前期如何赚钱 暗区突围新手教学

暗区突围国际服pc端海外版新手前期如何赚钱 暗区突围新手教学 暗区突围是一款极为惊险的射击游戏&#xff0c;让玩家充分感受紧张激烈的战斗以及获取财富的过程。但是有许多新手玩家是不会在游戏里赚钱的&#xff0c;也会在赚钱过程中遇到很多问题&#xff0c;我将在这篇文章…

Learning Continuous Image Representation with Local Implicit Image Function

CVPR2021https://github.com/yinboc/liif 问题引入 图像普遍都是使用像素来表示的&#xff0c;而现实世界是连续的&#xff0c;所以本文借鉴3D中neural implicit representation的思想&#xff0c;以连续的方式表示图像&#xff1b;模型输入坐标值和坐标附近的特征&#xff0…

区块链 | NFT 水印:Review on Watermarking Techniques(一)

&#x1f34d;原文&#xff1a;Review on Watermarking Techniques Aiming Authentication of Digital Image Artistic Works Minted as NFTs into Blockchains 1 应用于 NFT 的水印技术 常见的水印技术类型可以分为&#xff1a; 可见 v i s i b l e \mathsf{visible} visi…

关于Anaconda常用的命令

常用命令 查看当前环境下的环境&#xff1a;conda env list查看当前conda的版本&#xff1b;conda --version conda create -n your_env_name pythonX.X&#xff08;2.7、3.6等)命令创建python版本为X.X。名字为your_env_name的虚拟环境。your_env_name文件可以在Anaconda安装…

2024第16届成都教育连锁加盟展6月1日举办 免费参观

2024第16届成都教育连锁加盟展6月1日举办 免费参观 邀请函 主办单位&#xff1a; 中国西部教体融合博览会组委会 承办单位&#xff1a;重庆港华展览有限公司 博览会主题&#xff1a;责任教育科技兴邦 幼教、普教、高教、校外教育、K12学科辅导、婴幼儿教育、兴趣辅导、学…

STC8增强型单片机开发

1.C51版本Keil环境搭建 下载地址是 Keil Product Downloads 选择C51进行下载&#xff1a; 2.STC环境添加 STC-ISP下载 进入stc官网 深圳国芯人工智能有限公司-工具软件 3.将STC添加到Keil中 打开stc-isp工具 按照图例点击按钮 选择keil的安装目录&#xff0c;以实际安装目…

Nacos单机模式集成MySQL

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Nacos支持三种部署…

VALSE 2024 Workshop报告分享┆ 大规模自动驾驶仿真系统研究

视觉与学习青年学者研讨会&#xff08;VALSE&#xff09;旨在为从事计算机视觉、图像处理、模式识别与机器学习研究的中国青年学者提供一个广泛而深入的学术交流平台。该平台旨在促进国内青年学者的思想交流和学术合作&#xff0c;以期在相关领域做出显著的学术贡献&#xff0c…

五月加仓比特币

作者&#xff1a;Arthur Hayes Co-Founder of 100x. 编译&#xff1a;Liam 编者注&#xff1a;本文略有删减 (以下内容仅代表作者个人观点&#xff0c;不应作为投资决策的依据&#xff0c;也不应被视为参与投资交易的建议或意见&#xff09;。 从四月中旬到现在&#xff0c;当你…

动态规划——路径问题:931.下降路径最小和

文章目录 题目描述算法原理1.状态表示&#xff08;经验题目&#xff09;2.状态转移方程3.初始化4.填表顺序5.返回值 代码实现CJava 题目描述 题目链接&#xff1a;931.下降路径最小和 关于这⼀类题&#xff0c;看过我之前的博客的朋友对于状态表示以及状态转移是⽐较容易分析…

Java 中的 HTTP 客户端库OkHttp、Apache HttpClient和HttpUrlConnection

大家好&#xff0c;我是G探险者。 项目开发里面经常会有这么一种场景&#xff1a;与服务器进行 HTTP 通信。一般存在于服务间远程调用的场景 Java 生态系统提供了多种 HTTP 客户端库&#xff0c;每种都有其自己的特点、优势和适用场景。 本文将介绍几种主要的 Java HTTP 客户…

【练习3】

1.将二叉搜索树转为排序的双向链表 (好久没看数据结构&#xff0c;忘完了&#xff0c;学习大佬的代码&#xff09; class Solution { public:Node* prenullptr,*headnullptr; //pre为每次遍历时的前一个节点&#xff0c;head记录头节点Node* treeToDoublyList(Node* root) {if…

Qt应用开发(拓展篇)——图表 QChart

一、前言 QChart是一个图形库模块&#xff0c;它可以实现不同类型的序列和其他图表相关对象(如图例和轴)的图形表示。要在布局中简单地显示图表&#xff0c;可以使用QChartView来代替QChart。此外&#xff0c;线条、样条、面积和散点序列可以通过使用QPolarChart类表示为极坐标…

Vue3 查看真实请求地址

上回说到Vue2查看真实请求地址&#xff0c;那么Vue3该如何查看呢&#xff1f; 传送门&#xff1a; Vue2 查看真实请求地址 1. bypass函数 使用bypass函数获取代理结果&#xff0c;设置响应头&#xff08;请求头设置未生效&#xff0c;也可以在响应头上看&#xff09;。 2. …

PRL:新型量子传感方案突破纳米测量极限

朴茨茅斯大学的研究人员近期宣布了一项令人振奋的量子传感方案&#xff0c;该方案在测量两个干涉光子之间的横向位移方面达到了前所未有的量子灵敏度。 这一技术的突破为超分辨率成像技术带来了新的可能性。目前&#xff0c;这些技术通常采用单光子源作为探针&#xff0c;用于在…

LCD驱动IC-抗干扰液晶段码显示屏驱动芯片,液晶显示驱动原厂-VK2C23A/B LQFP64/48

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK2C23A/B 封装形式&#xff1a;LQFP64/48 概述 VK2C23是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大224点&#xff08;56SEGx4COM&#xff09; 或者最大416点&#xff08;52SEGx8COM&#xff09;的LCD屏。…

电-热耦合市场联合出清!考虑均衡约束的综合能源系统电-热分配方法程序代码!

前言 随着现代城市面临环境问题&#xff0c;原来燃煤的水和空间供暖设备已逐渐被电锅炉和热泵等电气设备所取代。此外&#xff0c;集中生产热能并通过管网分配热能的区域供暖系统&#xff0c;由于其更高的效率&#xff0c;在冬季漫长寒冷的国家和地区越来越受欢迎。供暖设备的…
最新文章