工具篇 | Gradle入门与使用指南
介绍
1.1 什么是Gradle?
Gradle是一个开源构建自动化工具,专为大型项目设计。它基于DSL(领域特定语言)编写,该语言是用Groovy编写的,使得构建脚本更加简洁和强大。Gradle不仅可以构建Java应用程序,还支持多种语言和技术,例如C++、Python、Android等。
更多信息和详细文档可以在Gradle官方网站上找到。
1.2 为什么选择Gradle?
与其他流行的构建工具(如Maven和Ant)相比,Gradle提供了以下优势:
-
性能:Gradle使用它的守护程序和增量构建技术来提高构建速度。你可以在1查看Gradle与其他工具的性能对比图。
-
灵活性:Gradle的DSL使你可以编写高度定制化的构建脚本。
-
可扩展性:Gradle可以通过插件机制轻松扩展,有着丰富的插件生态系统。
-
Android官方支持:对于Android开发,Google官方推荐使用Gradle作为构建工具。
安装和设置
2.1 前提条件
在安装Gradle之前,你需要确保满足以下前提条件:
- 一个有效的Java Development Kit (JDK)安装。Gradle 7.0及以上版本需要JDK版本为8到16。
JAVA_HOME
环境变量已正确设置,指向JDK的安装目录。
2.2 下载和安装Gradle
-
直接下载:你可以从Gradle官方下载页面下载最新版本的Gradle分发包。选择合适的分发包,通常我们使用二进制分发包。
-
使用包管理器:对于某些操作系统,如macOS,你可以使用Homebrew包管理器来安装:
brew install gradle
对于Linux用户,可以使用SDKMAN:
sdk install gradle
-
解压下载的文件到一个合适的安装位置。
-
将解压后的路径添加到你的操作系统的PATH变量中,以便从任何位置运行Gradle命令。
2.3 验证安装
要验证你的Gradle安装是否成功,可以在命令行或终端中运行以下命令:
gradle -v
会显示Gradle的版本、Groovy的版本以及JVM版本等详细信息,如下图所示:
Gradle基础概念
3.1 项目和任务
在Gradle中,构建是由项目和任务组成的。
- 项目:代表你正在构建的东西,可以是一个库、应用程序或者是一个更大的单元,如多模块项目。一个构建可以有一个或多个项目。
- 任务:表示一个原子的构建操作,例如编译类或创建JAR文件。
3.2 构建脚本
Gradle使用构建脚本来配置和控制构建过程。这些脚本默认使用Groovy
或Kotlin DSL
编写,并具有特定的文件名,如build.gradle
或build.gradle.kts
。
构建脚本定义了项目和任务以及它们之间的关系。
3.3 依赖管理
Gradle不仅仅是一个构建工具,它还有一个强大的依赖管理系统,允许你声明你的项目依赖的外部库,并自动下载和管理它们。
3.4 插件
插件扩展了Gradle的功能,使得常见的构建任务和配置变得简单。例如,Java插件为Java项目添加了常见的任务,如编译和打包。
使用插件通常是通过在构建脚本中声明它们来完成的。例如:
plugins {id 'java'
}
3.5 生命周期
Gradle任务有一个生命周期,包括三个阶段:
- 初始化:在此阶段,Gradle决定要处理哪些项目。
- 配置:在此阶段,Gradle构建所有的项目的任务对象。
- 执行:在此阶段,Gradle运行实际的任务。
创建和运行你的第一个Gradle项目
4.1 初始化项目
你可以使用Gradle的命令行界面创建一个新的项目。例如,要创建一个新的Java应用程序,可以运行以下命令:
gradle init --type java-application
指定一些版本号,就会在当前目录下生成一个新的Java项目。
4.2 项目结构
上面的命令执行完毕后,会在目录下创建这样的一个结构:
4.3 编写代码
它默认会在app/src/main/java
目录中添加一个简单的App
类。
public class App {public String getGreeting() {return "Hello World!";}public static void main(String[] args) {System.out.println(new App().getGreeting());}
}
4.4 构建项目
在项目的根目录中,运行以下命令来构建项目:
gradle build
这会编译Java类、运行任何测试(如果有的话)并创建一个JAR文件。
4.5 运行应用
如果你已经使用--type java-application
来初始化项目,你可以使用以下命令来运行你的应用:
gradle run
你应该会看到Hello World!
的输出。
Gradle构建脚本基础
5.1 build.gradle文件的作用
build.gradle
是Gradle构建的核心。它是一个用Groovy或Kotlin DSL编写的脚本,用于定义项目的构建逻辑。它描述了如何编译和打包代码,如何运行测试,以及如何发布成果物。
5.2 任务(Tasks)
任务是构建的原子操作。每个任务都代表了构建过程中的一个步骤。例如,编译源代码、运行单元测试、生成文档等。
tasks.register('myTask') {doLast {println 'This is a custom task.'}
}
上面的代码定义了一个名为myTask
的任务,当其被执行时,会在控制台上打印出消息。我们把这段话复制到刚刚的build.gradle下,然后执行就会打印这句话:
5.3 依赖(Dependencies)
任务之间可能存在依赖关系。这意味着一个任务可能依赖于其他一个或多个任务的成功执行。
tasks.register('taskA') {doLast {println 'Task A is executed.'}
}tasks.register('taskB') {dependsOn 'taskA'doLast {println 'Task B is executed.'}
}
在上面的例子中,taskB
依赖于taskA
。当你执行taskB
时,首先会执行taskA
。如图所示:
5.4 插件(Plugins)
插件是一种强大的扩展Gradle功能的方式。它们可以提供额外的构建任务,增强现有任务,甚至改变Gradle的核心行为。下面列举了一些常用的插件和它们的作用。
plugins {id 'java' // Java插件,为Java项目提供编译、测试和打包的任务id 'application' // Application插件,可以创建可运行的应用程序,提供了‘run’任务来运行应用id 'war' // War插件,用于构建Java Web应用程序,提供了生成WAR文件的任务
}
Java插件
java
插件是最基础的插件之一,提供了用于Java项目的核心任务,如compileJava
来编译Java源代码和test
来运行测试。
Application插件
application
插件扩展了java
插件,提供了创建可执行Java应用程序所需的功能。最重要的是,它添加了run
任务,允许你直接从Gradle运行你的应用。
War插件
war
插件是为Java Web应用程序设计的,用于生成WAR文件,这是Java EE和Servlet容器通常使用的部署格式。
其他插件
Gradle拥有丰富的插件生态系统,包括但不限于Android开发、Spring Boot集成、Docker构建等。你可以浏览Gradle Plugin Portal来查找更多可用的插件。
每个插件都有其独特的配置和用法,因此在使用新插件时,请务必查阅其官方文档,以了解如何正确配置和使用它们。
不同的插件解决了不同的问题,但它们都遵循着同样的设计原则和配置方式,一旦你熟悉了几个常用插件的用法,就能快速学会使用新的插件。
常用的Gradle任务
在Gradle中,每一个构建动作都是通过执行一个或多个任务来完成的。当我们引入插件时,这些插件通常会为我们预定义一些任务。以下,我们将深入探讨一些常用的Gradle任务。
6.1 清理
任务名称: clean
这是一个非常常用的任务。当执行此任务时,Gradle会删除构建目录,确保下一次构建是从干净的状态开始的。
使用命令:
gradle clean
6.2 构建
任务名称: build
此任务是Java插件提供的。当执行此任务时,Gradle会执行完整的构建周期,包括编译、测试等。
使用命令:
gradle build
6.3 测试
任务名称: test
该任务也是Java插件提供的。它负责运行项目的单元测试。
使用命令:
gradle test
6.4 运行
任务名称: run
为了使用此任务,我们需要引入application
插件,并设置主类。
plugins {id 'application'
}
mainClassName = 'com.example.Main'
然后,可以使用以下命令来运行应用:
gradle run
依赖管理
在大多数软件项目中,我们通常依赖于第三方库来完成某些功能。Gradle提供了一个强大的依赖管理系统,使得声明、解析和使用这些第三方库变得轻而易举。
7.1 声明仓库
要使用外部依赖,首先需要告诉Gradle从哪里获取它们。最常用的仓库是Maven Central和JCenter。
例如,要添加Maven Central仓库,你可以这样写:
repositories {mavenCentral()
}
如果你想使用JCenter仓库:
repositories {jcenter()
}
7.2 声明和使用依赖
一旦设置了仓库,就可以开始添加依赖了。
例如,要在Java项目中使用Google的Gson库,可以如下添加:
dependencies {implementation 'com.google.code.gson:gson:2.8.6'
}
其中,implementation
表示这是一个主要的运行时依赖。
7.3 依赖冲突解决
有时,当你的项目依赖于多个库,并且这些库依赖于相同库的不同版本时,就会发生冲突。Gradle有强大的冲突解决策略,通常会选择最新的版本。
但如果你需要更精确的控制,可以这样做:
configurations.all {resolutionStrategy {force 'com.google.code.gson:gson:2.8.5'}
}
这将确保项目中使用的Gson库版本为2.8.5,即使其他依赖可能请求了一个不同的版本。
使用插件
Gradle插件为构建和管理项目提供了额外的功能。从Java到Android,再到Spring Boot,几乎所有的现代框架和平台都有自己的Gradle插件来简化相关任务。
8.1 常见的插件
-
Java 插件: 这是最常用的插件之一,它为Java项目提供了编译、测试和打包的功能。
plugins {id 'java' }
-
Application 插件: 如果你正在构建一个应用程序,这个插件可以帮助你打包并运行它。
plugins {id 'application' }
-
War 插件: 为Web应用程序提供支持,使你能够构建WAR文件。
plugins {id 'war' }
8.2 如何应用插件
你已经看到了如何应用一个插件,那么我们将更深入地了解它。插件可以从Gradle插件门户、Maven仓库或本地文件应用。
-
从Gradle插件门户应用(目前主流做法,简洁):
plugins {id 'org.springframework.boot' version '2.5.4' }
-
从Maven仓库应用:
buildscript {repositories {mavenCentral()}dependencies {classpath("org.springframework.boot:spring-boot-gradle-plugin:2.5.4")} }apply plugin: 'org.springframework.boot'
-
从本地文件应用:
apply from: 'other.gradle'
8.3 插件的配置
大多数插件都提供了一组可配置的属性来定制它们的行为。例如,application
插件允许你指定应用的主类:
application {mainClassName = 'com.example.Main'
}
建议查看官方文档或插件的文档来了解所有可用的配置选项。
多项目构建
大型应用程序和库通常不仅仅是一个孤立的项目。它们可能由多个子项目组成,每个子项目都负责特定的功能。Gradle支持多项目构建,允许你在一个构建中管理和编译多个项目。
9.1 设置子项目
在你的主项目目录下,创建一个settings.gradle
文件(如果尚未存在),并声明子项目:
include 'subproject1', 'subproject2'
此处的subproject1
和subproject2
是子项目的目录名。
9.2 配置和执行跨项目的任务
每个子项目都可以有自己的build.gradle
文件,其中定义了该子项目的构建逻辑。但在根项目中,你可以定义影响所有子项目的构建逻辑:
subprojects {apply plugin: 'java'repositories {mavenCentral()}dependencies {testImplementation 'junit:junit:4.12'}
}
上面的代码片段将Java插件、Maven Central仓库和JUnit依赖添加到所有子项目中。
要在所有子项目上执行任务,只需在根目录下运行该任务。例如,运行gradle build
将构建所有子项目。
如果只想在一个特定的子项目上执行任务,可以这样:
gradle :subproject1:build
多项目构建是Gradle的强大特性之一,尤其是对于大型的代码库。通过合适地组织和配置,你可以确保整个代码库的一致性和可维护性。
自定义任务和扩展
10.1 编写自己的任务
在创建自定义任务时,推荐使用tasks.register
方法来注册新的任务。这是一个懒加载的方法,意味着任务只有在真正需要时才会创建。
abstract class HelloTask extends DefaultTask {@TaskActiondef sayHello() {println 'Hello, Gradle!'}
}tasks.register('hello', HelloTask)
此处使用abstract
关键字是因为Gradle会为任务生成具体的实现。
运行gradle hello
将输出Hello, Gradle!
。
10.2 使用Gradle的API
对于现有的任务,我们通常使用tasks.withType
来对某种特定类型的所有任务进行配置:
tasks.withType(HelloTask).configureEach {// 这里可以为每个HelloTask类型的任务进行配置
}
10.3 扩展的概念
Gradle扩展依然是为项目定义自定义属性的推荐方式。但在新的API中,推荐使用extensions.create
的方式:
extensions.create('myExtension', MyExtension)abstract class MyExtension {String customProperty = 'default value'
}
通过自定义任务和扩展,你可以使Gradle构建过程更加灵活和强大。它们提供了一种机制,使你可以适应项目的特定需求,同时还能保持构建脚本的可读性和组织性。
构建缓存和增量构建
构建优化对于大型项目和频繁的构建操作非常关键。Gradle 提供了两个强大的特性来加速构建:构建缓存和增量构建。
11.1 为什么需要缓存?
每次运行构建时,都有很多任务是重复的,尤其是在没有对代码或资源做任何修改的情况下。构建缓存的作用是存储已经执行过的任务的输出,以便在将来的构建中重用,从而避免不必要的工作。
11.2 构建缓存的使用和配置
默认情况下,Gradle 使用本地构建缓存。你可以通过以下方式在项目的 settings.gradle
或 settings.gradle.kts
文件中启用或禁用它:
buildCache {local {enabled = true}
}
此外,Gradle 也支持远程构建缓存,这在团队开发中非常有用,因为它允许团队成员之间共享构建的输出。
11.3 增量构建
增量构建是指只对自上次构建以来发生变化的部分进行构建。为了使任务支持增量构建,你需要确保:
- 使用
@Input
和@Output
注解来声明任务的输入和输出。 - 使用
@Incremental
注解在TaskAction
方法上。
Gradle 会自动跟踪这些输入和输出之间的变化,并在可能的情况下只执行所需的工作。
11.4 示例:增量构建
假设我们有一个任务,该任务将源文件从一个目录复制到另一个目录,并将所有文件的扩展名更改为 .txt
。我们可以这样做:
11.4.1添加一个自定义任务
在 build.gradle
文件的顶部,添加以下内容:
import org.gradle.work.InputChanges
abstract class IncrementalCopyTask extends DefaultTask {@InputDirectoryabstract DirectoryProperty getSourceDir()@OutputDirectoryabstract DirectoryProperty getTargetDir()@TaskActionvoid executeIncremental(InputChanges inputChanges) {inputChanges.getFileChanges(getSourceDir()).each { change ->switch (change.changeType.name()) {case "ADDED":case "MODIFIED":def targetFile = new File(getTargetDir().asFile, change.file.name + '.txt')change.file.copyTo(targetFile)breakcase "REMOVED":new File(getTargetDir().asFile, change.file.name + '.txt').delete()break}}}
}
在 build.gradle
的底部,注册这个任务:
tasks.register('incrementalCopy', IncrementalCopyTask) {sourceDir = file('src/main/resources')targetDir = file("$buildDir/output")
}
这样,我们就为 src/main/resources
目录中的文件定义了一个增量复制任务,输出目录是 build/output
。
11.4.2运行任务
为了测试这个任务,你可以首先在 src/main/resources
中创建一些文件,然后运行:
$ gradle incrementalCopy
你会看到这些文件被复制到 build/output
目录,并且它们的扩展名都被更改为 .txt
。
如果你再次运行该任务,不做任何改动,Gradle 会检测到没有任何变化,因此不会执行任何复制操作,这就是增量构建的威力。试试在 src/main/resources
中添加、修改或删除文件,然后再次运行任务。你会看到只有发生变化的文件才会被处理。这就是一个简单的增量构建示例。你可以在此基础上进一步扩展或修改来满足你的实际需求。
Gradle Wrapper的使用
12.1 什么是Gradle Wrapper?
Gradle Wrapper是一个工具,允许你在没有预先安装Gradle的情况下执行构建。这样做的好处是可以确保每个开发者和持续集成工具都使用相同版本的Gradle,避免了“在我的机器上可以运行”这样的问题。Wrapper由一个小的gradlew
(Unix系统)或gradlew.bat
(Windows系统)脚本和一些库文件组成。
12.2 为什么要使用Gradle Wrapper?
- 版本一致性:确保每个开发者和CI环境都使用相同的Gradle版本。
- 简化构建过程:开发者无需手动安装特定版本的Gradle。
- 灵活性:项目可以很容易地切换到新的Gradle版本,只需修改Wrapper配置即可。
12.3 如何设置Gradle Wrapper?
大部分通过gradle init
初始化的新项目默认就包含了Wrapper。但如果你的项目还没有Wrapper,可以很容易地添加:
$ gradle wrapper --gradle-version=7.2
这会为你的项目生成Wrapper脚本和相关配置。
12.4 如何使用Gradle Wrapper?
一旦你的项目配置了Wrapper,你应该使用Wrapper脚本来运行所有Gradle任务,而不是直接使用gradle
命令。例如:
在Unix或macOS上:
$ ./gradlew <task>
在Windows上:
> gradlew.bat <task>
如果你看到有人在项目的README或构建指南中推荐使用gradlew
而不是gradle
,这就是为什么。
12.5更新Gradle Wrapper的版本
随着Gradle的发展,你可能想要更新项目中的Gradle版本。使用Wrapper,这变得很容易。例如,要更新到Gradle 7.3,你可以运行:
$ ./gradlew wrapper --gradle-version=7.3
这会更新Wrapper使用的Gradle版本,并下载必要的文件。
总结
Gradle Wrapper是Gradle的一个强大特性,它确保了构建的一致性和简化了开发和CI环境的配置。为你的项目使用Wrapper是一个最佳实践,无论项目大小都推荐这样做。
参考文献
- 云原生—Gradle和Maven性能对比及技术选型 - 稀土掘金
- Gradle | Releases - 官方文档
- Gradle | Plugins - 官方文档
- Gradle 比 Maven 好为什么用的人少? - 知乎
- Gradle 快速入门
- Gradle 详细手册(从入门到入土) - 稀土掘金
- 如何使用Gradle管理多模块Java项目 - 知乎
- Android—Gradle教程(一) - 稀土掘金
- GradleUserGuide - GitHub
- Github Actions - GitHub
https://juejin.cn/post/7209178782657675319 ↩︎
相关文章:

