当前位置: 首页 > news >正文

Flink DataStream API深度解析(Scala版):窗口计算、水位线与状态编程

在前面的文章中Flink 编程基础:Scala 版 DataStream API 入门-CSDN博客,我们已经介绍了 Flink 的 Datastream API 编程模型、窗口划分以及时间语义(处理时间、事件时间等)。本篇文章将深入讲解窗口计算的进阶内容,包括水位线(Watermark)、延迟数据处理(Late Data Handling)以及状态编程(State Programming)。通过手把手的示例,我们将逐步揭开这些概念的神秘面纱,帮助大家构建健壮的流处理应用程序。

目录

一、窗口计算

1.1 窗口分配器(Window Assig2ner)

滚动窗口(Tumbling Window)

滑动窗口(Sliding Window)

会话窗口(Session Window)

1.2 窗口计算函数

ReduceFunction(增量计算)

AggregateFunction(可控的增量计算)

ProcessWindowFunction(全量计算)

组合用法

1.3 触发器 Trigger

1.4 驱逐器 Evictor

二、水位线(Watermark)详解

三、延迟数据处理

3.1 allowedLateness:允许一定时间内迟到的数据

3.2 sideOutputLateData:输出极度迟到数据

四、状态编程

4.1 状态类型

4.2 示例:使用 ValueState

结语


一、窗口计算

在流式处理中,由于数据是无界的,我们需要对数据进行分组(按照时间或数量切分)来进行聚合计算。窗口计算(Window Computation)的主要思想是对数据按照一定规则进行划分,然后在每个窗口内执行计算操作,比如求和、求平均、计算最大最小值等。

Flink 中的窗口计算是流处理中的核心操作,用于将无限的数据流划分为有限的、可计算的块(窗口)。窗口计算的一般结构如下:

DataStream → keyBy() → window()/windowAssigner 
→ allowedLateness → trigger → evictor 
→ apply/reduce/aggregate → Sink

我们可以把窗口看作是给数据加上“时间范围”的过滤器,把连续流拆分成一个个小段,每段再单独进行聚合或统计处理。 

1.1 窗口分配器(Window Assig2ner)

窗口分配器负责告诉 Flink 如何将数据划分到一个个窗口中。主要有三种常见窗口类型: 

滚动窗口(Tumbling Window)

滚动窗口的特点是固定时间长度,并且窗口之间互不重叠。每个元素只属于一个窗口。

.window(TumblingEventTimeWindows.of(Time.seconds(10)))

上面的代码表示每 10 秒划分一个窗口,例如 [00:00:00, 00:00:10), [00:00:10, 00:00:20) 等。 

 

上图展示了 Flink DataStream API 的滚动窗口 机制:

时间轴(t0 至 t4)上严格划分出固定大小的连续窗口(窗口1至窗口4),每个窗口独立且不重叠,事件数据(●)根据时间戳归属到唯一对应的窗口中,适用于周期性的无重复聚合计算(如每5秒统计流量)。 

滑动窗口(Sliding Window)

滑动窗口支持窗口重叠。可以设定窗口大小和滑动步长。

.window(SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(5)))

 此处每 5 秒滑动一次,窗口长度为 10 秒,例如:

  • [00:00:00, 00:00:10)

  • [00:00:05, 00:00:15)

  • [00:00:10, 00:00:20)

此图展示了Flink DataStream API 中的滑动窗口机制。图中设定窗口大小为2,滑动步长为1 ,意味着每1个时间单位会计算最近2个时间单位的数据。通过窗口1([t0,t2] )、窗口2([t1,t3] )、窗口3([t2,t4] )的范围示意窗口滑动过程,重叠区域体现窗口重叠特性,表明存在重复计算数据的情况。

蓝色点:窗口 1 范围是 [t0,t2) ,它在这个区间内;窗口 2 范围是 [t1,t3] ,当时间走到 t1 ,窗口 2 开启,蓝色点所处时间也在窗口 2 的时间跨度里,所以它同时属于窗口 1 和窗口 2 。

 

绿色点:窗口 1 是左闭右开区间 [t0,t2) ,不包含 t2 ,绿色点虽在 t1 - t2 之间,但没到 t2 ,就不在窗口 1 里;而窗口 2 范围是 [t1,t3] ,把绿色点 “包” 进去了,所以绿色点只属于窗口 2 

