江科大/江协科技 STM32学习笔记P13

文章目录 TIM定时中断1、TIM简介计数器PSC预分频器(Prescaler)ARR自动重装寄存器(Auto Reload Register) 2、定时器类型基本定时器主模式触发DAC 通用定时器高级定时器 3、定时器原理定时中断基本结构预分频器时序计数器时序RCC时钟树 TIM定时中断 1、TIM简介 定时器的基准时钟一般都是主频72MHz,如果对72MHz计72个数,就是1us的时间,如果计72000个数就是1ms的时间。 计数器 就是执行计数定时的一个寄存器,每来一个时钟计数器加一 PSC预分频器(Prescaler) 对计数器的时钟进行分频,让计数更灵活 ARR自动重装寄存器(Auto Reload Register) 计数的目标值,就是想要计多少个时钟申请中断 2、定时器类型 基本定时器 基本定时器只能选内部时钟,通向时基单元的计数基准频率一般是与系统的主频72MHz有关的72M,到预分配器这里,如果寄存器写0就是不分频,写1就是2分频,输出频率=输入频率/2=36MHz,以此类推,即实际分频系数=预分频器的值+1。然后到了计数器,计数器可以对预分频后的计数时钟进行计数,计数器的值会在计时过程中不断的自增运行,当到目标值时,产生中断,完成了定时的任务。ARR自动重装寄存器存的就是计数目标,当计数值等于自动重装值时,计时时间到了,产生一个中断信号并且清零计数器,计数器自动开始下一次的计数计时,这种计数值等于自动重装值产生的中断,一般叫“更新中断”,这个更新中断结束后会通往NVIC,再配置好NVIC的定时器通道,定时器的更新中断就能得到CPU响应。向上的折线箭头代表产生中断,向下的箭头代表产生一个事件,这里对应的事件叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作。 主模式触发DAC 在使用DAC时,可能会用DAC输出一段波形,那就需要每隔一段时间触发一次DAC,让他输出下一个电压点。如果用正常思路来实现,先设置一个定时器产生中断,每隔一段时间在中断程序中调用代码手动触发一次DAC转换,然后DAC输出,这样会使主程序处于频繁被中断的状态,影响主程序的运行和其他中断的响应,所以定时器设计了一个主模式,使用主模式可以把定时器的更新事件映射到触发输出TRGO的位置,然后TRGO直接接到DAC的触发转换引脚上,这样定时器的更新就不需要通过中断来触发DAC转换了 通用定时器 通用定时器和高级定时器除了向上计数模式外,还支持向下计数模式和中央对齐模式。向下计数模式就是从重装值开始向下自减,减到0之后回到重装值同时申请中断,然后下一轮。中央对齐模式就是先向上自增到重装值,申请中断,然后再向下自减减到0,申请中断,然后下一轮。 图上面是内外时钟源选择和主从触发模式的结构。先看内外时钟源选择,第一个外部时钟是来自TIMx_ETR引脚上的外部时钟,ETR引脚的位置如下图复用到了PA0。 即在PA0上接一个外部方波时钟,然后配置内部的极性选择、边沿检测和预分频器电路,再配置一下输入滤波电路,这些电路对外部时钟进行一定的整形,因为是外部引脚的时钟,这些电路对输入的波形进行滤波,滤波后的信号上面一路ETRF进入触发控制器,紧跟着可选择作为时基单元的时钟了,如果想在ETR外部引脚提供时钟,或者想对ETR时钟进行计数,把这个定时器当计数器来用的话,那就可以配置这一路的电路,在STM32中这一路也叫外部时钟模式2。 下面一路TRGI,主要用作触发输入来使用,可以触发定时器的从模式。本节讲触发输入作为外部时钟来使用的情况,暂且把TRGI当做外部时钟的输入来看,这种情况这一路叫“外部时钟模式1”,通过这一路的外部时钟,第一个是ETR引脚的信号,ETR引脚既可以通过上面一路当时钟,又可以通过下面一路当时钟,下面一路输入会占用触发输入的通道。第二种就是ITR信号,这一部分的时钟信号来自其他定时器,从右边可以看出这个主模式的输出TRGO可以通向其他定时器,接到其他定时器的ITR引脚,这里ITR0到ITR3分别来自其他四个定时器的TRGO输出,实现定时器级联的功能,比如可以先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,接着再初始化TIM2,选ITR2,对应TIM3的TRGO,后面选择时钟为外部模式1,这样TIM3的更新事件就可以驱动TIM2的时基单元,实现定时器的级联。第三种是CH1引脚的边沿,也就是从CH1引脚获得时钟,带ED就是边沿的意思,上升沿和下降沿均有效。第四种,CH1引脚和CH2引脚,通过TI1FP1和TI2FP2获得,TI1FP1连接到CH1引脚的时钟。 下面部分主要包含两块电路,右边是输出比较电路,四个通道对应CH1-4,可以用于输出PWM波形,驱动电机,左边这一块是输入捕获电路,四个通道,可以用于测量输入方波的频率等。中间的寄存器是捕获/比较寄存器,是输入捕获和输出比较电路共用的,因为输入捕获和输出比较不能同时使用,所以共用。 高级定时器 在申请中断的地方增加了一个重复次数计数器,右上,有了这个计数器之后,就可以实现每隔几个计数周期才发生一次更新事件和更新中断,相当于对输出的更新信号又做了一次分频。 DTG是死区生成电路,右边的输出引脚由原来的一个变为了两个互补的输出,可以输出一对互补的PWM波,这些电路是为了驱动三相无刷电机,因为三相无刷电机的驱动需要三个桥臂,每个桥臂2个大功率开关管来控制,总共需要6个大功率开关管来控制,所以输出的PWM引脚的前三路就变为互补的输出,另外为了防止互补输出的PWM驱动桥臂时,在开关切换的瞬间由于器件不理想造成短暂的直通现象,所以前面加上死区生成电路,在开关切换的瞬间产生一定时长的死区,让桥臂的上下管全都关断,防止直通现象。 最后是刹车输入的功能,在左下,是为了给电机驱动提供安全保障,如果外部引脚BKIN产生了刹车信号或者内部时钟失效,产生了故障,那么控制电路就会自动切断电机的输出,防止意外发生。 3、定时器原理 定时中断基本结构 中断输出控制就是一个中断输出的允许位,如果需要某个中断,就允许一下。 预分频器时序 CK_PSC是预分频器的输入时钟,选内部时钟时一般是72MHz,CNT_EN是计数器使能,高电平计数器正常运行,低电平计数器停止,CK_CNT是计数器时钟,即是预分频器时钟输出也是计数器的时钟输入,开始时计数器未使能,计数器时钟不运行,使能后,前半段预分频器系数从0变1,计数器的时钟等于预分频器前的时钟,后半段,预分频器系数从1变2,计数器的时钟也变为预分频器前时钟的一半,在计数器时钟的驱动下,下面的计数器寄存器也跟随时钟的上升沿不断自增,在中间FC之后计数值变为0,可推断重装值就是FC。 下三行描述的是预分频器的一种缓冲机制,在某时刻把预分配控制寄存器由0改1,如果在此时此刻改变时钟的分频系数,就会导致一个计数周期内前后频率不一样,所以设计预分配缓冲器,变化不会立刻生效,而是等本次计数周期结束后,产生了更新事件,预分频器的值才会被传递到缓冲寄存器里生效。最后一行描述预分配器内部实际上也是依靠计数来分频,当预分频值为0时,计数器就一直为0,直接输出原频率,当预分频值为1时,计数器0、1、0、1计数,在回到0时输出一个脉冲,这样输出频率就是输入频率的2分频,预分频的值和实际的分频系数之间有一个数的偏移。 计数器时序 计数器在每个上升沿自增,当计到0036后,再来一个上升沿计数器清零,产生一个更新事件脉冲,另外更新中断标志位UIF只要置1就会申请中断,中断响应后需要在中断程序中手动清零。 计数器也有缓存寄存器,可以自己设置用还是不用,如下两图 ARPE为0,不使用影子寄存器,自动加载寄存器FF改到36立刻生效,所以计到36后直接更新开始下一轮计数 有预装时,F5变36,影子寄存器控制还是F5,计到F5产生更新事件,同时要更改的36才被传到影子寄存器,在下一个计数周期生效,所以引入影子寄存器是为了同步,让值的变化和更新事件同步发生,防止运行途中更改造成错误 RCC时钟树 左边的时钟产生电路有四个震荡源,分别是内部的8MHz高速RC振荡器,外部的4到16MHz高速石英晶体振荡器,一般为8MHz,外部的32.768KHz低速晶振,一般给RTC提供时钟,最后是内部的40KHz低速RC振荡器,可以给看门狗提供时钟,上面两个高速晶振给系统提供时钟,AHB、APB1、APB2时钟都来源于这俩个高速晶振,外部的石英振荡器比内部RC振荡器更稳定。 在SystemInit函数里,ST首先启动内部时钟,以内部8MHz为系统时钟,然后再启动外部时钟,配置外部时钟进入PLL锁相环进行倍频,8MHz倍频9倍,得到72MHz,等锁相环输出稳定后选择锁相环输出为系统时钟。CSS是时钟安全系统,一旦外部时钟失效,自动把外部时钟切回内部时钟,保证系统时钟的运行,防止程序卡死,在高级定时器的刹车输入这里一旦CSS检测到外部时钟失效,通过或门立刻让输出控制的电机停止防止意外。 右图这些时钟输出都有一个与门进行输出控制,控制位写的是外部时钟使能,我们在程序中写RCC_APB2/1 PeriphClockCmd就是作用在这。