工具篇 | Gradle入门与使用指南
介绍 1.1 什么是Gradle? Gradle是一个开源构建自动化工具,专为大型项目设计。它基于DSL(领域特定语言)编写,该语言是用Groovy编写的,使得构建脚本更加简洁和强大。Gradle不仅可以构建Java应用程序&#x…...

Wireshark TS | MQ 传输缓慢问题
问题背景 应用传输慢是一种比较常见的问题,慢在哪,为什么慢,有时候光从网络数据包分析方面很难回答的一清二楚,毕竟不同的技术方向专业性太强,全栈大佬只能仰望,而我们能做到的是在专注于自身的专业方向之…...

flink集群与资源@k8s源码分析-回顾
本章是分析系列最后一章,作为回顾,以运行架构图串联起所有分析场景 1 启动集群,部署集群(提交k8s),新建作业管理器组件 2 构建和启动flink master组件 3 提交作业,N/A...

学习心得09:C++新特性
现在语言越来越复杂,关键字也越来越多。所以我提出了关键字自动加标识的想法。 这些新特性也都是有用的,一般人也用不上。在这方面,我的主张是:除非你确实需要用到新特性,否则尽量不要用。保证了代码的可维护。 C很复杂…...

前端框架vBean admin
文章目录 引言I 数据库表设计1.1 用户表1.2 角色表1.3 菜单表II 接口引言 文档:https://doc.vvbin.cn/guide/introduction.html http://doc.vvbin.cn 仓库:https://github.com/vbenjs/vue-vben-admin git clone https://github.com/vbenjs/vue-vben-admin-doc 在线体验demo:…...
云原生周刊:Grafana Beyla 发布 | 2023.9.18
开源项目推荐 Komiser Komiser 是一个与云无关的开源资源管理器。它与多个云提供商(包括 AWS、Azure、Civo、Digital Ocean、OCI、Linode、腾讯和 Scaleway)集成,构建云资产库存,并帮助您在资源层面分解成本。 kr8s 这是一个用…...
C++ std::unique_lock 用法
文章目录 1.创建 std::unique_lock 对象2.自动加锁和解锁3.延迟加锁与手动加解锁4.尝试加锁5.配合条件变量使用6.小结参考文献 std::unique_lock 是 C11 提供的一个用于管理互斥锁的类,它提供了更灵活的锁管理功能,适用于各种多线程场景。 1.创建 std::u…...
Pytorch C++ 前端第二部分:输入、权重和偏差
本教程分为两部分 第 2.1 部分 – 基础知识速成课程。第 2.2 部分 – 使用 C++ 构建神经网络如果您已经了解神经网络的基础知识,那么无需阅读 Part-2.1 的内容,理解 Part-2.2 应该没有问题。我们试图通过动画 GIF 来可视化方程,从而使其简短而有趣。但请注意,我们根据在解释…...