会话窗口(Session Window)

会话窗口不是固定时间,而是基于事件之间的不活动间隔进行划分。

 .window(ProcessingTimeSessionWindows.withGap(Time.seconds(5)))

如果两个事件之间的时间间隔超过 5 秒,就会触发一个新窗口。

1.2 窗口计算函数

窗口划分好之后,我们就需要对每个窗口中的元素进行计算。这可以通过三种窗口函数实现:

ReduceFunction(增量计算)

适用于可以连续合并的数据,如求和、最大值等。

.reduce((v1, v2) => (v1._1, v1._2 + v2._2))

上面这个例子是对每个 key 的值进行累加。

AggregateFunction(可控的增量计算)

更复杂的增量计算方式,支持中间状态(Accumulator)。

class MyAgg extends AggregateFunction[(String, Int), Int, Int] {override def createAccumulator(): Int = 0override def add(value: (String, Int), acc: Int): Int = acc + value._2override def getResult(acc: Int): Int = accoverride def merge(acc1: Int, acc2: Int): Int = acc1 + acc2
}

ProcessWindowFunction(全量计算)

拥有更强大的上下文信息,可以访问窗口元数据和所有元素。

class MyWindowFunc extends ProcessWindowFunction[(String, Int), String, String, TimeWindow] {override def process(key: String, context: Context, elements: Iterable[(String, Int)], out: Collector[String]): Unit = {val sum = elements.map(_._2).sumout.collect(s"$key 窗口 [${context.window.getStart} - ${context.window.getEnd}] 总和: $sum")}
}

组合用法

可将增量计算与全量处理结合,效率更高:

.aggregate(new MyAgg, new MyWindowFunc)

1.3 触发器 Trigger

触发器决定何时执行窗口计算逻辑。默认是事件时间触发:

.trigger(CountTrigger.of(5))

表示每收到 5 条数据就触发一次计算。常用触发器类型:

  • EventTimeTrigger:基于水位线,默认类型。

  • ProcessingTimeTrigger:基于系统时间。

  • CountTrigger:基于数据条数。

  • 自定义 Trigger:继承 Trigger 类实现自定义逻辑。

1.4 驱逐器 Evictor

Evictor 控制在窗口计算之前剔除一部分元素,适用于对窗口中数据量进行限制。

.evictor(CountEvictor.of(3))

表示只保留最后 3 个元素进行窗口计算。


 

二、水位线(Watermark)详解

在处理事件时间窗口时,由于数据可能无序到达,需要用水位线机制来判断数据是否已经“齐全”。水位线是一种特殊的时间标记,用来指出目前事件时间的进度。当数据的事件时间超过水位线后,窗口操作就可以安全地触发计算。 

如何定义水位线

单调递增时间戳(适合有序数据):

data.assignAscendingTimestamps(_.timestamp)

有限乱序时间戳(容忍延迟):

data.assignTimestampsAndWatermarks(WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(5)).withTimestampAssigner(new SerializableTimestampAssigner[MyEvent] {override def extractTimestamp(element: MyEvent, recordTimestamp: Long): Long = element.timestamp}))

上面的策略会容忍最多 5 秒的乱序。 

示例:

import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks
import org.apache.flink.streaming.api.watermark.Watermarkclass MyTimestampExtractor extends AssignerWithPeriodicWatermarks[(String, Long)] {// 定义允许的最大乱序间隔(毫秒),比如 3 秒val maxOutOfOrderness = 3000Lvar currentMaxTimestamp: Long = _override def extractTimestamp(element: (String, Long), previousElementTimestamp: Long): Long = {val timestamp = element._2currentMaxTimestamp = Math.max(timestamp, currentMaxTimestamp)timestamp}override def getCurrentWatermark: Watermark = {// 当前水位线:当前最大时间戳减去乱序间隔new Watermark(currentMaxTimestamp - maxOutOfOrderness)}
}

讲解:

  1. 我们通过 maxOutOfOrderness 定义允许数据乱序的最大容忍时间。

  2. 每次取到元素时更新 currentMaxTimestamp,水位线则为 currentMaxTimestamp - maxOutOfOrderness

  3. 这样就可以确保,当事件时间超过水位线后,窗口内数据已经尽可能到齐,可以放心触发计算。