PDF解析,还能做得更好

随着大模型文档智能应用逐渐步入正轨,文档解析类产品成为其中重要的一环。 文档解析工具能够“唤醒”沉睡在PDF文件中的知识,将其转化为机器能够识别、读取的信息,将可用数据从txt、csv格式扩展到大批量的电子档、扫描档文件,为数据处理、大模型训练、RAG系统开发提供优质的“燃料”。 近期,文档解析的赛道越发火热,大量企业、开发者入局,为AI应用者提供更多可选产品。最近我们也在文章《以后再也不用肉眼测评解析产品了》(+link)中探讨了面对多种选项,我们应如何挑选适合自己业务场景的产品。 然而,作为解析产品的开发者之一,我们认为:PDF解析,还能做得更好,为用户提供更可靠、优质的服务。 今天,我们将从开发者的视角,与大家分享目前解析产品能进一步提升的一些不足之处,也欢迎大家在评论区分享使用感受、提出指正意见。 在与大模型应用接轨的解析领域,开发人员与用户是并肩作战的开拓者,所有意见对我们而言都至关重要! 使用过Markdown Tester的朋友可能已经注意到,目前测评的国内外几款相对主流解析产品,包括GPT-4o,都还称不上是“六边形战士”。 其中颇为薄弱的一项,就是公式。 而准确的公式识别在许多场景下,都显得相当重要。 当我们需要处理技术类论文、专业书籍时,复杂公式是绕不开的重难点。在涉及大量教科书、教辅、试卷的教育应用场景下情况同样如此。在OCR与文档解析工具得到普遍使用之前,公式的手动输入和校对需要消耗许多人力成本,而公式的多变大小及版式也给机器识别造成了挑战。 以下图为例—— 尽管公式中大部分信息被正确识别,在指数方面,解析工具反馈的结果仍有误差。这也是目前教育类应用的用户朋友仍需手动调整的原因。 对于复杂公式的训练提升,是我们重视的优化方向之一。 在财经、学术、企业知识库等各类RAG场景下,比公式出镜率更高的,就是此前我们已经介绍过的表格识别《聊聊文档解析测评里的表格指标》(+link)。如下图案例所显示,表格形式的复杂性、多样性无法穷举,面对无线表、合并单元格、不规则行距、跨段、跨页等难题,表格识别的加强是文档解析类产品的长期命题。 针对RAG,TextIn团队还在关注一个提及率不算特别高的问题:标题检测与目录树。在RAG系统开发过程中,面对长文档切片的需要,业内已形成普遍共识: 如果文档有清晰准确的标题及层级,即可改换按长度分chunk的传统方式,而是利用子标题、段落做基于语义理解的分片。这有利于提升系统后续的检索召回能力,以及问答任务中总体的回复表现。 目前,在文档解析过程中,由于不同类型的长文档标题格式各异,同时部分标题在语义上相对模糊,要准确、稳定地完成一级、二级、三级与其他子标题的识别仍属难点。以TextIn团队在开发中处理的实际场景为例,对年报、财报、研报等类型文件,标题层级识别与目录树建构已经能达到较好的效果,但在解析格式一致性更弱的文档类型时,表现还需要进一步优化。对解析来说,尝试如实还原各层级标题是一项较为困难、但对下游工作助益相当大的工作。因此,文档目录树的识别是我们关注的解析重点之一,欢迎对此有较高精度需求的用户随时与我们探讨应用场景,试用最新版的解析效果! 最后,我们也想与大家分享一个我们接到的吐槽——文档解析产品的API使用专业性要求太高!尤其在JSON结构的Detail参数方面,例如,现在当我们在参数中读取某一元素的位置,得到的结果为: 坐标数组[283,96,343,96,343,116,283,116] 数组的实际理解方式是:在象限内,以左下坐标为起点的顺时针坐标位置。 但显然,它与“直观简单”相去甚远。 接下来,我们会不断以用户体验为中心,进行输出优化,争取让JSON坐标数组这种类型的“槽点”不再成为我们用户的困扰。 LLM时代,我们需要更多优质的语料。AI相关行业的小伙伴基本上都认同,我们“喂”给大模型的语料质量,决定了大模型反馈给我们的回答质量。 所以,尽管在这一年中,PDF解析工作同样进度条发展迅速,我们仍然认为:解析还能做得更好! 今天我们分享了一些当前的重难点与优化方向,欢迎各位开发者随时向我们提出其他需求,与我们共同交流当下的需求~ TextIn文档解析产品目前正在内测计划中,可持续关注我们公众好 合研社 ,申领内测福利立刻试用文档解析! 关于测评工具、产品或需求,都可以找我们沟通。我们欢迎所有探讨和交流!