面试题:RocketMQ 如何保证消息不丢失,如何保证消息不被重复消费?
文章目录 1、消息整体处理过程Producer发送消息阶段手段一:提供SYNC的发送消息方式,等待broker处理结果。手段二:发送消息如果失败或者超时,则重新发送。手段三:broker提供多master模式,即使某台broker宕机…...

uniapp打包安卓后在安卓屏上实现开机自启动
实现开机自启动(使用插件) 打开插件地址安卓开机自启动 Fvv-AutoStart - DCloud 插件市场 使用方法 选择你要开启自启动的项目 在项目的manifest.json中app-plus下写入以下代码 注意需要替换 android_package_name 为自己的,不然无法进行安卓apk打包 "nativePlugins&q…...
浅谈KNX总线智能照明控制系统在北京南站房中的应用
安科瑞 华楠 摘要:本文简要介绍了i-bus EIB/KNX智能建筑控制系统的基本原理及在北京南站房中的成功应用。阐述了这一系统强大的系统功能、灵活的控制方式节能效果。 关键词:i-bus智能建筑控制;控制系统;节能 1、工程概况 北京新…...
深入了解Java的核心库
掌握Java的核心库是成为一名优秀的Java开发者的关键。Java提供了丰富的核心库和API,包括集合框架、输入输出、多线程、异常处理等等。熟悉并掌握这些库的使用,可以提高编程效率和代码质量。在本文中,我们将深入讨论Java的核心库,并…...