将上述时间戳提取器应用到数据流中: 

val timestampedStream = dataStream.assignTimestampsAndWatermarks(new MyTimestampExtractor)

三、延迟数据处理

在处理流数据时,迟到的数据是不可避免的。Flink 提供了三种策略来应对:

3.1 allowedLateness:允许一定时间内迟到的数据

.allowedLateness(Time.seconds(60))

这个设置告诉 Flink:即使窗口已经关闭,在接下来的 60 秒内到来的迟到数据依然会重新触发计算。

3.2 sideOutputLateData:输出极度迟到数据

.sideOutputLateData(lateOutputTag)

对于超过 allowedLateness 时间的极度迟到数据,我们可以将其发送到旁路输出流中,从而单独处理。


 

四、状态编程

Flink 强大的地方在于它是有状态的流处理框架。状态用于记录和保存处理过程中的中间结果。

4.1 状态类型

状态类型描述
ValueState保存单个值
ListState保存多个值(列表)
MapState保存键值对(K-V)
ReducingState自动合并的聚合状态
BroadcastState广播状态,所有子任务共享

4.2 示例:使用 ValueState

以下示例展示如何统计每个 key 的累加值:

class StatefulMapFunction extends RichMapFunction[(String, Int), (String, Int)] {private var countState: ValueState[Int] = _override def open(parameters: Configuration): Unit = {val desc = new ValueStateDescriptor[Int]("count", createTypeInformation[Int])countState = getRuntimeContext.getState(desc)}override def map(value: (String, Int)): (String, Int) = {val current = Option(countState.value()).getOrElse(0) + value._2countState.update(current)(value._1, current)}
}

使用状态时有两个要点:

  1. 必须在 keyBy 后使用状态,状态与 key 绑定。

  2. Flink 会自动进行状态的 checkpoint 和恢复。


 

结语

本文系统介绍了 Flink Scala 版 DataStream API 中窗口计算的各个组件、水位线与迟到数据处理机制,以及核心的状态编程能力。掌握这些内容后,将能够构建更加鲁棒、高性能的流处理程序。

如果这篇文章对你有所启发,期待你的点赞关注!

相关文章:

Flink DataStream API深度解析(Scala版):窗口计算、水位线与状态编程

在前面的文章中Flink 编程基础:Scala 版 DataStream API 入门-CSDN博客,我们已经介绍了 Flink 的 Datastream API 编程模型、窗口划分以及时间语义(处理时间、事件时间等)。本篇文章将深入讲解窗口计算的进阶内容,包括…...

【从零实现高并发内存池】内存池整体框架设计 及 thread cache实现

📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...

#MES系统中的一些相关的名词

📌MES系统 部分 术语表 缩写英文全称中文名称详细解释MESManufacturing Execution System制造执行系统用于连接计划系统与生产现场,实时管理和控制整个生产过程,覆盖物料、人员、设备、质量、指令等。ERPEnterprise Resource Planning企业资…...

《灵活的接口设计:如何支持多种后端数据存取实现》

《灵活的接口设计:如何支持多种后端数据存取实现》 一、引言:从单一适配到多样需求 在现代软件开发中,系统通常需要与不同的数据存储后端进行交互,例如关系型数据库(MySQL、PostgreSQL)、NoSQL 数据库(MongoDB、Redis)或文件存储(JSON、CSV)。为了增强系统的可扩展性…...

Spark-SQL核心编程(一)

一、Spark-SQL 基础概念 1.定义与起源:Spark SQL 是 Spark 用于结构化数据处理的模块,前身是 Shark。Shark 基于 Hive 开发,提升了 SQL-on-Hadoop 的性能,但因对 Hive 依赖过多限制了 Spark 发展,后被 SparkSQL 取代&…...

Qt:解决MSVC编译器下qDebug输出中文乱码的问题

问题描述: 使用msvc编译器,通过qDebug输出打印信息为乱码(显示问号或者乱码) 百度到以下方案,但是没有效果 最终解决: 在.pro文件中添加如下,重新构建运行即可显示中文内容 msvc:QMAKE_CXXFLAGS -exec…...