移动云数据库积极拥抱“云原生”

当前,云计算席卷数据库市场,云技术正加速数据库产业革新。为了充分享受云计算的价值,解决数据库性能和成本问题,数据库架构不断与云架构融合,云原生数据库日渐成为云厂商和各类数据库厂商的重要赛道。 云原生数据库当前并无标准定义,但应具备四大核心特征,按照云原生纵深演进,分别为:容器化部署、存算分离、Serverless、算力网络。其中,容器化部署和K8s编排是云原生的事实标准;存算分离是云原生数据库的主要架构;Serverless是云原生数据库的供给新模式;算力网络是云原生数据库的新方向。 在“云原生”的浪潮中,移动云积极展开云原生数据库实践。移动云基于K8s构建云原生数据库底座,全线产品达云原生L1级。其中,云原生数据库整体技术架构包含内核云原生和平台云原生,分别进行深入耦合和重构和共性能力统一建设。此外,移动云自研数据库系列产品,采用存算分离架构,并全面向Serverless演进。在PostgreSQL版中,做到持续深化云原生,实现“混动”架构兼容存算一体;在数仓版中,培育了Serverless化的数据导入能力,全量同步达20w/s,增量同步达5w/s,并降低整体资源成本约30%。在中国移动算力网络战略下,移动云正大力探索算力网络数据库,积极推进相关技术以及行业标准制定。 移动云始终坚持核心自研,并广泛与合作伙伴开展联合研发,提供关系型、分析型、非关系型以及数据库生态工具在内的一站式云原生产品和服务。目前,移动云现已形成“2+7”行业推广模式,赋能5000+政企用户,在中国移动内外取得良好的应用效果和社会反响。 未来,移动云算力网络数据库将实现“算力网络”+“云原生数据库”,即无需关注地域,全域实现Regionless & Serverless,数据访问与处理就近接入,多云、多云数据算力统一纳管;无需关注资源,即依托算网大脑实现全网资源弹性供给,全域实现数据流通与治理、数据交换与交易;无需关注业务负载,即不用考虑数据库负载和选型等,提交数据任务,交由算力网络数据库一个入口统一处理。 云原生数据库将不仅仅是一项技术革新,更是一种全新的数据管理和服务模式。移动云作为云计算国家队、主力军,积极投身云原生数据库实践,为推动数字化转型和智能化升级,为构建更加开放、互联和智能的世界贡献力量。

接了一个2000块的小活,大家进来看看值不值,附源码