嵌入式:驱动开发 Day9
作业:通过platform总线驱动实现 a.应用程序通过阻塞的io模型来读取number变量的值 b.number是内核驱动中的一个变量 c.number的值随着按键按下而改变(按键中断) 例如number0 按下按键number1 ,再次按下按键number0 d.在按下按键的时候需要同时…...

【ComfyUI】安装 之 window版
文章目录 序言步骤下载comfyUI配置大模型和vae下载依赖组件启动 生成图片解决办法 序言 由于stable diffusion web ui无法做到对流程进行控制,只是点击个生成按钮后,一切都交给AI来处理。但是用于生产生活是需要精细化对各个流程都要进行控制的。 故也…...

iMazing 2 .17.9最新官方中文版免费下载安装激活
iMazing 2 .17.9最新版是一款帮助用户管理IOS手机的应用程序,iMazing2最新版能力远超iTunes提供的终极的iOS设备管理器。IMazing与你的iOS设备(iPhone、 iPad或iPod)相连,使用起来非常的方便。作为苹果指定的iOS设备同步工具。 mazing什么意思 iMazing…...

Postman应用——Pre-request Script和Test Script脚本介绍
文章目录 Pre-request Script所在位置CollectionFolderRequest Test Script所在位置CollectionFolderRequest Pre-request Script(前置脚本):可以使用在Collection、Folder和Request中,并在Request请求之前执行,可用于…...

vue2中年份季度选择器(需要安装element)
调用 <!--父组件调用--><QuarterCom v-model"quart" clearable default-current/> 组件代码 <template><div><span style"margin-right: 10px">{{ label }}</span><markstyle"position:fixed;top:0;bottom:0…...

QT day5
数据库完成登入注册 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include<QDebug> #include<QPushButton> #include<QLineEdit> #include<QLabel> #include <QMainWindow> #include<QMessageBo…...

设计模式Java实战
文章目录 一、前置1.1 目的1.2 面向对象1.3 接口和抽象类 二、七大设计原则2.1 单一职责2.2 接口隔离原则2.3 依赖倒转原则2.4 里氏替换原则2.5 开闭原则2.6 不要重复原则2.7 迪米特最少知道法则 三、23种设计模式3.1创建型:创建对象3.1.1 单例模式定义最佳实践场景…...

外国固定资产管理系统功能有哪些
很多公司都在寻找提高自己资产管理效益的方法。为了满足这一要求,国外的固定资产管理系统已经发展成多种形式。以下是国外一些常见的固定资产管理系统的特点:自动化和智能化:许多现代固定资产管理系统采用自动化和数字化技术,以简化流程,减少…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...