Go:接口

接口既约定 Go 语言中接口是抽象类型 ,与具体类型不同 ,不暴露数据布局、内部结构及基本操作 ,仅提供一些方法 ,拿到接口类型的值 ,只能知道它能做什么 ,即提供了哪些方法 。 func Fprintf(w io.Writer, …...

js | 网页上的 json 数据怎么保存到本地表格中?

1.思路 json 转为 csv 保存到本地或者:json 转为 html 显示到网页中,然后复制到excel中。 (2) 数据 wjl{"code":1,"data":[{"chrmiRNA":"chr1","0":"chr1","startmiRNA":&quo…...

智能Todo协作系统开发日志(二):架构优化与安全增强

📅 2025年4月14日 | 作者:Aphelios380 🌟 今日优化目标 在原Todo单机版基础上进行三大核心升级: 组件化架构改造 - 提升代码可维护性 本地数据加密存储 - 增强隐私安全性 无障碍访问支持 - 践行W3C标准 一、组件化架构改造 …...

buctoj_算法设计与分析(5)

问题 A: 没有上司的舞会 题目描述 Ural大学有N名职员,编号为1~N。 他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。 每个职员有一个快乐指数,用整数 HiHi 给出,其中 1≤i≤N。 现在要召开一场周年庆宴会&#x…...

VUE项目中的package.json中的启动脚本

"scripts": {"dev": "vite","build:prod": "vite build","build:stage": "vite build --mode staging","preview": "vite preview"}vite build 和 vite build --mode staging 是 V…...

目标追踪数据标注

在将 YOLO(目标检测) 和 DeepSORT(目标追踪) 结合时,数据标注需要同时满足 检测 和 追踪 的需求。以下是具体的分阶段标注策略和操作指南: 一、标注的核心要求 检测标注:每帧中目标的 边界框&a…...

详细介绍7大排序算法

1.排序的概念及其运用 1.1 排序的概念 排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记…...

TGCTF web

AAA偷渡阴平 这个题是一个非预期的无参RCE <?php$tgctf2025$_GET[tgctf2025];if(!preg_match("/0|1|[3-9]|\~|\|\|\#|\\$|\%|\^|\&|\*|\&#xff08;|\&#xff09;|\-|\|\|\{|\[|\]|\}|\:|\|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){//hi…...

RTPS数据包分析

DDS-RTPS 常见子消息_dds pdp消息-CSDN博客Fast RTPS原理与代码分析(3)&#xff1a;动态发现协议之端点发现协议EDP_fast-rtps 原理-CSDN博客 在RTPS&#xff08;Real-Time Publish-Subscribe&#xff0c;实时发布订阅&#xff09;协议中&#xff0c;DATA(r)和DATA是两种不同的…...

go语言gRPC使用流程

1. 安装工具和依赖 安装 Protocol Buffers 编译器 (protoc) 下载地址&#xff1a;https://github.com/protocolbuffers/protobuf/releases 使用说明&#xff1a;https://protobuf.dev/ 【centos环境】yum方式安装&#xff1a;protoc[rootlocalhost demo-first]# yum install …...

回溯算法的要点

可以用树结构&#xff08;解空间树&#xff09;来表示用回溯法解决的问题的所有选项。 叶节点则对应着最终的状态. 回溯过程&#xff1a;深度遍历&#xff0c;在任意时刻&#xff0c;算法只保存从根结点到当前结点的路径。 “剪枝”&#xff1a;当某一节点不包含问题的解&am…...

爬虫: 一文掌握 pycurl 的详细使用(更接近底层,性能更高)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、PycURL概述1.1 PycURL介绍1.2 基本安装1.3 安装依赖(Linux/macOS)1.4 常用选项参考二、基本使用2.1 简单 GET 请求2.2 获取响应信息2.3 设置请求头2.4 超时设置2.5 跟随重定向三、高级功能3.1 POST 请求3.2 文件上…...

大模型文生图

提示词分4个部分&#xff1a;质量&#xff0c;主体&#xff0c;元素&#xff0c;风格 质量&#xff1a;杰作&#xff0c;高质量&#xff0c;超细节&#xff0c;完美的精度&#xff0c;高分辨率&#xff0c;大师级的&#xff1b; 权重&#xff1a;把图片加括号&#xff0c;&am…...

c# AI编程助手 — Fitten Code

前言 前有Copilot各种酷炫操作&#xff0c;今有国产软件杀出重围。给大家介绍的是一款国内的国产编程神器&#xff0c;可与微软GitHub Copilot比比身手。关键它还是完全免费。它就是&#xff1a;非十团队国产自主研发的Fitten Code。此工具的速度是GitHub Copilot的两倍&#x…...

《植物大战僵尸融合版v2.4.1》,塔防与创新融合的完美碰撞

《植物大战僵尸融合版》是基于经典塔防游戏《植物大战僵尸》的创意同人改版&#xff0c;由“蓝飘飘fly”等开发者主导制作。它在保留原版核心玩法的基础上&#xff0c;引入了独特的植物融合机制&#xff0c;玩家可以将不同的植物进行组合&#xff0c;创造出全新的植物种类&…...

深度学习总结(12)

层:深度学习的基础模块 神经网络的基本数据结构是层。层是一个数据处理模块&#xff0c;它接收一个或多个张量作为输入&#xff0c;并输出一个或多个张量。有些层是无状态的&#xff0c;但大多数层具有状态&#xff0c;即层的权重。权重是利用随机梯度下降学到的一个或多个张量…...

pyqt环境配置

文章目录 1 概述2 PyQt6和PySide6区别3 环境配置4 配置PySide65 配置PyQt66 配置外部工具7 添加模板8 使用pyside6-project构建工程9 常见错误10 相关地址 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发 &#x1f448;&#x1f449;python开发 &#x1…...

YOLO11改进——融合BAM注意力机制增强图像分类与目标检测能力

深度学习在计算机视觉领域的应用取得了显著进展&#xff0c;尤其是在目标检测&#xff08;Object Detection&#xff09;和图像分类&#xff08;Image Classification&#xff09;任务中。YOLO&#xff08;You Only Look Once&#xff09;系列算法凭借其高效的单阶段检测框架和…...

考研单词笔记 2025.04.14

amount n数量&#xff0c;数额v&#xff08;数量&#xff09;达到&#xff0c;总计&#xff08;to&#xff09;&#xff0c;意味着&#xff0c;相当于 couple n一对&#xff0c;一双&#xff0c;一些&#xff0c;几个&#xff0c;夫妻&#xff0c;情侣v连接&#xff0c;结合 …...

AI云游戏盒子:未来娱乐的新纪元

AI云游戏盒子&#xff1a;未来娱乐的新纪元 随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;与云计算技术的结合正在重新定义我们享受数字娱乐的方式。2025年&#xff0c;一款名为“AI云游戏盒子”的产品正逐渐成为家庭娱乐的核心设备&#xff0c;它不仅集…...

第八章 文件操作

第八章 文件操作 文章目录 第八章 文件操作1 文件读取1 将文件整个读取内存2 按字节读取文件 1 文件读取 1 将文件整个读取内存 类似于python的 with open(filename, modert, encodingutf-8) as f:res f.read()go中的书写方式&#xff1a; 方式一&#xff1a; package ma…...

《extern:如何在编译时“暗通款曲“》

C中extern关键字的完整用法总结 extern是C中管理链接性&#xff08;linkage&#xff09;的重要关键字&#xff0c;主要用于声明外部定义的变量或函数。以下是详细的用法分类和完整示例&#xff1a; 一、基本用法 1. 声明外部全局变量 // globals.cpp int g_globalVar 42; …...

活动图与流程图的区别与联系:深入理解两种建模工具

目录 前言1. 活动图概述1.1 活动图的定义1.2 活动图的基本构成要素1.3 活动图的应用场景 2. 流程图概述2.1 流程图的定义2.2 流程图的基本构成要素2.3 流程图的应用场景 3. 活动图与流程图的联系4. 活动图与流程图的区别4.1 所属体系不同4.2 表达能力差异4.3 使用目的与语境4.4…...

FinanceRAG获奖方案解读:ACM-ICAIF ’24的FinanceRAG挑战赛

ACM-ICAIF 24 FinanceRAG Challenge提供一套整合的文本和表格财务数据集。这些数据集旨在测试系统检索和推理财务数据的能力。参与者将受益于 Github 上的基线示例和官方提交代码&#xff0c;其位于FinanceRAG&#xff0c;以及在 huggingface 上的简化的数据集访问&#xff0c;…...

Linux LED驱动(gpio子系统)

0. gpio子系统 gpio子系统是linux内核当中用于管理GPIO资源的一套系统&#xff0c;它提供了很多GPIO相关的API接口&#xff0c;驱动程序中使用GPIO之前需要向gpio子系统申请。 gpio子系统的主要目的就是方便驱动开发者使用gpio&#xff0c;驱动开发者在设备树中添加gpio相关信息…...

场外期权交易和结算方式的区别是什么?

场外期权交易的核心在于双方协商一致的合约条款。这些条款包括但不限于期权的类型&#xff08;看涨或看跌&#xff09;、执行价格、到期日、合约规模以及支付的期权费。由于每份合约都是独一无二的&#xff0c;因此交易双方需要具备高度的专业知识和谈判技巧&#xff0c;下文为…...

自注意力的机制内涵和设计逻辑

在自注意力机制中&#xff0c;查询&#xff08;Q&#xff09;、键&#xff08;K&#xff09;和值&#xff08;V&#xff09;的交互过程是核心设计&#xff0c;其背后的数学和语义内涵可以从以下角度理解&#xff1a; 1. 数学视角&#xff1a;动态加权聚合 自注意力机制的公式可…...

VIM学习笔记

1. ex模式 vim中&#xff0c;按&#xff1a;触发的命令行模式&#xff0c;称为 ex模式&#xff0c;具体命令参见如下笔记&#xff1a; https://blog.csdn.net/u010250151/article/details/51868751?ops_request_misc%257B%2522request%255Fid%2522%253A%2522814b671a9898c95…...

Windows系统docker desktop安装(学习记录)

目前在学习docker&#xff0c;在网上扒了很多老师的教程&#xff0c;终于装好了&#xff0c;于是决定再装一遍做个记录&#xff0c;省的以后再这么麻烦 一&#xff1a;什么是docker Docker 是一个开源的应用容器引擎&#xff0c;它可以让开发者打包他们的应用以及依赖包到一个…...

操作系统学习笔记——[特殊字符]超详细 | 如何唤醒被阻塞的 socket 线程?线程阻塞原理、线程池、fork/vfork彻底讲明白!

&#x1f4a1;超详细 | 如何唤醒被阻塞的 socket 线程&#xff1f;线程阻塞原理、线程池、fork/vfork彻底讲明白&#xff01; 一、什么是阻塞&#xff1f;为什么线程会阻塞&#xff1f;二、socket线程被阻塞的典型场景&#x1f9e0; 解法思路&#xff1a; 三、线程的几种阻塞状…...

GIC驱动程序对中断的处理流程

承接上一篇&#xff0c;我们来讲讲GIC的处理流程&#xff1a; 我们先来看看老版本的CPU是怎么去处理中断的&#xff1a; 这种的话&#xff0c;基本上就是一开始就确定你有多少个中断&#xff0c;就为你分配好了多少个irq_desc&#xff0c;这样子每一个硬件中断&#xff0c;也就…...

罗庚机器人:机器人打磨领域的先行者

近日&#xff0c;记者在广东罗庚机器人有限公司&#xff08;以下简称罗庚机器人&#xff09;总经理蒲小平处了解到&#xff0c;该公司是一家研发与为客户提供高精度自适应机器人打磨抛光集成工艺的高科技企业&#xff0c;是机器人打磨领域的先行者。在国内外机器人打磨抛光应用…...

如何在 Java 中对 PDF 文件进行数字签名(教程)

Java 本身并不原生支持 PDF 文件&#xff0c;因此若要对 PDF 进行数字签名&#xff0c;您需要使用一些专用的软件。本教程将演示如何使用 JPedal PDF 库来对 PDF 文件进行数字签名。 步骤&#xff1a; • 下载 JPedal 并将 Jar 文件添加到项目中 • 创建一个 PKCS#12 密…...

一文了解:北斗短报文终端是什么,有哪些应用场景?

在通信技术飞速发展的今天&#xff0c;人们已习惯于依赖地面基站和互联网实现即时通信。然而&#xff0c;当自然灾害突发、远洋航行遇险或深入无人区勘探时&#xff0c;传统通信手段往往失效。北斗短报文终端——这一由中国自主研发的卫星通信技术&#xff0c;正以“无网络通信…...

【KWDB创作者计划】_KWDB应用之实战案例

【KWDB 2025 创作者计划】_KWDB应用之实战案例 本文是在完成KWDB数据库安装的情况下的操作篇&#xff0c;关于KWDB的介绍与安装部署&#xff0c;可以查看上一篇博客: https://blog.itpub.net/70045384/viewspace-3081187/ https://blog.csdn.net/m0_38139250/article/details/…...

JavaScript中的运算符与语句:深入理解编程的基础构建块

# JavaScript中的运算符与语句&#xff1a;深入理解编程的基础构建块 在JavaScript编程的世界里&#xff0c;运算符和语句就像是构建大厦的基石&#xff0c;它们是编写高效、灵活代码的基础。今天&#xff0c;我们就来深入了解一下这些重要的元素。 ## 一、运算符&#xff1a;…...

MySQL——学习InnoDB(1)

MySQL——学习InnoDB&#xff08;1&#xff09; 文章目录 MySQL——学习InnoDB&#xff08;1&#xff09;1. InnoDB的前世今生1.1 诞生发展1.2 核心设计1.3 关键进化 2. InnoDB和MyISAM在性能和安全上的区别2.1 性能对比2.2 安全对比 3. InnoDB架构图&#xff08;内存结构磁盘结…...

QT中多线程写法

转自个人博客&#xff1a;QT中多线程写法 1. QThread及moveToThread() 使用情况&#xff1a; 多使用于需要将有着复杂逻辑或需要一直占用并运行的类放入子线程中执行的情况&#xff0c;moveToThread是将整个类的对象移入子线程。 优缺点&#xff1a; 优点&#xff1a;更符合…...

css 二维码始终显示在按钮的正下方,并且根据不同的屏幕分辨率自动调整位置

一、需求 “求职入口” 下面的浮窗位置在其正下方&#xff0c;并且浏览器分辨的改变&#xff08;拖动浏览器&#xff09;&#xff0c;位置依旧在最下方 二、实现 <div class"btn_box"><div class"btn_link id"js-apply">求职入口<di…...

STM32 认识STM32

目录 什么是嵌入式&#xff1f; 认识STM32单片机 开发环境安装 安装开发环境 开发板资源介绍 单片机开发模式 创建工程的方式 烧录STM32程序 什么是嵌入式&#xff1f; 1.智能手环项目 主要功能有&#xff1a; 彩色触摸屏 显示时间 健康信息&#xff1a;心率&#…...

关于 CSDN的C知道功能模块 的详细解析,包括 新增的AI搜索(可选深度思考) 和 智能体功能 的具体说明及对比分析

以下是关于 CSDN的C知道功能模块 的详细解析&#xff0c;包括 新增的AI搜索&#xff08;可选深度思考&#xff09; 和 智能体功能 的具体说明及对比分析&#xff1a; 一、C知道核心功能模块详解&#xff08;基础功能&#xff09; &#xff08;参考前文内容&#xff0c;此处略…...

Vue--组件练习案例

图片轮播案例&#xff1a; <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>Title</title></head><body><!--轮播图片--><div id"app"><h1>轮播图</h1…...

Sentinel源码—1.使用演示和简介一

大纲 1.Sentinel流量治理框架简介 2.Sentinel源码编译及Demo演示 3.Dashboard功能介绍 4.流控规则使用演示 5.熔断规则使用演示 6.热点规则使用演示 7.授权规则使用演示 8.系统规则使用演示 9.集群流控使用演示 1.Sentinel流量治理框架简介 (1)与Sentinel相关的问题 …...

空间信息可视化——WebGIS前端实例(二)

技术栈&#xff1a;原生HTML 源代码&#xff1a;CUGLin/WebGIS: This is a project of Spatial information visualization 5 水质情况实时监测预警系统 5.1 系统设计思想 水安全是涉及国家长治久安的大事。多年来&#xff0c;为相应国家战略&#xff0c;诸多地理信息领域的…...