如题,上周的一天,朋友圈的一个旧友找到了我,说让我帮他开发一个小工具,虽然活不大,但没个几年的全栈经验还不一定能接下来,因为麻雀虽小,涉及的内容可不少: 需求分析 原型设计 详细设计 架构选型 接口设计 数据库设计 后端开发 前端开发 服务器购买 服务器配置 镜像构建 服务调试 服务部署测试 优化迭代 交付收款 如果你对上述流程感兴趣,可以继续看下去,关注公&号:新质程序猿,回复:api-mark 可以获取源码包。 废话不多说,开整吧! 需求分析 用户故事如下,我大概评估了一下需要 1-2 个工作日,就要个 2000 块吧。 总结一下就是: 支持批量上传(添加)一批接口数据 提供获取接口,每次获取一条数据以供他自己的使用 提供标记接口,他使用完会标记这条数据的状态(1成功,2老号,3异常) 提供删除接口(多条件) 支持查询导出(多条件) 数据格式大概是这样的: 61057944----http://xxx/api/getcode?token=e49debc93 61057945----http://xxx/api/getcode?token=e49deb333 原型设计 看起来好像蛮简单哈~~,我随即画了一个 原型图 给他。 得到确认后,就开整吧。 注:原型设计采用的是 Axure RP 9 + ElementUI,如有需要也可以公&号留言。 详细设计 需求分析只是大概对需求进行了梳理,在进行开发之前,还需要进行深入详细的设计才能评估出工作量。 我们来拆解一下这个项目。 架构选型 首先要明确项目各关键点所采用的架构选型,如服务器怎么选,前后端框架怎么选,如何部署,安全标准,性能要求等等,这些都会影响到架构选型。 对于这个项目来说,单机足够,没啥安全要求,一句话就是够简单,无压力开整。 服务器:centos 7.9 4c8g 200g 足够 数据库:mysql 5.7+(部署使用的 mysql 8) 后端:springboot + jpa 够用 前端:vue + vue-admin-template 快速开发框架 部署:docker + docker-compose 方便快捷

Java语言程序设计——篇十一(1)

🌿🌿🌿跟随博主脚步,从这里开始→博主主页🌿🌿🌿 欢迎大家:这里是CSDN,我的学习笔记、总结知识的地方,喜欢的话请三连,有问题可以私信🌳🌳🌳 您的点赞、关注、收藏、评论、私信是我最大的支持与鼓舞!!!🌻🌻🌻 泛型 泛型类型实战演练实战演练 泛型方法实战演练 通配符(?)的使用实战演练 有界类型参数实战演练 继承泛型类与实现泛型接口🐱综合练习 泛型类型 泛型其实质就是将数据的类型参数化,通过为类、接口及方法设置类型参数来定义泛型。泛型使一个类或一个方法可在不同类型的对象上进行操作。泛型所操作的数据类型被指定为一个参数,这个参数被称为类型参数(type parameters)。泛型类的定义是在类名后面加上,泛型接口的定义是在接口名后面加上,而泛型方法的定义是在方法的返回值前面加上,其头部定义分别如下: 泛型类的定义:[修饰符] class 类名<T> 泛型接口的定义:[public] interface 接口名<T> 泛型方法的定义:[public][static] <T> 返回值类型 方法名(T 参数) a、类型参数名使用单个大写字母表示。 b、常用的类型参数名有:E(表示元素)、K(表示键)、N(表示数)、T(表示类型)、V(表示值) c、在类和接口的声明中,可以有多个类型参数,但每个参数必须是唯一的。 实战演练 例:泛型类Node public class Node<T> { private T data; public Node() {} public Node(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } public void showType() { System.out.println(" T的类型是:" +data.getClass().getName()); } } 在使用泛型定义的类创建对象时,即在泛型类实例化时,也使用new运算符,但在类名后面需给出类型参数T的具体类型。 eg: Node<Integer> intNode = new Node<Integer>(); Node<Integer> intNode = new Node<>(); 在泛型类实例化的过程中,实际类型必须是引用类型, 不能用int、double或char等这样的基本类型来替换类型参数T。 实战演练 public interface Entry<K,V> { public K getKey(); public V getValue(); } public class Pair<K,V> implements Entry<K,V>{ private K key; private V value; public Pair(K key, V value) { this.

Linux中防火墙实战之Web服务器和ssh远程服务配置指南

🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧Linux高级管理防护和群集专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️创作时间:2024年8月1日8点15分 在当今数字化时代,网络安全显得尤为重要。Linux作为一种开源操作系统,广泛应用于服务器管理和网络配置中。本篇文章将详细介绍如何配置Linux防火墙和Web服务器,确保内网与外网的安全访问。同时,我们将探讨如何通过SSH远程管理服务器,提升网络管理的灵活性和安全性。 实验环境 四台服务器 一台作为防火墙 (ens33,ens36,ens37) 一台模拟外网 (ens37) 一台web服务器 (ens36) 一台作为内网PC 访问测试(NAT模式) 实验要求 内网PC能过访问Web服务器 ICMP中不能ping Web服务器 内网PC通过SSH的1234端口来远程Web服务器 外网通过SSH的1234端口来远程防火墙 网络环境配置 防火墙网卡配置 cd /etc/sysconfig/network-scripts/ cp -p ifcfg-ens33 ifcfg-ens36 cp -p ifcfg-ens33 ifcfg-ens37 ens36网卡 ens37网卡 ens33是nat模式 这个不用介绍 你设置DHCP 或者静态都可以 查看一下ip 把内网网关指向他就行 web服务器网卡 vim /etc/sysconfig/network-scripts/ifcfg-ens33 外网网卡配置 vim /etc/sysconfig/network-scripts/ifcfg-ens33 内网PC测试网卡 vim /etc/sysconfig/network-scripts/ifcfg-ens33 防火墙 开启路由转发 vim /etc/sysctl.conf sysctl -p 刷新 net.ipv4.ip_forward = 1 测连通性 配置完成之后检测连通性 可以发现防火墙都是可以访问通的 web服务器配置 配置完成网络环境之后 开启防火墙 在web上下载httpd yum install -y httpd echo testsmqnz > /var/www/html/index.

Flink-StarRocks详解:第二部分(第52天)

文章目录 前言2. 表设计2.1 StarRocks表设计2.1.1 列式存储2.1.2 索引2.1.3 加速处理2.1.3.1 预先聚合2.1.3.2 分区分桶2.1.3.3 物化视图2.1.3.4 列级索引 2.2 数据模型2.2.1 明细模型2.2.1.1 适用场景2.2.1.2 创建表2.2.1.3 使用说明 2.2.2 聚合模型2.2.2.1 适用场景2.2.2.2 原理2.2.2.3 创建表2.2.2.4 使用说明 2.2.3 更新模型2.2.3.1 适用场景2.2.3.2 原理2.2.3.3 创建表2.2.3.4 使用说明 2.2.4 主键模型2.2.4.1 适用场景2.2.4.2 原理2.2.4.3 创建表2.2.4.4 使用说明 前言 本文为Flink-StarRocks详解后续章节:主要详解StarRocks表设计,聚合,更新,主键三大数据模型。 由于篇幅过长,后续接着下面进行详解:  StarRocks分区分桶  StarRocks查询数据湖  实现即席查询案例 2. 表设计 2.1 StarRocks表设计 2.1.1 列式存储 StarRocks 中的表由行和列构成。每行数据对应用户一条记录,每列数据具有相同的数据类型。所有数据行的列数相同,可以动态增删列。在 StarRocks 中,一张表的列可以分为维度列(也称为 Key 列)和指标列(也称为 Value 列)。维度列用于分组和排序,指标列的值可以通过聚合函数 sum、count、min、max、hll_union_agg 和 bitmap_union 等累加起来。 在 StarRocks 中,表数据按列存储。物理上,一列数据会经过分块编码、压缩等操作,然后持久化存储到非易失设备上。但在逻辑上,一列数据可以看成是由相同类型的元素构成的一个数组。 一行数据的所有列值在各自的数组中按照列顺序排列,即拥有相同的数组下标。数组下标是隐式的,不需要存储。表中所有的行按照维度列,做多重排序,排序后的位置就是该行的行号。 查询时,如果指定了维度列上的等值条件或者范围条件、并且这些条件中的维度列可以构成表的维度列前缀,则可以利用数据的有序性,使用二分查找法快速锁定目标行。例如,表 table1 包含 event_day、siteid、citycode 和 username 四列,其中 event_day 和 siteid 是维度列。如果查询条件为 event_day = 2020-09-18 和 siteid = 2,因为 event_day 和 siteid 可以构成维度列前缀,因此可以使用二分查找法,只需要处理指定范围内的数据;如果查询条件为 citycode = 4 和 username = Andy,因为 citycode 和 username 不能构成维度列前缀,因此无法使用二分查找法,必须处理整表的数据。

web安全之简要sql注入

SQL注入原理:可控变量,带入数据库查询,变量中未存在过滤或者过滤不严谨 如何判断注入点?(以下数据库类型为mysql) 老办法: and 1=1 页面正常 and 1=2 页面错误 可能存在注入点 但是要选用最舒服的方法去测试! 讲一下老方法的原理 select * from users where id=1 and 1=1,正常 select * from users where id=1 and 1=2,错误 前面都是正确的语句,区别在于后面。 如果是1=1,那么就是真且真,结果为真 如果是1=2,那么就是真且假,结果为假 就是说你所自定义的1=1或者1=2,被网站正常执行到了,所以就存在注入点 那么我们就可以自定义一些sql语句,获取数据库的数据,写sql语句可以用到联合查询UNION这个关键字 操作流程如下: 1.判断注入 2.猜测列名数量(字段数),一般用order by去猜 select * from users where id=1 order by (1~n),直到页面不正常即为字段数,比如4正常,5不正常,则字段数为4。 3.猜解准备 select * from users where id=-1 union select 1,2,3,4,正常 注意:id=-1,让前面的语句为错误语句,即可只执行后面的语句,这样的作用是看下哪几列数据可以显示出来,然后将能显示的替换成注入语句即可 4.信息收集 数据库版本:version() 数据库名称:database() 数据库用户:user() 操作系统:@@version_compile_o s 比如说正常显示2和3,那就可以写 select * from users where id=-1 union select 1,database(),version(),4

【C++标准库】介绍及使用string类

string 一.string类介绍二.string类的静态成员变量三.string类的常用接口1.构造函数(constructor)2.析构函数(destructor)3.运算符重载(operator)1.operator=2.operator[]3.operator+=4.operator+ 4.string的四种迭代器(iterator)1.正向迭代器 iterator2.反向迭代器 reverse_iterator3.const修饰的正向迭代器 const_iterator4.const修饰的反向迭代器 const_reverse_iterator5.四种迭代器源代码 5.string类对象的容量操作6.string类对象的修改操作7.string类对象的查找操作8.string类对象的遍历操作1.下标 + []2.迭代器3.auto和范围for1.auto关键字2.范围for 四.非成员函数:getline()五.string——>OJ题 一.string类介绍 C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。 C++中将string封装为单独的类,string 类是 C++ 标准库中的一个非常重要的类,用于表示和操作字符串。string类位于命名空间std(标准库)下,使用string类记得加上头文件#include,并且使用命名空间using namespace std或者using std::string。 //使用时记得加上 #include<string> using std::string;//或者using namespace std; //源代码大致框架 namespace std { class string { private: char* _str; size_t _size; size_t _capacity; }; } 二.string类的静态成员变量 静态成员变量:static const size_t npos = -1; int main() { //static const size_t npos = -1; //typedef unsigned long long size_t //-1的原码:10000000 00000000 00000000 00000001 //-1的反码:11111111 11111111 11111111 11111110 //-1的补码:11111111 11111111 11111111 11111111 //npos:-1的补码按照无符号整形打印出的值,由于静态成员变量,类外使用时加上类域 cout << string::npos << endl;//32位环境:4294967295 return 0; } 三.

LeetCode题练习与总结:第N高的薪水--177

一、题目描述 SQL Schema > Pandas Schema > 表: Employee +-------------+------+ | Column Name | Type | +-------------+------+ | id | int | | salary | int | +-------------+------+ 在 SQL 中,id 是该表的主键。 该表的每一行都包含有关员工工资的信息。 查询 Employee 表中第 n 高的工资。如果没有第 n 个最高工资,查询结果应该为 null 。 查询结果格式如下所示。 示例 1: 输入: Employee table: +----+--------+ | id | salary | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | +----+--------+ n = 2 输出: +------------------------+ | getNthHighestSalary(2) | +------------------------+ | 200 | +------------------------+ 示例 2:

postman接口测试工具介绍与使用

Postman是一款功能强大的API接口测试工具,广泛用于开发人员、测试人员和API设计者之间。以下是关于Postman接口测试工具的详细解析: 一、Postman的特点 1、多样化的HTTP请求模拟:支持多种请求方法,如GET、POST、PUT、DELETE等,满足各种API测试需求。 2、Collection功能:允许用户将多个接口保存在测试集合中,便于管理和重用。 3、人性化的Response整理:优化响应参数的格式,支持JSON、HTML、XML等多种格式显示,便于查看和分析。 4、内置测试脚本语言:支持自定义参数和编写测试脚本,快速检查请求结果,增强测试的灵活性和自动化程度。 5、环境变量设定:支持全局和局部变量,提高参数复用率,便于在不同环境下进行测试。 6、团队协作:支持团队协作功能,可以共享测试脚本、集合和环境变量,提高团队工作效率。 二、Postman的使用场景 1、接口测试:用于测试API接口的功能、性能和稳定性,确保接口按预期工作。 2、前端开发:支持Mock测试,可以模拟后端服务,便于前端开发和调试。 3、后端开发:用于接口测试和生成接口文档,提高开发效率和质量。 4、API文档化:自动生成API文档,方便团队成员理解和使用接口。 三、Postman的基本操作 1、安装:Postman可以在多个平台上安装,包括Windows、MacOS和Linux。用户可以从Postman官网下载对应版本的安装包进行安装。 2、创建请求:在Postman中,可以通过点击“+”按钮来创建一个新的请求。输入请求的URL、选择请求方法(如GET、POST等)以及设置请求头和参数。 3、发送请求:点击发送按钮,Postman会向服务器发送请求,并显示响应结果。 4、查看响应:响应内容可以以文本、JSON格式显示,还可以通过预览器查看HTML内容。 5、编写测试脚本:在Tests标签页中,可以编写测试脚本来验证响应是否符合预期。例如,判断HTTP返回状态码是否为200,或者响应正文是否包含特定的字符串。 四、Postman的高级功能 1、参数化:可以通过占位符(如:id)来实现参数化,这样可以在不同的测试中使用相同的请求但传递不同的参数。 2、Mock Server:Postman提供了Mock Server功能,可以模拟后端服务,便于进行前端开发和调试。 3、监控和日志:Postman提供了监控功能,可以帮助开发者跟踪API的性能和稳定性。 4、自动化测试:可以使用Postman Tests来编写自动化测试脚本,并通过集合批量执行这些请求,实现自动化的接口测试。 5、生成报告:Postman可以生成多种格式的测试报告,如JSON、HTML等,方便团队成员共享和讨论测试结果。 五、Postman的优缺点 优点: 功能强大,支持多种请求方法和响应格式。支持自定义参数和编写测试脚本,增强测试的灵活性和自动化程度。提供Mock Server功能,便于前端开发和调试。支持团队协作和API文档化,提高团队工作效率。 缺点:不适合进行大规模的性能数据分析。部分高级功能需要付费使用。 综上所述,Postman是一款功能强大、易于使用的API接口测试工具,能够满足开发人员、测试人员和API设计者的各种需求。

《学会 SpringMVC 系列 · 剖析篇(上)》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍 文章目录 写在前面的话学前准备 请求流程分析Step1、DispatcherServlet#doDispatchStep2、DispatcherServlet#getHandlerStep3、DispatcherServlet#getHandlerAdapterStep4、DispatcherServlet#handleStep5、InvocableHandlerMethod#getMethodArgumentValuesStep6、InvocableHandlerMethod#doInvokeStep7、HandlerMethodReturnValueHandlerComposite#handleReturnValueStep8、RequestResponseBodyMethodProcessor#writeWithMessageConverters 请求分析复盘整个流程梳理(精简版)doDispatch(部分代码) 总结陈词 写在前面的话 通过上一篇博文《学会 SpringMVC 系列 · 基础篇》的学习,可以掌握 SpringMVC 的项目搭建和部分用法,从搭建过程中我们看到,SpringMVC 的入口是在 web.xml 中添加 DispatcherServlet,它是一个Servlet,那请求流程也遵循 Servlet 相关规范展开。 接下来,让我们进一步分析相关源码,顺带引出相关扩展点和实战运用。 学前准备 1、SpringMVC 源码分析分为初始化流程和请求流程两部分,本篇先重点介绍后者。可以把 SpringMVC的请求流程,比作一个请求(Servlet)的完整生命周期,那就是包括“请求前 - 实际请求 - 请求后”,以此思路展开; 2、本篇 SpringMVC 源码分析系列文章,将以 《搭建拥有数据交互的 SpringBoot 》的 SpringBoot3.x 为基础,学习相关源码,对应 SpringMVC 版本为 6.1.11,不过核心流程上,基本大同小异; 3、先添加一个入参和返回值都是实体对象的接口,如下所示,正所谓麻雀虽小,但也覆盖到入参解析逻辑了,启动Boot项目,Postman测试一下,恩,功能都正常,可以开始源码学习了! @ResponseBody @RequestMapping("/studyJson") public ZyTeacherInfo studyJson(@RequestBody ZyTeacherInfo teacherInfo) { teacherInfo.setTeaName("战神"); return teacherInfo; } 相关文章 《学会 SpringMVC 系列 · 剖析篇(上)》 请求流程分析 Tips:先通过示例方法的执行,梳理一下相对完整的链路,后续在此基础上扩展自定义逻辑。 Step1、DispatcherServlet#doDispatch 前面提到 DispatcherServlet 是 SpringMVC 的入口,不管是否为 SpringBoot 项目,都是如此。

string类简单模拟实现

目录 1. string成员变量 2. string的成员函数 (1). 构造函数和析构函数 (2). string的访问 ① 范围for访问 ②下标访问 (3). string的修改 ① 函数重载+= ② push_back与append的实现 ③ insert的实现 ④ erase与clear的实现 ⑤ 交换函数 (4). string的查找 (5). string的流插入与流提取的重载 (6). 其他一些操作 ① 比较 ② substr ③ 赋值运算符重载 3. 源代码 (1). 头文件 (2). 实现功能的 我们实现string将其封装到一个namespace(命名空间中) 1. string成员变量 我们在使用string的时候发现它存储字符串,并且可以动态增加容量,于是我们用_str 来存储字符串,用_size来记录它存储的字符个数,用_capacity来记录容量 此外我们还实现了一个静态变量 npos #pragma once #include<iostream> #include<assert.h> #include<cstring> using std::cout; using std::cin; using std::endl; using std::istream; using std::ostream; namespace Pc { class string { public: //static const size_t npos = -1; static const size_t npos ; .

【c++】爬虫到底违不违法?

很多小伙伴都想知道爬虫到底违法吗,今天博主就给大家科普一下 爬虫本身并不违法,但使用爬虫采集数据可能涉及违法风险,具体取决于采集行为是否侵犯了他人的合法权益,尤其是隐私权和个人信息权。以下是对爬虫是否违法的详细分析: 一、爬虫技术的中立性 爬虫作为一种计算机技术,其本身并不具有违法性。爬虫技术被广泛用于数据收集、搜索引擎优化、市场分析等多个领域,为许多行业提供了便利。 二、爬虫行为违法的判定标准 是否存在非法获取行为: 判定爬虫行为是否违法,首先要看爬虫程序是否通过非法手段获取了数据。例如,破解网站的验证码或登录验证等安全措施,强行进入并爬取数据,这种行为就可能构成非法获取。 是否侵犯了他人隐私: 如果爬虫程序获取的数据涉及个人隐私,如姓名、身份证件号码、通信通讯联系方式、住址、账号密码、财产状况、行踪轨迹等,且未经授权或超出合理范围进行采集,就可能构成侵犯隐私权的违法行为。 是否具有恶意目的: 爬虫行为的目的也是判断其是否违法的重要因素。如果爬虫程序被用于恶意目的,如进行诈骗、盗号、攻击计算机系统等,即使其未直接侵犯他人隐私,也可能因其恶意目的而被视为违法行为。 三、法律依据 《中华人民共和国民法典》:根据该法律的相关规定,任何组织或个人不得以刺探、侵扰、泄露、公开等方式侵害他人的隐私权和个人信息权。《中华人民共和国刑法》:对于违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰等行为,造成严重后果的,将依法追究刑事责任。

关于 Postman 这些你都知道吗?

Postman是接口测试工具,在做接口测试的时候,Postman相当于一个客户端,它可以模拟用户发起的各种http请求,将请求的数据发送到服务端,获取对应的结果,从而测试接口是否能够满足业务功能要求,很直观的返回接口的结果。虽说是测试工具,但作为前端仔,还是需要了解的。接下来我们一起下载安装,并且看一下怎么使用的吧。 目录 1.下载 2.安装 2.1 根据下载路径,找到已经下载的安装包文件 2.2 打开之后会有提示让注册 3.如何使用 1.下载 百度直接搜索postman下载 也可直接点这里:Download Postman | Get Started for Free 2.安装 2.1 根据下载路径,找到已经下载的安装包文件 2.2 打开之后会有提示让注册 3.如何使用 3.1双击打开就可以使用了 这里可以对不同的请求方式 比如 get post put delete 等进行切换测试不同的请求接口。 接口请求的参数可以设置 按照接口请求数据以及要求设置后点击send按钮就可以返回接口的信息了。 有问题评论区留言,谢谢。 学习基于node.js平台的web应用开发请参考:Express基于Node.js基础知识【1】全面总结 推荐收藏-CSDN博客

web安全基础学习

http基础 HTTP(HyperText Transfer Protocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。本文将介绍如何使用HTTP协议,以及在Linux操作系统中如何使用curl工具发起HTTP请求。 一、HTTP特性 无状态:HTTP协议本身不保存用户状态信息,每次请求都是独立的。不连接:HTTP协议采用无连接的方式,即每次请求完成后,服务器和客户端之间的连接就会关闭。一问一答模式:客户端发起请求(Request),服务器返回响应(Response)。 二、HTTP报文格式 1. 请求报文 请求行:包括请求类型(如POST、GET、HEAD等)、目的地(URL)和HTTP版本。请求头:包含请求的附加信息,如User-Agent、Content-Type等。正文:请求的内容,如POST请求的表单数据。 2. 响应报文 响应行:包括HTTP版本、状态码(如200、404等)和状态消息(如OK、Not Found等)。响应头:包含响应的附加信息,如Content-Type、Server等。正文:响应的内容,如HTML页面、图片等。 三、请求类型 GET:请求内容会附加在URL中,适用于查询操作。POST:请求内容在包体中,适用于提交数据。HEAD:与GET类似,但不会返回响应正文,常用于测试文件是否存在。 四、常见状态码 200:请求成功。302:重定向。404:资源不存在。400:请求语法错误。401:未授权,需要身份验证。403:禁止访问,服务器理解请求,但拒绝执行。500:服务器内部错误。503:服务器暂时不可用。 五、Linux中使用curl工具发起HTTP请求 以下是一个使用curl工具发起HTTP GET请求的示例: curl -X GET http://www.example.com 发起POST请求的示例: curl -X POST -d "param1=value1&param2=value2" http://www.example.com 发起HEAD请求的示例: curl -X HEAD http://www.example.com

7月31日MySQL学习笔记

今日内容: mysql: 行列转换 数据类型 函数 触发器 存储过程 事务 索引(还没讲) 三范式 JDBC连接数据库的6个步骤 三握四挥 行列转换 第一步 新建要转换的列 select name, 1 as '语文', 1 as '数学', 1 as '英语' from t_score GROUP BY name 第二步 对每一列填入值,没有对应值填null/0 select *, CASE subject when '语文' then fraction else 0 end , CASE subject when '数学' then fraction else 0 end, CASE subject when '英语' then fraction else 0 end from t_score 第三步 将多行数据分组合并 -- 求和或最大值 select name, sum(CASE subject when '语文' then fraction else 0 end) as '语文', sum(CASE subject when '数学' then fraction else 0 end) as '数学', sum(CASE subject when '英语' then fraction else 0 end) as '英语' from t_score GROUP BY name 或者使用if函数

【C++】C++11之右值引用

目录 一、前言 二、概念 2.1 左值和左值引用 2.2 右值和右值引用 三、左值引用与右值引用的区别 四、应用场景 4.1 左值引用的短板(将亡值) 4.2 右值引用的意义(移动语义) 五、右值引用引用左值 六、万能引用和完美转发 一、前言 在传统的C++语法中就有引用,而C++11中又新增了右值引用的语法特性,从此传统的引用就变为了左值引用。无论是哪种引用,都是给一个对象取别名,不过二者针对的对象种类不同 右值引用是一块晦涩难懂的语法糖,何为左值?何为右值?何为左值引用?何为右值引用? 二、概念 2.1 左值和左值引用 左值(lvalue)是一个表达式,它表示一个可被标识的(变量或对象的)内存位置,并且允许使用&操作符来获取这块内存的地址。如果一个表达式不是左值,那它就被定义为右值。 简单来说,左值就是可以出现在赋值符号左侧的值,一个表示数据的表达式(如变量名或指针)就是左值;可以被取地址的就是左值;可以被赋值的就是左值。 而左值引用很好理解,就是对左值的引用,符号为& 例如: int main() { int a = 1; //a是左值 int* p = new int(1); //*p和p是左值 const int b = 1; //b是左值 int& ra = a; //左值引用 int*& rp = p; //左值引用 const int& rb = b; //左值引用 return 0; } 2.2 右值和右值引用 一个表达式如果不是左值,那么就是右值。如字面常量、表达式返回值、非左值引用返回的函数返回值等都是右值。 右值可以出现在赋值符号的右边,但是一定不能出现在赋值符号的左边。右值不能被取地址 右值引用就是对右值的引用,符号为&&

数据结构:二叉树(链式结构)

文章目录 1. 二叉树的链式结构2. 二叉树的创建和实现相关功能2.1 创建二叉树2.2 二叉树的前,中,后序遍历2.2.1 前序遍历2.2.2 中序遍历2.2.3 后序遍历 2.3 二叉树节点个数2.4 二叉树叶子结点个数2.5 二叉树第k层结点个数2.6 二叉树的深度/高度2.7 二叉树查找值为x的结点2.8 层序遍历2.9 判断二叉树是否为完全二叉树2.10 二叉树的销毁 3. 源代码 1. 二叉树的链式结构 二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成:数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,三叉链在结构上比二叉链多了一个指向父节点的指针域。 在这里先使用二叉链来实现二叉树 2. 二叉树的创建和实现相关功能 2.1 创建二叉树 用链表来实现二叉树,每个链表结点都由一个数据域和左右指针域组成 //定义二叉树的链式结构 //二叉树结点的结构 typedef int BTDataType; typedef struct BinaryTreeNode { BTDataType data;//存储数据 struct BinaryTreeNpde* left;//指向左孩子结点的指针 struct BinaryTreeNode* right;//指向右孩子结点的指针 }BTNode; 接下来我们来实现创建节点的函数: 首先使用malloc函数创建一个节点大小的空间,如果创建失败就打印错误信息,创建成功则把数据存储在新节点的数据域中,再将新节点的左右孩子指针指向空,最后返回新节点即可 //创建二叉树新节点 BTNode* buyNode(BTDataType x) { BTNode* newnode = (BTNode*)malloc(sizeof(BTNode)); if (newnode == NULL) { perror("malloc fail!"); exit(1); } newnode->data = x; newnode->left = newnode->right = NULL; return newnode; } 下面我们来创建一棵如图所示的二叉树