作者:程序员CKeen
博客:http://ckeen.cn
长期坚持做有价值的事!积累沉淀,持续成长,升维思考!希望把编码作为长期兴趣爱好😄
目录 1. 背景2. Web端本地File操作的API3. File and Directory Entries API的介绍4. 代码实现 1. 背景 最近遇到一个很特别的需求,需要将嵌入式设备的里面的视频流和图片通过websocket直接传到浏览器端进行显示和存储(因为设备的存储空间较有限,不能将视频和图片存在设备上),并且本地浏览器还可以查看视频和图片列表以及提供视频和图片的本地下载。不过还好的是,不用考虑所有浏览器。具体需求参考如下:
通过分析, 貌似要做的就是将websocket传过来的视频裸流和图片数据,通过web端浏览器接口直接存储在本地,以及从本地读取这些文件。 于是就开始去找web浏览器关于本地文件操作的方法, 在MDN找到了web端对File操作的相关的API。
参考链接:https://developer.mozilla.org/en-US/docs/Web/API
2. Web端本地File操作的API MDN介绍的File相关的API主要有以下三个:
File API 。文件API使web应用程序能够访问文件及其内容。
当用户使文件可用时,Web应用程序可以访问文件,可以使用file 元素,也可以通过拖放操作。
以这种方式提供的文件集被表示为FileList对象,它使web应用程序能够检索单个File对象。反过来,File对象提供对元数据的访问,例如文件的名称、大小、类型和最后修改日期。
文件对象可以传递给FileReader对象来访问文件的内容。FileReader接口是异步的,但只有在web worker中可用的同步版本由FileReaderSync接口提供。
File and Directory Entries API。
文件和目录条目API模拟了一个本地文件系统,web应用程序可以在其中导航和访问文件。你可以开发在虚拟的沙盒文件系统中读取、写入和创建文件和/或目录的应用。
File System Access API。
文件系统访问API允许读、写和文件管理功能。该API允许与用户本地设备上的文件或用户可访问的网络文件系统上的文件进行交互。该API的核心功能包括读取文件、写入或保存文件以及访问目录结构。
大多数与文件和目录的交互都是通过句柄完成的。父类FileSystemHandle帮助定义两个子类:FileSystemFileHandle和FileSystemDirectoryHandle,分别用于文件和目录。
而今天我们主要用到的是文件和目录的API:File and Directory Entries API。该API提供了对本地目录的创建,以及对文件的创建和读写操作。
3. File and Directory Entries API的介绍 上面已经简单了介绍了File and Directory Entries API的用途,下面我们主要介绍该分类下的API接口。
该API详细的介绍可以参考提案:https://wicg.github.io/entries-api/#api-domfilesystem
文件和目录的API主要有以下5个
FileSystem:表示文件系统。当我们需要对文件进行操作时,需要先获取FileSystem的对象,然后通过FileSystem对象来操作具体的目录和文件对象。FileSystemEntry:表示文件系统中单个条目的基本接口。这是由表示文件或目录的其他接口实现的。FileSystemDirectoryEntry:表示文件系统中的单个目录。FileSystemFileEntry:表示文件系统中的单个文件。FileSystemDirectoryReader:该接口通过调用 FileSystemDirectoryEntry.createReader() (en-US) 创建,提供了允许读取目录内容的功能。 下面是不同浏览器对File and Directory Entries API支持的情况:
目录 常见术语如何解决数据重复和数据乱序幂等性幂等性的缺陷事务事务原子性事务原理流程图 如何解决数据积压解决方法 Kafka的高水位(HW)和Leader Epoch副本同步机制解析Leader Epoch是如何解决消息丢失和消息不一致的问题的 常见术语 Kafka的三层消息架构:
第一层是主题层,每个主题可以配置M个分区,而每个分区又可以配置N个副本。
第二层是分区层,每个分区的N个副本中只能有一个充当领导者角色,对外提供服务;其他N-1个副本是追随者副本,只是提供数据冗余之用。(客户端程序只与分区的领导者副本进行交互)
第三层是消息层,分区中包含若干条消息,每条消息的位移从0开始,依次递增。
在Kafka中,发布订阅的对象是主题(Topic),每个业务、每类数据都能创建对应的主题。
向主题发布消息的客户端应用程序称为生产者(Producer)
订阅这些主题消息的客户端应用程序就被称为消费者(Consumer)
生产者和消费者统称为客户端(Clients)。
Kafka的服务器端由被称为Broker的服务进程构成,即一个Kafka集群由多个Broker组成,Broker负责接收和处理客户端发送过来的请求,以及对消息进行持久化。
为了保证高可用,可以采取多副本进行数据同步。Kafka定义了两类副本:领导者副本(Leader Replica)和追随者副本(Follower Replica)。
生产者总是向领导者副本写消息;而消费者总是从领导者副本读消息。至于追随者副本,它只做一件事:向领导者副本发送请求,请求领导者把最新生产的消息发给它,这样它能保持与领导者的同步。
为了保证系统的伸缩性,Kafka中的分区机制指的是将每个主题划分成多个分区(Partition),每个分区是一组有序的消息日志。生产者生产的每条消息只会被发送到一个分区中,也就是说如果向一个双分区的主题发送一条消息,这条消息要么在分区0中,要么在分区1中。
副本是在分区这个层级定义的。生产者向分区写入消息,每条消息在分区中的位置信息由一个叫位移(Offset)的数据来表征。
每个消费者在消费消息的过程中必然需要有个字段记录它当前消费到了分区的哪个位置上,这个字段就是消费者位移(Consumer Offset)。
如何解决数据重复和数据乱序 Kafka默认提供的交付可靠性保障是“至少一次”,即消息不会丢失,但有可能被重复发送。
只有Broker成功“提交”消息且Producer接到Broker的应答才会认为该消息成功发送。不过倘若消息成功“提交”,但Broker的应答没有成功发送回Producer端(比如网络出现瞬时抖动),那么Producer就无法确定消息是否真的提交成功了。因此,它只能选择重试,也就是再次发送相同的消息。这就是Kafka默认提供至少一次可靠性保障的原因,不过这会导致消息重复发送。
对于涉及金钱交易的系统,我们更希望交付方式是“精确一次”,即消息既不会丢失,也不会被重复处理。Kafka通过两种机制:幂等性(Idempotence)和事务(Transaction)保证了“精确一次”的交付。
幂等性 Producer 的幂等性指的是当发送同一条消息时,数据在 Server 端只会被持久化一次,数据不丟不重,Kafka为了实现幂等性,在0.11.0.0之后加入的该新功能,它在底层设计架构中引入了ProducerID和SequenceNumber。
ProducerID:每个生产者启动时,Kafka 都会给它分配一个 ID,ProducerID 是生产者的唯一标识,需要注意的是,Kafka 重启也会重新分配 PIDSequenceNumber :对于每个ProducerID,Producer发送数据的每个Topic和Partition都对应一个从0开始单调递增的SequenceNumber值。 如果Broker在发送Ack信号给Producer时出现网络异常,导致发送失败。异常情况如下图所示:
每个新的Producer在初始化的时候会被分配一个唯一的PID(凡是开启幂等性都是需要生成PID,只不过未开启事务的PID可以在任意broker生成,而开启事务只能在TransactionCoordinator节点生成),该PID对用户完全透明而不会暴露给用户。Broker端也会为每个<PID, Topic, Partition>维护一个序号,并且每次Commit一条消息时将其对应序号递增。对于接收的每条消息,如果其消息序号比Broker维护的序号(即最后一次Commit的消息的序号)大一,则Broker会接受它,否则将其丢弃:
如果消息序号比Broker维护的序号大于1以上,说明中间有数据尚未写入,也即乱序,此时Broker拒绝该消息,Producer抛出InvalidSequenceNumber如果消息序号小于等于Broker维护的序号,说明该消息已被保存,即为重复消息,Broker直接丢弃该消息,Producer抛出DuplicateSequenceNumber 上述设计解决了数据重复和数据乱序的问题。
幂等性的缺陷 只能保证 Producer 在单个会话内不丟不重 ,如果 Producer 出现意外挂掉再重启是无法保证的(幂等性情况下,是无法获取之前的状态信息,因此是无法做到跨会话级别的不丢不重);另外幂等性不能跨多个 Topic-Partition,只能保证单个 partition 内的幂等性 ,当涉及多个 Topic-Partition 时,这中间的状态并没有同步。
如果需要跨会话、跨多个 topic-partition 的情况,需要使用 Kafka 的事务性来实现。
事务 为了实现有状态的应用也可以保证重启后从断点处继续处理,也即事务恢复。应用程序必须提供一个稳定的(重启后不变)唯一的 ID,也即Transaction ID。Transactin ID与PID可能一一对应。区别在于Transaction ID由用户提供,而PID是内部的实现对用户透明。
说明: ChatGPT等基于Transformer的大语言模型(LLM)的成功带给了人们巨大的震撼,其表现的few-shot甚至zero-shot能力仿佛让人们看到了通用人工智能(AGI)的曙光。而CLIP等跨模态模型打通了NLP和CV的界限,这些VLM模型将AGI发展继续向前推进。
AGI在机器人领域同样有很大的提升空间。试想如果机器人拥有了LLM般的思考能力,那这个世界将变得多么智能!届时的机器人不是只能机械执行预先设定好的程序,而是能够真的读懂人类,和人类自然交互。
RT2是谷歌deepmind团队今年7月底结合VLM和机器人控制技术研发的横跨语言-视觉-动作三模态的大模型。真正赋予了机器人的泛化能力!
——————————————————————————————————————————
本文包括论文的摘要、介绍、相关工作及模型介绍;论文其他部分翻译和解读见本专栏其他文章。翻译仅供参考。
论文地址:arxiv.org/pdf/2307.15818.pdf 翻译:ChatGPT Abstract 我们研究了在互联网规模数据上训练的视觉-语言模型如何直接融入端到端的机器人控制中,以提升泛化能力并实现新兴的语义推理。我们的目标是使单一的端到端训练模型既能够学习将机器人的观测映射到动作,又能够享受来自网络的大规模语言和视觉-语言数据的好处。为此,我们提出了将最先进的视觉-语言模型在机器人轨迹数据和互联网规模的视觉-语言任务(如视觉问答)上进行协同微调的方法。与其他方法不同的是,我们提出了一个简单通用的方法来实现这个目标:为了将自然语言回复和机器人动作都适应相同的格式,我们将动作表达为文本标记,并将其与自然语言标记一样直接并入模型的训练集中。我们将这类模型称为视觉-语言-动作模型(VLA),并且实例化了一个这样的模型,我们称之为RT-2。我们广泛的评估(6,000个评估试验)显示,我们的方法导致了高性能的机器人策略,并使RT-2能够从互联网规模的训练中获得一系列新兴的能力。其中包括对新颖对象的显著改进的泛化能力,解释机器人训练数据中不存在的命令(例如将物体放在特定的数字或图标上),以及能够对用户命令做出基本推理(例如拾取最小或最大的物体,或距离另一个物体最近的物体)。我们进一步展示,引入思维链推理使得RT-2能够进行多阶段的语义推理,例如找出哪个物体适合用作临时的锤子(一块石头),或者哪种类型的饮料最适合疲劳的人(能量饮料)。
Introduction 在广泛的网络规模数据集上预训练的高容量模型为各种下游任务提供了一个有效且强大的平台:大型语言模型不仅可以实现流畅的文本生成(Anil等,2023;Brohan等,2022;OpenAI,2023),还能够实现新兴的问题解决(Cobbe等,2021;Lewkowycz等,2022;Polu等,2022)和创造性的散文(Brown等,2020;OpenAI,2023)和代码生成(Chen等,2021),而视觉-语言模型可以实现开放词汇的视觉识别(Kirillov等,2023;Minderer等,2022;Radford等,2021),甚至可以对图像中的物体-代理交互进行复杂推断(Alayrac等,2022;Chen等,2023a,b;Driess等,2023;Hao等,2022;Huang等,2023;Wang等,2022)。这种语义推理、问题解决和视觉解释能力对于必须在现实环境中执行各种任务的通用型机器人将非常有用。然而,机器人应该如何获得这些能力尚不清楚。虽然一种蛮力方法可能涉及收集数百万次机器人交互试验,但最能胜任的语言和视觉-语言模型是在来自网络的数十亿标记和图像上进行训练的(Alayrac等,2022;Chen等,2023a,b;Huang等,2023)——在不久的将来,机器人数据不太可能达到这个数量级。另一方面,直接将这些模型应用于机器人任务也很困难:这些模型推理语义、标签和文本提示,而机器人需要基于实际的低级行动,比如笛卡尔末端执行器命令。尽管近期有许多工作试图将语言模型(LLMs)和视觉-语言模型(VLMs)融入机器人技术中(Ahn等,2022;Driess等,2023;Vemprala等,2023),但这些方法通常只涉及机器人规划的“高级”方面,本质上扮演着解释命令并将其解析为单独基元(如拾取和放置物体)的状态机的角色,这些基元然后由独立的低级控制器执行,而这些控制器本身在训练过程中并未从互联网规模模型的丰富语义知识中受益。因此,在本文中,我们提出了一个问题:是否可以将大型预训练的视觉-语言模型直接集成到低级机器人控制中,以提升泛化能力并实现新兴的语义推理?
为了实现这一目标,我们探索了一个既简单又出奇有效的方法:我们直接训练设计用于开放词汇视觉问答和视觉对话的视觉-语言模型,使其输出低级机器人动作,并解决其他互联网规模的视觉-语言任务。尽管这些模型通常是针对生成自然语言标记进行训练的,但我们可以通过将动作标记为文本标记,并创建“多模态句子”(Driess等,2023),通过将动作与摄像头观测相配对来“响应”机器人指令,从而训练它们在机器人轨迹上。这种方式,视觉-语言模型可以直接被训练成为遵循指令的机器人策略。这种简单方法与将VLMs纳入机器人策略的先前替代方法(Shridhar等,2022a),或者从头开始设计新的视觉-语言-动作架构(Reed等,2022)形成了鲜明对比:相反,现有的视觉-语言模型,已经经过了大量的计算投入,可以在不引入任何新参数的情况下进行训练,以输出文本编码的动作。我们将这类模型称为视觉-语言-动作(VLA)模型。我们通过在RT-1(Brohan等,2022)提出的协议基础上进行扩展来实例化VLA模型,使用类似的数据集,但将模型扩展为使用大型视觉-语言主干。因此,我们将我们的模型称为RT-2。我们在图1中提供了一个概览。
图1:左侧是利用互联网上的VQA(视觉问答数据),但是把回答的内容从自然语言替换成了动作的表示。中间是RT-2模型架构,它的核心是一个transformer,视觉图像通过ViT模型进行输入;输出是机器人的一系列动作token并解码表示为动作。右侧是最终的机器人闭环控制效果。 我们观察到,从这些视觉-语言模型衍生出的机器人策略表现出一系列引人注目的能力,将从机器人数据中学到的物理运动能力与从网络数据中学到的图像和文本解释能力融合到一个单一的模型中。除了显著提高对新颖物体和语义多样指令的泛化能力的预期好处外,我们还观察到一些新兴的能力。虽然模型的物理技能仍然局限于机器人数据中看到的技能分布,但模型通过使用从网络获取的知识来解释图像和语言命令,获得了将这些技能以新方式应用的能力。一些示例亮点如图2所示。模型能够将从机器人数据中学到的拾取和放置技能重新用于将物体放置在语义指示的位置附近,例如特定的数字或图标,尽管这些提示在机器人数据中不存在。模型还可以解释物体之间的关系,以确定选择哪个物体以及在哪里放置它,尽管机器人演示中没有提供这样的关系。此外,如果我们使用思维链提示来增强命令,模型甚至可以进行更复杂的语义推理,例如找出哪个物体适合用作临时的锤子(一块石头),或者哪种类型的饮料最适合疲劳的人(能量饮料)。
我们的主要贡献是RT-2,这是一系列从在网络规模数据上进行训练的大型视觉-语言模型进行微调得到的模型,直接用作具有泛化能力和语义感知的机器人策略。我们的实验研究了在互联网数据和来自先前工作的带有指令注释的机器人轨迹上训练的多达550亿参数的模型(Brohan等,2022)。在6000次机器人评估过程中,我们展示了RT-2能够显著提高对物体、场景和指令的泛化能力,并且表现出从网络规模的视觉-语言预训练中继承而来的广泛新兴能力。
Related Work 视觉-语言模型 视觉-语言模型(VLMs)可以分为几个类别(Gan等,2022),其中可能有两个最相关的类别:(1)表示学习模型,例如CLIP(Radford等,2021),它们学习了两种模态的共同嵌入,以及(2)形式为{视觉,文本} → {文本}的视觉语言模型,它们学习以视觉和语言作为输入,并提供自由格式的文本输出。这两个类别已被用于为各种应用于下游应用程序的预训练,如物体分类(Radford等,2021)、检测(Gu等,2021)和分割(Ghiasi等,2021)。在这项工作中,我们关注后一类别(Alayrac等,2022;Chen等,2023a,b;Driess等,2023;Hao等,2022;Li等,2023, 2019;Lu等,2019)。这些模型通常在许多不同的任务上进行训练,例如图像字幕生成、视觉问答(VQA)以及多个数据集上的通用语言任务。虽然先前的研究在广泛的问题和设置中研究了VLMs,包括在机器人技术中,但我们的重点是如何将VLMs的能力扩展到机器人闭环控制,赋予它们预测机器人动作的能力,从而利用VLMs中已经存在的知识,实现新水平的泛化能力。
机器人学习中的泛化 在机器人研究中,开发能够在各种情景中广泛成功的机器人控制器是一个长期存在的目标(Kaelbling,2020;Smith和Coles,1973)。在机器人操作中实现泛化的一个有希望的方法是从大规模和多样化的数据集中学习(Dasari等,2019;Levine等,2018;Pinto和Gupta,2016)。通过这样做,先前的方法已经证明了机器人如何能够对新的物体实例(Finn和Levine,2017;Levine等,2018;Mahler等,2017;Pinto和Gupta,2016;Young等,2021),对涉及新对象和技能组合的任务(Dasari和Gupta,2021;Finn等,2017;James等,2018;Jang等,2021;Yu等,2018),对新目标或语言指令(Jang等,2021;Jiang等,2022;Liu等,2022;Mees等,2022;Nair等,2022a;Pong等,2019),对新的语义物体类别的任务(Shridhar等,2021;Stone等,2023),以及对未见环境(Cui等,2022;Du等,2023a;Hansen等,2020)进行泛化。与大多数这些先前的工作不同,我们的目标是开发和研究一个单一模型,能够在所有这些方面泛化到未见条件。我们方法的关键要素之一是利用预训练模型,这些模型已经接触到比机器人所见的数据更广泛的数据。
预训练机器人操作 预训练在机器人学习中有着悠久的历史。大多数工作都集中在预训练的视觉表示上,这些表示可以用来初始化机器人摄像头观测的编码器,可以通过监督的ImageNet分类(Shah和Kumar,2021)、数据增强(Kostrikov等,2020;Laskin等,2020a,b;Pari等,2021)或专门用于机器人控制的目标(Karamcheti等,2023;Ma等,2022;Majumdar等,2023b;Nair等,2022b;Xiao等,2022b)来实现。其他工作已经将预训练的语言模型纳入,通常是作为指令编码器(Brohan等,2022;Hill等,2020;Jang等,2021;Jiang等,2022;Lynch和Sermanet,2020;Nair等,2022a;Shridhar等,2022b)或用于高层规划(Ahn等,2022;Driess等,2023;Huang等,2022;Mu等,2023;Singh等,2023;Wu等,2023)。与使用预训练视觉模型或预训练语言模型不同,我们特别考虑使用预训练的视觉-语言模型(VLMs),这些模型为世界提供了丰富的、基于现实的知识。先前的工作已经研究了VLMs在机器人技术中的使用(Driess等,2023;Du等,2023b;Gadre等,2022;Karamcheti等,2023;Shah等,2023;Shridhar等,2021;Stone等,2023),并且为本工作提供了灵感。这些先前的方法使用VLMs用于视觉状态表示(Karamcheti等,2023),用于识别物体(Gadre等,2022;Stone等,2023),用于高级规划(Driess等,2023),或用于提供监督或成功检测(Du等,2023b;Ma等,2023;Sumers等,2023;Xiao等,2022a;Zhang等,2023)。虽然CLIPort(Shridhar等,2021)和MOO(Stone等,2023)将预训练的VLMs整合到端到端的视觉运动控制策略中,但两者都将重要结构纳入策略中,从而限制了其适用性。值得注意的是,我们的工作不依赖于受限制的二维动作空间,也不需要校准的摄像头。此外,一个关键区别在于,与这些工作不同,我们利用了生成语言的VLMs,并且我们的统一输出空间使得模型权重可以在语言和动作任务之间完全共享,而不需要引入仅针对动作的模型层组件。
Vision-Language-Action Models 在本节中,我们介绍我们的模型系列以及使训练VLMs能够直接进行闭环机器人控制的设计选择。首先,我们描述了我们模型的总体架构,以及它们如何从通常用于视觉-语言任务的模型中派生出来。然后,我们介绍了将在网络规模数据上预训练的大型VLMs进行微调的方法和挑战,使其能够直接输出机器人动作,成为VLA模型。最后,我们描述了如何使这些模型在机器人任务中变得实用,解决了模型大小和推理速度方面的挑战,以实现实时控制。
预训练视觉-语言模型 我们在本研究中所使用的视觉-语言模型(Chen等,2023a;Driess等,2023)将一个或多个图像作为输入,并生成一系列标记,通常代表自然语言文本。这样的模型可以执行广泛的视觉解释和推理任务,从推断图像的构成到回答关于单个对象及其与其他对象关系的问题(Alayrac等,2022;Chen等,2023a;Driess等,2023;Huang等,2023)。代表执行如此广泛任务所需的知识需要大型模型和网络规模的数据集。在本研究中,我们对两个先前提出的VLMs进行了调整,使其能够充当VLA模型:PaLI-X(Chen等,2023a)和PaLM-E(Driess等,2023)。我们将这些模型的视觉-语言-动作版本称为RT-2-PaLI-X和RT-2-PaLM-E。我们利用了这些模型的实例,其参数数量从数十亿到数百亿不等。我们在附录D中详细描述了这两个模型的架构。
机器人动作微调 为了使视觉-语言模型能够控制机器人,它们必须被训练为输出动作。我们采用了一种直接的方法来解决这个问题,将动作表示为模型输出中的标记,这些标记与语言标记相同对待。我们的动作编码基于Brohan等人(2022)在RT-1模型中提出的离散化方法。动作空间包括机器人末端执行器的6自由度位置和旋转位移,以及机器人夹持器的伸展程度和特殊的离散终止命令(用于终止机器人行为)。这应该由策略触发以表示成功完成。连续的维度(除了离散终止命令外的所有维度)被均匀地离散成256个箱子。因此,机器人动作可以用离散箱子的序数表示为8个整数。为了将这些离散化动作用于对视觉-语言进行微调以创建视觉-语言-动作模型,我们需要将模型现有标记的标记与离散动作箱子关联起来。这需要预留256个标记作为动作标记。选择哪些标记取决于每个VLM使用的特定标记化方法,我们稍后在本节中讨论这一点。为了为VLM微调定义一个目标,我们通过简单地将每个维度的动作标记与空格字符连接起来,将动作向量转换为单个字符串:
这样一个目标的可能实例化为:“1 128 91 241 5 101 127”。我们在实验中微调的两个VLMs,PaLI-X(Chen等,2023a)和PaLM-E(Driess等,2023),使用不同的标记化。对于PaLI-X,整数最多到1000,每个都有一个唯一的标记,因此我们只需将动作箱子与表示相应整数的标记相关联。对于PaLM-E模型,它没有提供这种方便的数字表示,我们只需覆盖256个最不常用的标记,以表示动作词汇。值得注意的是,训练VLMs覆盖现有标记以动作标记是符号调谐(Wei等,2023)的一种形式,在先前的工作中已被证明对VLMs非常有效。
采用上述所述的动作表示,我们将我们的机器人数据转换为适合VLM模型微调的格式,其中我们的输入包括机器人摄像头图像和文本任务描述(使用标准的视觉问答格式“Q:机器人应该采取什么动作来[任务说明]?A:”),我们的输出被格式化为表示机器人动作的数字/最不常用标记的字符串。
共同微调。正如我们将在实验中展示的那样,改善机器人性能的训练方法的一个关键技术细节是将机器人数据与原始网络数据一起进行共同微调,而不是仅在机器人数据上进行朴素微调。我们注意到,共同微调可以带来更具有泛化性的策略,因为在微调过程中,策略不仅暴露于来自网络规模数据的抽象视觉概念,还暴露于低级机器人动作,而不仅仅是机器人动作。在共同微调中,我们通过增加机器人数据集的采样权重来平衡每个训练批次中机器人和网络数据的比例。
输出约束。RT -2与标准的VLMs之间一个重要的区别是,RT -2需要输出可在真实机器人上执行的有效动作标记。因此,为了确保在解码过程中RT -2输出有效的动作标记,我们通过在模型被提示进行机器人动作任务时只对有效的动作标记进行采样来限制其输出词汇表,而在标准视觉-语言任务中,模型仍然可以输出完整范围的自然语言标记。
实时推理 现代VLMs的规模可以达到数百亿甚至数千亿个参数(Chen等,2023a;Driess等,2023)。本研究中训练的最大模型使用了550亿个参数。在通常用于实时机器人控制的标准台式机或机器人GPU上直接运行这样的模型是不可行的。据我们所知,我们的模型是有史以来用于直接闭环机器人控制的规模最大的模型,超过了一个数量级,因此需要一组新的解决方案来实现高效的实时推理。我们制定了一个协议,允许我们在多TPU云服务中部署RT-2模型,并通过网络查询此服务以在机器人上运行。通过这种解决方案,我们可以实现合适的控制频率,并且使用同一云服务为多个机器人提供服务。我们评估的最大模型是55B参数的RT-2-PaLI-X-55B模型,可以以1-3赫兹的频率运行。该模型的较小版本,由50亿个参数组成,可以以约5赫兹的频率运行。
文章目录 一、RBAC概念
二、实验步骤(serviceaccoount使用案例介绍)
1.创建sa并绑定到pod
2.创建pod
3.验证(拒绝访问)
4.对sa做授权
5.再次请求验证
三、自定义角色
1.创建角色,控制权限
2.角色绑定
总结
一、RBAC概念 1.RBAC官网介绍:使用 RBAC 鉴权 | Kubernetes
2.RBAC(基于角色的访问控制):是一种基于组织中各个用户的角色来调节对计算机或网络资源的访问方法。
作用:防止k8s里的pod能随意获取整个集群里的信息和访问集群里的资源
2.UserAccount和ServiceAccount介绍
二、实验步骤(serviceaccoount使用案例介绍) 1.创建sa并绑定到pod [root@k8smaster ingress]# kubectl create sa sa-lay serviceaccount/sa-lay created [root@k8smaster ~]# kubectl get sa NAME SECRETS AGE default 1 103d sa-lay 1 2d3h 2.创建pod [root@k8smaster sa]# cat sa-pod.yaml apiVersion: v1 kind: Pod metadata: name: sa-lay namespace: default labels: app: sa-lay spec: serviceAccountName: sa-lay containers: - name: sa-nginx ports: - containerPort: 80 image: nginx imagePullPolicy: IfNotPresent [root@k8smaster sa]# kubectl apply -f sa-pod.
1、谈出隐藏
fadeOut() 2、淡入显示
fadeIn() 3、隐藏元素
hide() 直接隐藏 hide( 3000 ) 动画隐藏过程为3秒 hide(3000,function(){ alert('执行3000ms动画完毕') } // 3秒后执行弹出对话框 4、显示元素
show() 直接显示 show( 3000 ) 动画显示过程为3秒 hide(3000).show(3000) 隐藏后显示 隐藏或显示都是会改变元素高度,高度,透明度开始,show与hide方法是修改的display属性 5、显示与隐藏切换
toggle() 显示与隐藏切换 如果元素是最初显示,它会被隐藏,如果隐藏的,它会显示出来 6、下拉动画
slideDown()下拉动画是从无到有,所以一开始元素是需要先隐藏起来的,可以设置display:none $("#a2").slideDown(3000,function(){alert('动画执行结束') 3秒后执行其他动作 7、上卷动画
slideUp() 8、上卷下拉切换
slideToggle("fast") 切换快200毫秒 slideToggle("slow") 切换慢600毫秒 9、淡入淡出切换
fadeToggle() 10、淡入效果值设定
fadeTo(1000,0.2) //等同于将opacity属性设定为0.2 11、效果比较
toggle() :切换显示与隐藏效果改变样式display,动态效果为从右至左 slideToggle() :切换上下拉卷滚效果设置位置高度,动态效果从下至上。竖向动作 fadeToggle() :切换淡入淡出效果 设置透明度,通过高度变化来切换所有匹配元素的可见性 12、用样式设定动画
animate({样式},时间,回调函数) animate({height: "toggle"},1000,function(){alert("动画 fontSize执行完毕!");}) 像画圈放下,时间为1秒,之后弹出“动画 fontSize执行完毕!” animate({ width:300, height :300 }) animate({ width:"+=100px", height : "
啊 发现问题的过程 在使用Card组件时有一个需求,就是需要将card组件的标题下方的横线缩短。
为了完成这一需求,首先只能是对card组件的标题栏进行自定义样式修改了。而修改也很简单,我只需要在页面绑定headStyle就行了。
//ChartCard组件 <template> <Card :title="growDate + '最新情报'" :bordered="false" :headStyle="headStyle"> <div ref="chartRef" :style="{ height, width }"></div> </Card> </template> <script setup lang='ts'> const headStyle = ref('margin:0 20px;boxSizing:border-box') </script> 但我发现其他组件也要改,于是我决定把headStyle写在父页面,然后通过props传入。如下:
//父页面 <template> <div> <GrowCard :headStyle="headStyle" /> <ChartCard :headStyle="headStyle" /> <div > </div> </div> </template> <script setup lang='ts'> import GrowCard from './GrowCard.vue' import ChartCard from './ChartCard.vue' import { ref } from const headStyle = ref('margin:0 20px;box-sizing:border-box;') </script> 这时ChartCard组件出现报错:
不能将类型“string”分配给类型“CSSProperties”。ts(2322)
index.d.ts(14, 13): 所需类型来自属性 "
今天要说的是spring中循环依赖的问题,最近有大量粉丝问这个问题,也是高薪面试中经常会被问到的一个问题。
关于循环依赖的问题,来感受一下连环炮,试试自己否可以过关斩将,轻松应对。
什么是循环依赖?
如何检测是否存在循环依赖?
如何解决循环依赖?
多例的情况下,循环依赖问题为什么无法解决?
单例的情况下,虽然可以解决循环依赖,是否存在其他问题?
为什么采用三级缓存解决循环依赖?如果直接将早期bean丢到二级缓存可以么?
前面4个ok的,超越了80%的人,后面2个难度指数递增,能回答出来的算是千分之一,如果能回答上来,会让面试官相当佩服你的。
下面我们来一个个突破。
什么是循环依赖? 这个很好理解,多个bean之间相互依赖,形成了一个闭环。
比如:A依赖于B、B依赖于C、C依赖于A。
代码中表示:
public class A{ B b; } public class B{ C c; } public class C{ A a; } 如何检测是否存在循环依赖? 检测循环依赖比较简单,使用一个列表来记录正在创建中的bean,bean创建之前,先去记录中看一下自己是否已经在列表中了,如果在,说明存在循环依赖,如果不在,则将其加入到这个列表,bean创建完毕之后,将其再从这个列表中移除。
源码方面来看一下,spring创建单例bean时候,会调用下面方法
protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } singletonsCurrentlyInCreation就是用来记录目前正在创建中的bean名称列表,this.singletonsCurrentlyInCreation.add(beanName)返回false,说明beanName已经在当前列表中了,此时会抛循环依赖的异常BeanCurrentlyInCreationException,这个异常对应的源码:
public BeanCurrentlyInCreationException(String beanName) { super(beanName, "Requested bean is currently in creation: Is there an unresolvable circular reference?"); } 上面是单例bean检测循环依赖的源码,再来看看非单例bean的情况。
FEC前向纠错用于丢包恢复,对媒体包进行异或或其他算法生成冗余包进行发送。如果接收端出现丢包,可以通过冗余包恢复出原始的媒体包。FEC的代价是增加码率带宽,所以一般会根据网络状况、丢包率来动态调整FEC冗余系数,也会结合NACK/ARQ丢包重传使用。WebRTC使用的FEC包括:ULP、flex、RED三种协议。接下来,我们主要分析ULP的协议结构。
ULP全称为Uneven Level Protection,不均匀级别保护,权衡网络带宽和保护力度。FEC冗余包越多,丢包恢复能力越强,但是带宽消耗越多。并不是所有媒体包的优先级都相同,因此可根据优先级来划分保护等级,比如优先分配给音频包,然后是视频的I帧包,接着是P帧、B帧。
1、ULP结构 基于ULP的FEC包有一个或多个保护等级。如下图所示,FEC包#1只有一个等级,用于保护媒体包A和B;而FEC包#2有两个等级,0级用于保护媒体包C和D,1级用于保护媒体包A、B、C、D。
2、FEC数据包结构 FEC数据包由RTP头、FEC头、FEC等级、FEC载荷组成,如下图所示。
3、FEC头结构 FEC头的结构由:扩展位E、长掩码L、填充位P、扩展标志X、CSRC计数、标志位M 、PT载荷类型、基本序列号、时间戳、长度组成,占8个字节。如下图所示:
E:扩展位,占1 bit,默认为0;
L:长掩码,占1 bit,L=0时掩码长度为16 bits,L=1时掩码长度为48 bits;
P、X、CC、M、PT与RTP头的数值一致;
SN base:基本序列号,占16 bits;
TS recovery:恢复包的时间戳,占32 bits;
length recovery:恢复包的长度,占16 bits; 4、 FEC的ULP等级 FEC的等级头占4或8字节,当L=0时头部长度为4字节,当L=1时头部长度为8字节。其中,保护长度占16 bits,mask掩码占16 bits,当L=1时有扩展mask占32 bits。
掩码的设置需要符合以下条件:
(1)、保护等级大于0的媒体包只会被保护一次,保护等级等于0的媒体包可以被多次保护; (2)、假设媒体包的保护等级为p,它可以被等级为p-1的任意FEC包进行保护;
(3)、假设FEC包包含保护等级p,它必须包含保护等级p-1;
5、生成FEC包 FEC包由媒体包逐位异或得到,并且根据每个等级生成不同的FEC包。假如RTP媒体包之间长度不同,需要以最长的媒体包为基准,其他媒体包添加填充位。
单个保护等级的FEC包示例如下,这里以媒体包D长度为准,其他媒体包后面填充0:
两个保护等级的FEC包示例如下:
6、FEC应用SDP会话 如下图所示,分为2个FEC组:第一组为"a=group:FEC 1 2",由音频流1和ulpfec流2组成;第二组为"a=group:FEC 3 4",由视频流3和ulpfec流4组成。
原文地址 原文链接
前言 如果要在Qt下实现软键盘的应用程序,在非嵌入式设备下就一行代码就可以处理了
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); 如果你希望自定义样式或者输入法,而你的嵌入式设备使用的是QML前端框架,也比较相对比较简单,可以参考Resize qtvirtualkeyboard according to QObject,以及官网相关说明
但是如果你使用的纯Widgets开发,而且又不希望混用QML的话就会稍微麻烦点了
生成自定义的虚拟动态链接库 如果你有更好的解决方案,可以在下方评论区提出,或者联系站长,这里我们是通过修改开源QWidget下virtualkeyboard实现来处理这个问题的,相对来说比较简单,开源库地址
这个方案源码只支持Qt5在Qt6下使用需要自行修改源码,修改处并不算特别多,有Qt6需求的按报错修改即可。使用步骤和他的文档中差不多,我这里仅作一些补充,大概说明一下源码主要文件以及修改方向
关于样式主要文件有KeyboardContainer键盘容器,定义了主键盘的样式以及上方中文字符选择列表的样式,NormalKeyboard定义了主键盘字符案件,没有特殊需求不必修改,SymbolKeyboard同理,CandidatesListWidget为中文选择列表类定义了一些样式和选择规则,InputContext输入初始化类,这个容易被忽视,这个他重写了键盘容器的位置和大小,如果需要调整键盘容器的位置和大小需要在这里调整
修改完源码,然后就是编译生成动态链接库了,如果你在Linux下打包生成的就是.so文件,如果是在windows下进行编译,生成就是.dll文件。Windows编译比较简单,直接点就行了,Linux下需要跑编译命令/your/qt/path/qmake xxxx.pro && make
先编译pinyin,注意,他用的中文字符库应该是GB2312的,对于中文字符的收录不全,就是我们xp时代自带的打字法所包含的字符,如果有生僻字需求需要更换字符相关的资源文件
再编译qt5softkeyboard,将生成在bin/plugins/platforminputcontexts/目录下的动态链接库拷贝到${YOUR_QT_DIR}/gcc/plugins/platforminputcontexts
最后在你的主程序中添加加载代码即可
qputenv("QT_IM_MODULE",QByteArray("Qt5Input")); 原文地址 原文链接
1、使用quartz框架可以实现并发执行 public class TestJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("TestJob TEST开始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("TestJob TEST结束"); } } @Configuration public class QuartzConfig { /** * 声明一个任务 * @return */ @Bean public JobDetail jobDetail() { return JobBuilder.newJob(TestJob.class) .withIdentity("TestJob", "test") .storeDurably() .build(); } /** * 声明一个触发器,什么时候触发这个任务 * @return */ @Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .forJob(jobDetail()) .withIdentity("trigger", "
本人是在最近一台新电脑想要装windows系统的虚拟机,下载了VMware workstation 17pro,也下载了官方的windows系统镜像iso文件。
但是在开启虚拟机的过程中,出现了类似以下的错误:
efi vmware virtual … No media
看到有人说需要下载官方镜像,我的就是,无效果。。。
也看到有人说需要开启虚拟机后,立马随便按键盘任意键,试了,无效果。。。
还有说需要在 虚拟机设置–》选项–》高级–》固件类型–》勾选 UEFI,试了,无效果。。。
后面我也想过会不会是VMware workstation 17 pro版本太高了,然后换成了VMware workstation 16 pro,结果开启虚拟机后,直接本地机器都蓝屏重启了。
最后好像是通过WIN+R,输入appwiz.cpl,勾选了Hyper-V就正常了。
前言 折腾了大概一天,东拼西凑终于还是搞定了
外网访问那里花费的时间最多
感慨颇多,前前后后还是做了很久的,必须要好好总结一下
jellyfin安装 参考的这篇文章
群晖NAS安装Jellyfin+TMM影片刮削器入门教程,完美硬解,轻松打造家庭影音中心!不敲一行命令轻松部署_NAS存储_什么值得买 (smzdm.com)
安装较为简单
且jellyfin使用也比较简单,简单的设置,主要就是添加媒体库就行
一步步来就行
因为不需要改造版的硬解码,故重新安装原版jellyfin
issue 原版和nayn版jellyfin都会爆内存,不过nyan版会自动关机,原本则需手动关机
故此选择nayn版配合自动启动,能够勉强正常使用,目前不知道什么原因
硬链接 推荐使用硬链接原影片后再进行刮削重命名整理一系列操作,更加合理
使用hlink项目:likun7981/hlink: 批量硬链接创建工具,又能PT做种,又能刮削电影资料 (github.com)
因为刮削的缘故,应该有更好的名字以及更好的文件层次分类
但因为PT,所以不能更改源地址
好在Linux支持硬链接
简单点说,就是复制,但复制和原本的文件,都是主体,两个文件只占一个存储,但可分别管理
两个必须同时删除,源文件才会被删除
资料刮削 tmm刮削普通电影 直接百度下载tmm的v3版本,v4版本收费
使用过程简单,按照自己的需求设置,摸索一下就行
部分没有成功,不知道是不是因为命名的问题
该文章提到了申请TMDB的api:群晖Nas通过jellyfin搭建本地影音库详细全过程(二):jellyfin影音库信息手动刮削和相关设置(100%扫库成功) - CodeAntenna
实际测试,提供API后能够更准确的刮削到电影资料,建议注册TMDB获得API
movie data capture刮削女友资料 使用该项目:Home · yoshiko2/Movie_Data_Capture Wiki (github.com)
具体操作看wiki
能够正常使用,能够刮削到大部分日产,但部分国产不行
renamer重命名 使用tmm自动重命名更为方便
但renamer是一个好用的软件,有特殊用途。
演员头像管理 女友照片 使用gfriends项目刮削:xinxin8816/gfriends: 媒体服务器演员头像仓库 (github.com)
该项目会出现黑裙jellyfin连接失败
安装原版jellyfin后可以使用
不行,原版主放弃了jellyfin的更新
JavScraper/Emby.Plugins.JavScraper: Emby/Jellyfin 的一个日本电影刮削器插件,可以从某些网站抓取影片信息。 (github.com)
更换此项目继续尝试
该项目不能被识别,放弃
准备摆烂
最后关闭了代理
竟然成功了
后面再次尝试又失败了,奇怪。看来好像只能随缘?
解决办法 在config.ini中按照以下配置
### Emby / Jellyfin 服务器地址 ### Host_Url=http://192.
我的问题好像是在安装Qt5.15.2出现的。
我的情况是由于网络问题问题,设置开启了本机的代理之后,就可以正常下载了。
在线SM4(国密)加密解密工具
基于javaweb+mysql的springboot仓库管理系统(java+springboot+layui+html+thymeleaf+mysql+实训报告)
运行环境
Java≥8、MySQL≥5.7
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SpringBoot仓库管理系统(java+springboot+layui+html+thymeleaf+mysql+实训报告)
项目介绍
仓库管理系统总共分为三个大的模块,分别是基础管理、仓库管理和系统管理。其中各个模块底下又有其子模块。 功能模块
一、基础管理
1、客户管理 客户列表 客户分页和模糊查询 客户添加、修改、删除、批量删除 2、供应商管理 供应商列表 供应商分页和模糊查询 供应商添加、修改、删除、批量删除 3、商品管理 商品列表 商品分页和模糊查询 商品添加、修改、删除、商品图片的上传
二、仓库管理
1.入库 订单查询、创建订单、删除订单 2.出库 订单查询、创建订单、删除订单 3.仓库基础设置 查询仓库、添加仓库、编辑仓库、删除仓库
三、系统管理
1、角色管理 全查询角色和模糊查询 角色的添加、修改、删除以及给角色分配权限 2、用户管理 全查询用户和模糊查询
用户的添加、修改、删除、重置密码以及给用户分配角色
环境需要
1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 5.是否Maven项目: 是;查看源码目录中是否包含pom.xml;若包含,则为maven项目,否则为非maven项目
6.数据库:MySql 8.0版本;
技术栈
后端:SpringBoot+Shiro+MybatisPlus
前端:HTML+CSS+Javascript+LayUI+DTree+Thymeleaf
使用说明
使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 将项目中application.yml配置文件中的数据库配置改为自己的配置; 3. 使用IDEA/Eclipse/MyEclipse导入项目,Eclipse/MyEclipse导入时,若为maven项目请选择maven; 若为maven项目,导入成功后请执行maven clean;maven install命令,配置tomcat,然后运行; 4. 运行项目,输入localhost:8080/ 登录 5.
前言 Dy这个东西想必大家都用过,而且还经常刷,今天就来用代码,获取它的视频数据
环境使用 Python 3.8
Pycharm
模块使用 requests
selenium
json
re
一. 数据来源分析 1. 明确需求
明确采集网站以及数据内容
网址: https://www.dy.com/user/MS4wLjABAAAAB0-gppwu15DtJJZmMpgUqakr7Jw_pmr7skR3IW6MwCQ?modal_id=7270865943398518050 数据: 视频链接 / 视频标题
2. 抓包分析
通过开发者工具进行抓包分析
I. 打开开发者工具: F12
II. 刷新网页
III. 找到数据链接
视频链接: https://v26-web.dyvod.com/295eea512e6f187309e6181297ec185e/64e8a7f8/video/tos/cn/tos-cn-ve-15c001-alinc2/o8vKACOD9NSbaA3mnggzfIO5QAgkqHnGr7sAeB/?a=6383&ch=26&cr=3&dr=0&lr=all&cd=0%7C0%7C0%7C3&cv=1&br=609&bt=609&cs=2&ds=3&ft=bvTKJbQQqU-mfJ4ZPo0OW_EklpPiXV8zNMVJEdBqSpvPD-I&mime_type=video_mp4&qs=15&rc=NTg8NzpoNGY2aGU0N2k1PEBpajhuNTY6ZmhtbTMzNGkzM0AtMy4xY2E0Xi4xYDNjX15iYSM2bl5scjRvLWdgLS1kLWFzcw%3D%3D&btag=e00010000&dy_q=1692965337&l=20230825200856A1A3326D295C25055965 IV. 通过关键字搜索, 找到链接对应数据包
视频链接 / 标题 --> 来自于网页源代码<进行编码>
数据包: https://www.dy.com/user/MS4wLjABAAAAB0-gppwu15DtJJZmMpgUqakr7Jw_pmr7skR3IW6MwCQ?modal_id=7270865943398518050 二. 代码实现步骤 发送请求, 模拟浏览器对于url地址发送请求获取数据, 获取服务器返回响应数据解析数据, 提取我们需要的数据内容保存数据, 保存视频数据 代码实现 发送请求 模拟浏览器: <可以直接复制>
response.text 获取响应文本数据
response.json() 获取响应json数据
response.content 获取响应二进制数据
我们使用requests.get()方法向指定的URL发送GET请求,并获取到响应的内容
headers = { # User-Agent 用户代理, 表示浏览器基本身份信息 'User-Agent': 'Mozilla/5.
原代码:
tf_swingbase_arm = torch.matmul(torch.inverse(tf_base_upper), torch.inverse(tf_uppernew_base)) 改成:
tf_swingbase_arm = torch.matmul(torch.inverse(tf_base_upper.cpu()).cuda(), torch.inverse(tf_uppernew_base.cpu()).cuda()) 原因不明的错误,不知道为什么要进行cpu和gpu的转换。
参考:
PVNet的demo报错解决方案(win10)_qq_36674060的博客-CSDN博客
前言:
每日一练系列,每一期都包含5道选择题,2道编程题,博主会尽可能详细地进行讲解,令初学者也能听的清晰。每日一练系列会持续更新,暑假时三天之内必有一更,到了开学之后,将看学业情况更新。
五道选择题: 1.执行完下面一段程序后输出的值是()
#include<stdio.h> int main() { int a = 1,b = 3,c = 5,d = 4; int x = 0; if (a < b)//1 if (c < d) x = 1;//2 else//3 if (a < c)//4 if (b < d) x = 2;//5 else x = 3;//6 else x = 6;//7 else x = 7;//8 printf("%d", x); } A、1 B、2 C、3 D、6
解析:易错题, 观察代码发现在代码1之前所做的操作只是简单地对变量初始化,到了代码1之后则是一大堆的if,else,这个地方其实考察的便是if,else的匹配问题,if,else的匹配在没有外界因素的影响之下秉承着就近原则,也就是if和else的相对距离小的会互相匹配上,根据这个我们可以得出,2和3匹配,5和6匹配,4和7匹配,1和8匹配
明白了匹配关系之后我们顺着代码走就行了,首先a<b成立,走到2,c<d不成立,走到3再走到4,a<c成立,走到5,b<d成立,令x=2,剩下的else就不用走了,因为之前已经匹配过了。故最后打印出来的是2,选B
拓展:当a=4,b=3,c=5,d=4时会打印出来什么(其他不变), 拓展解析:根据if,else的匹配问题,在a<b不成立时,就已经走到了代码8,令x=7,故最后会打印出7
背景 近来在搞springcloud微服务,有服务的注册和发现,即nacos。有网关服务,即spring-gateway。有认证中心服务。还有用户中心服务,文件中心服务,springboot admin等等。部署的时候,这么多服务,一个个启动起来甚是麻烦。由于我的服务都是部署在windows下,所以就想着用windows命令行来统一启动和关闭这些服务。
启动服务 部署目录结构如下:
config:数据库等的配置。jar:各个服务jar包。logs:服务的日志。nacos:服务注册和发现中心。 话不多说,直接上代码:
chcp 65001 @echo off taskkill /f /fi "IMAGENAME eq redis*" /im * taskkill /f /fi "IMAGENAME eq javaw.exe" /im * e: rem 启动nacos cd E:\projects\yyl-system\java\micro-system\release\nacos\bin start /min shutdown.cmd timeout /T 5 start /min startup.cmd timeout /T 5 rem 启动redis d: cd D:\Redis start /b redis-server.exe rem java服务 e: cd E:\projects\yyl-system\java\micro-system\release\jar rem 网关中心-sc-gateway.jar start "网关" javaw "-Dfile.encoding=utf-8" -jar sc-gateway.jar timeout /T 5 rem 认证中心-sc-gateway.
【python脚本】cv2.putText不显示中文,显示为???????解决方案,亲测有效。 text = "选中目标区域增强后的\n空间频率是%s,\n信息熵是%s" % (spatialF(gray_overlay_img), imageEn(gray_overlay_img)) cv2.putText(img2, text, (min_x, min_y + height + 30), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 0, 255), 2) 将上述代码改为:
from PIL import Image, ImageDraw, ImageFont def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20): if (isinstance(img, np.ndarray)): # 判断是否OpenCV图片类型 img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 创建一个可以在给定图像上绘图的对象 draw = ImageDraw.Draw(img) # 字体的格式 fontStyle = ImageFont.truetype( "STSONG.TTF", textSize, encoding="utf-8") # 绘制文本 draw.text((left, top), text, textColor, font=fontStyle) # 转换回OpenCV格式 return cv2.
GLSL是OpenGL着色器语言(OpenGL Shading Language)
版本说明 OpenGLES版本GLSL版本2.01003.03003.13103.2320 GLSL3.0与2.0差异 用 in 和 out 取代 attribute 和 varying头文件多了个 #version 300 es纹理 texture2D 和 texture3D 统统改为 texture内置函数 gl_FragColor 和 gl_FragData 删除,如果片段着色器要输出用out声明字段输出,不过保留了gl_Position可直接使用 layout 指定属性位置 数据类型 基本数据类型:void、int、float、double、uint、bool容器数据类型:向量(Vector)、矩阵(Matrix) 向量 可以包含有2、3、4个分量,分量的类型可以是基础数据类型的任意一个(除过void类型),n表示向量维度,如下表:
数据类型说明vecn包含n个float分量的默认向量bvecn包含n个bool分量的默认向量ivecn包含n个int分量的向量uvecn包含n个unsigned int分量的向量dvecn包含n个double分量的向量 一个向量可能有特殊含义,其可以看作是空间坐标(x,y,z,w)、颜色(r,g,b,a)或纹理坐标(s,t,p,q)。向量的分量可以通过vecn.x这种方式获取,可以分别使用.x、.y、.z、.w来获取它们的第1、2、3、4个分量(或着使用颜色vecn.rgba、或者使用纹理venc.stpq)。向量可以使用上面4个字母任意组合来创建一个和分量类型相同的新向量,只要原来向量有那些分量即可,这个叫做向量重组 //如果向量构造器中只提供了一个标量参数,则向量中所有值都会设定为该参数,即color={1.0,1.0,1.0,1.0} vec4 color = vec4(1.0); //向量重组 vec2 someVec; vec4 differentVec = someVec.xyxx; vec3 anotherVec = differentVec.zyw; vec4 otherVec = someVec.xxxx + anotherVec.yxzy; 矩阵 OpenGL的矩阵是列主顺序的
数据类型说明mat2 或 mat2x22×2的浮点数矩阵类型mat3 或 mat3x33×3的浮点数矩阵类型mat4x44×4的浮点矩阵mat2x32列3行的浮点矩阵mat3x23列2行的浮点矩阵mat3x43列4行的浮点矩阵mat4x24列2行的浮点矩阵mat4x34列3行的浮点矩阵 输入与输出 GLSL 3.0 定义了in 和 out 关键字专门来实现输入输出,只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。
Nvida jetson nano开发板 1、anaconda安装链接 2、pytorch安装链接 创建虚拟环境python==3.7后,通过nvcc -V或者 cat /usr/local/cuda/version.txt查看cuda版本,本机显示为
根据cuda10.2,安装1.8版本的torch:
pip install torch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 -f https://cf.torch.kmtea.eu/whl/stable-cn.html 安装成功。
此时导入torch模块后发现
torch版本不匹配,卸载后安装更低版本的torch==1.7.0后
其他应用的安装可参考链接
目录
初始化项目
创建项目
下载node_modules 运行测试
项目启动,自动打开
项目配置
配置eslint
安装eslint
生成配置文件: .eslint.cjs
安装Vue3环境代码校验插件
修改 .eslint.cjs 配置文件
为eslint生成 .eslintignore 忽略文件
为eslint添加运行脚本
如何使用
配置prettie
安装prettie
创建prettie的配置文件 prettierrc.json,并完成配置
创建prettie的忽略文件 .prettierignore,并完成配置
如何使用
配置stylelint
安装stylelint
创建配置文件 .stylelintrc.cjs ,并完成配置
创建stylelint的忽略文件 .stylelintignore,并完成配置
为stylelint添加运行脚本
如何使用
配置husky
安装husky
执行(需要先连接远程仓库)
在.husky/pre-commit文件添加如下命令:
配置commitlint
安装commitlint
创建配置文件 commitlint.config.cjs ,并完成配置
为commitlint添加运行脚本
配置husky
修改生成的commit-msg文件
配置统一使用pnpm包管理器工具 在根目录创建scritps/preinstall.js文件,添加下面的内容
添加运行脚本
项目集成
集成element-plus
安装element-plus
在main.ts进行配置
测试
安装element-plus的图标组件库
测试
入口文件main.ts全局安装element-plus,element-plus默认支持语言英语设置为中文
Element-Plus全局组件类型声明
src别名的配置
在vite.config.ts文件进行src别名配置
TypeScript 编译配置
测试
环境变量的配置
在项目的根目录下创建如下3个文件,注意文件名称
编辑
文件内容
根据@i冰宇宙的消息,三星Galaxy S24 Ultra采用了钛合金边框和直屏设计,这标志着设计师李一焕的首次亮相。
李一焕是梅赛德斯-奔驰中国区前首席设计官,在去年12月受聘为三星执行副总裁兼移动体验设计团队负责人。
他曾在微博中确认了Galaxy S24 Ultra 机身宽度为79mm,并表示这个参数不会有错(如果有错的话,也只能是屏幕数据的问题)。这个宽度对于直屏手机来说有些不太常见,因为相同宽度的直屏手机可能比曲屏手机更加不便使用。
此外,他还指出79mm宽度对人类来说有些不合理,三星旗舰手机史上,上一个宽度超过79mm的手机是Note Edge,而如果加上保护壳,Galaxy S24 Ultra手机的手感就类似于那款怪异的Note Edge手机。
与苹果的产品相比,三星此次选择了不同的方向,iPhone 15 Ultra的尺寸缩小至76.7mm,三星则在这方面持相反的态度,这一点令人难以理解。
此外,他还在微博和推特上分享了一系列对比照片,让人们更直观地了解Galaxy S24 Ultra与其他手机的差异。这些消息给手机用户提供了更多的信息和参考,让他们可以更好地了解和比较不同手机的设计和性能特点。
百度网盘yunshellextv164.dll删不掉 在删除百度网盘的时候,经常会碰到百度网盘的yunshellextv164.dll删不掉
方法:电脑重启——>打开yunshellextv164.dll所处的文件夹——>复制到火绒文件粉碎中进行粉碎——粉碎成功
删除成功
最近,我们项目组的工作接近尾声,需要把项目部署上线。由于前端第一次使用Nuxt3框架,后端也是第一次部署Nuxt3项目,所以刚开始出现了很多问题。在我上网搜索很多教程后,得到了基本的流程。
1.服务器安装node.js环境 Nuxt3官方文档https://nuxt.com/docs/getting-started/installation通过官方文档我们可知,nuxt3要求nodejs 环境在16.10.0v以上
1.下载安装包
# 下载到当前文件夹(可以访问https://nodejs.org/dist/这个地址选择源) wget https://nodejs.org/dist/v16.14.0/node-v16.14.0-linux-x64.tar.xz 2.解压
# 解压到当前文件夹 tar xf node-v16.14.0-linux-x64.tar.xz 3.建一个node文件夹并且把解压的文件夹移动到当前目录
mv node-v16.14.0-linux-x64 /usr/local/node 4.配置环境变量
# 编辑配置文件 vim /etc/profile # 在profile文件末尾添加(移动的位置) export NODEJS=/usr/local/node export PATH=$NODEJS/bin:$PATH 5.保存后重新加载配置
source /etc/profile 6.检查nodejs是否配置成功
node -v 出现版本即代表安装成功
7.配置淘宝镜像并查看是否成功
# 配置淘宝镜像 npm config set registry=https://registry.npmmirror.com/ # 检测是否切换成功 npm config get registry 2.安装Nuxt3的运行管理工具 pm2 npm install pm2 -g 3.将前端打包好的 .output 文件上传到服务器 上传成功后可能 ls 不显示,这个时候可以 ls -a 一下,就可以发现 .output 文件了
4.配置ecosystem.config.js文件 如果要使用pm2 管理运行项目,需要在根目录下配置 ecosystem.
目录
目录
1.收藏与取消收藏切换
2.使用layui插件下拉选择渲染问题
1.收藏与取消收藏切换 说明:从接口中获取收藏状态,单击切换状态,如下图所示:
开始状态:
点击后状态:
代码实现:
1、全局定义一个变量,记录状态:var collect_flag = false;
2、获取接口中的字段状态:collect_flag = head.is_collect;//head.is_collect为接口中返回的字段
3、页面展示:(由于开发中都是使用append添加上的,所以定义了变量a,然后添加到节点)
if(head.is_collect ==false){ a+=`<img class ="collect_img" src="../static/image/icon/shoucang.png"/> <span class = "collect_text">收藏</span> ` }else{ a+=`<img class ="collect_img" src="../static/image/icon/shoucang_select.png"/> <span class = "collect_text">取消收藏</span> ` } 代码截图:
4、 添加点击事件:
//操作收藏/取消收藏 function collect(tender_unid){ if(collect_flag){ $(".collect_img").attr("src","../static/image/icon/shoucang.png"); $(".collect_text").text("收藏"); }else{ $(".collect_img").attr("src","../static/image/icon/shoucang_select.png"); $(".collect_text").text("取消收藏"); } collect_flag = !collect_flag; //之后调用接口,将相应值传过去即可 } 2.使用layui插件下拉选择渲染问题(第二次下拉仍是第一次的值) 说明:jq开发使用的是layui插件,使用layui.dropdown做联动的时候,第二次下拉显示的值仍是第一次的,如下:
选择一级工程荣誉-二级国家级-三级下拉荣誉类别如上, 如改变一级,二级,三级荣誉类别数据仍是上边,源部分代码如下(只截取部分代码示例):
修改后代码如下:
经测试实现了想要的效果。
YOLOv8依旧是Ultralytics的巨作,这是备受赞誉的实时对象检测和图像分割模型的最新版本。 YOLOv8 建立在深度学习和计算机视觉的前沿进步之上,在速度和准确性方面提供无与伦比的性能。 其流线型设计使其适用于各种应用程序,并可轻松适应从边缘设备到云 API 的不同硬件平台。 yolov8的推理速度对比如下,极大的提高了训练速度。
1、安装: 官方提供了两种形式的安装方法,这里如果只是玩玩的话建议使用是一种方法安装,为了扩展,开发的可以是第二种方法安装(本文采用的是第二种方法,为了更好的管理项目)
#方法一(建议) pip install ultralytics #方法二 git clone https://github.com/ultralytics/ultralytics cd ultralytics pip install -e . 2、使用yolov8: 这里也分为两种方法
1、命令行
example Syntax yolo TASK MODE ARGS
Where TASK (optional) is one of [detect, segment, classify]
MODE (required) is one of [train, val, predict, export, track]
ARGS (optional) are any number of custom 'arg=value' pairs like 'imgsz=320' that override defaults.
Trainyolo train data=coco128.yaml model=yolov8n.pt epochs=10 lr0=0.
EGE专栏:EGE专栏
目录 一、时间相关函数1. 延时函数1.1 delay_ms( ) 函数1.2 delay( ) 函数 2. 帧率延时3.4. 程序运行时间计时倒计时 一、时间相关函数 1. 延时函数 延时函数的作用是使后面的代码延迟一段时间再执行,此时程序犹如被按下了暂停键,时间过后才会恢复(延时通常只影响当前线程)。
EGE 中的延时函数主要有三类:
① 纯延时函数
② 延时固定时间,附带刷新窗口内容的作用
③ 按照设定的帧率延时,延时时间自动调整而不固定,附带刷新窗口内容的作用
1.1 delay_ms( ) 函数 平均延迟以毫秒为单位的时间, 附带刷新窗口内容。
delay_ms(time); 1.2 delay( ) 函数 至少延迟以毫秒为单位的时间。只延时,不会刷新窗口内容。
delay(time); 2. 帧率延时 附带刷新窗口的作用延迟以 FPS 为准的时间,以实现稳定帧率 delay_fps(fps); 延迟以 FPS 为准的时间,以实现稳定帧率(带跳帧) delay_jfps(fps); 使用示例,用来稳定帧率,设定一秒钟循环60次(实际受一个循环的执行时间影响) for ( ; is_run(); delay_fps(60)) { } 3. 纯延时,不会附带刷新窗口的作用
api_sleep() 可以用于延时,内部实际上调用的是 Windows API中的 Sleep() 函数。
VOID api_sleep(long dwMilliseconds); dwMilliseconds 要延迟的时间,以毫秒为单位 4.
一、快速排序的介绍 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。(其时间复杂度最优为N*logN,空间复杂度最优为lonN,这里就不予证明了!过程相当复杂!)
用一种通俗的话来讲快速排序其实就时设定一个界定值,然后分别开始遍历需要排序的元素,将小于该界定值和大于该界定值的放在其两侧,每次结束都能将该界定值放到其最终正确的位置!
二、快速排序的思想 快速排序其思想也是采用了分治的思想,将一个大问题转化为若干个小问题,然后逐个解决每个小问题,最终达到解决问题的目的!
三、快速排序的实现 由上面内容可以知道,若想实现快速排序,则可以先执行单个元素的排序,然后再进行递归处理解决整组数据的排序!因为快速排序是一种二叉树结构的交换排序,所以可以采用递归的方法将其解决!
下面来看一下如何实现单趟排序,让数据中一个元素位于其最终应处于的位置!
单趟排序的实现 注:本篇文章例子是以默认排升序,若要实现降序仅需要将循环条件改变一下即可!
法一:(霍尔思想) 其单趟排序的思想就是假定一个界定值,然后左右两边开始遍历,若要排升序,则左边找到的比界定值大的值就停下,右边找到比界定值小的就停下,然后交换两者的值,当左右两边相遇时,就结束循环,最后将相遇的位置的值与界定值交换位置即可完成本次界定值的最终位置的实现!
//注意:因为这是单趟排序,保证了界定值处于该数据最终所在的位置,所以该函数应返回本次界定值的位置,方便下次调用这个函数实现递归调用解决其另外界定值最终的位置!
画个图来形象的描述一下该过程是如何实现的吧!
代码如下:
int Hoare(int* a, int left,int right) { int vali = left; while (left < right) { //若没有left<right这个限制条件,那么当从左边开始走的时候其对应的值一直小于a[vali]时,则会导致越界问题! //注意若选取vali在左边,那么从右边先走,因为从右边先走才能保证最后相遇的位置一定是小于vali的值,因为从右边找 //的话是找比val小于或等于的值停下来! while (left < right && a[right] >= a[vali]) { right--; } while (left < right && a[left] <= a[vali]) { left++; } swap(&a[left], &a[right]); } //因为最后left和right相遇,所以只需将a[vali]与二者任意一个交换位置即可! swap(&a[left], &a[vali]); return left; } 注意:(1)该函数的实现需要注意的是,必须保证里面的循环条件是left<right,因为假设当从左边开始时,其后面的值一直小于等于val时,则会导致left越界,进而导致程序错误!
(2)还需要注意一点的是,当选的界定值在左边时,那么必须从右边开始遍历,因为从右边先走可以保证最终左边相遇右边时,其遇到的右边一定是小于val的值,因为当最后左边和右边相遇时,还需要交换左边或右边的值与val的值,若交换的值大于val时,交换之后则没有排序成功,反之,若选的界定值在右边时,那么必须从左边开始遍历,原理同上!
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 第三方包名
例子
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspark pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scipy
https://baijiahao.baidu.com/s?id=1750888821840618173&wfr=spider&for=pc
先走上面链接哦
如果有yarn也要先把yarn卸载
所以我在使用yarn命令运行 的时候发生了node版本不兼容
然后启动项目还是启动不了,发现node版本跟sassnode版本也不兼容,
去更改了package.json里面的配置,(node-sass版本号和sass-loader版本号)
下面是node版本对应的node-sass版本号,最狗的是,node-sass还跟sass-loader版本不兼容,所以也要配置版本号,在下面
原来的
更改后的
最后更改完yarn 一下
目录会出现一个,yarn.lock文件
最后执行一次npm run serve
就成功啦.
目录
1.需求
2.问题
3.解决方法
1.需求 某个字段是级联选择器,如果只勾选了一级,就取一级;如果同时勾选了一级和二级,那结果只取二级;如果同时勾选了一级、二级和三级,那结果只取三级
结果传到后台的值为:["养殖区","鸡棚","E5001"]
预期的结果应该为:["E5001"]
先贴代码:
<el-form-item label="{:__('基地土地编号')}" prop="base_id"> <el-cascader :options="baseOptions" v-model="animalDetail.base_id" :show-all-levels="false"></el-cascader> </el-form-item> 2.问题 如图:选中的值为三级id
3.解决方法 增加change事件方法,处理选中的value值
贴代码:
<el-form-item label="{:__('基地土地编号')}" prop="base_id"> <el-cascader :options="baseOptions" v-model="animalDetail.base_id" @change="handleBaseValue" :show-all-levels="false"></el-cascader> </el-form-item> handleBaseValue(val){ this.animalDetail.base_id = val[val.length - 1]; }, 传值结果为:
前言 写代码的时候操作class对象的时候老是出现XXX::operator=(XXX&)...implicitly deleted的报错,直译过来就是class XXX的copy assignment这个操作被隐式删除,我们解决这个bug需要先了解C++class operator隐式删除的规则
定义 首先给出copy assignment operator隐式删除的规则的定义
A implicitly-declared copy assignment operator for class Tis defined as deleted if any of the following is true:
Thas a user-declared move constructor;Thas a user-declared move assignment operator. Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class Tis defined as deleted if any of the following is true:
Thas a non-static data member of non-class type (or array thereof) that is const;Thas a non-static data member of a reference type;Thas a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);Tis a union-like class, and has a variant member whose corresponding assignment operator is non-trivial.
目录
1 前言 2下载安装显卡驱动步骤 2.1禁用nouvwau 2.2重新建立initramfs image文件 2.3英伟达官网下载显卡驱动 2.4查看驱动包 2.5安装显卡驱动 2.6安装显卡驱动过程 2.7安装显卡驱动完成 3 下载安装CUDA步骤 3.1下载CUDA版本 3.2选择对应的版本 3.3下载安装CUDA 3.4安装CUDA过程 3.5选择安装CUDA功能 3.6安装CUDA完成 4下载安装gpu_burn步骤 4.1下载gpu_burn 4.2安装gpu_burn 4.3执行显卡压力测试 4.4实时查看显卡状态 1 前言 △ 操作在Windows系统使用ssh远程进入操作
△ 安装显卡驱动
△ 安装CUDA
△ 安装gpu_burn
2下载安装显卡驱动步骤 2.1禁用nouvwau 命令:echo -e "blacklist nouveau\noptions nouveau modeset=0" > /etc/modprobe.d/blacklist.conf
2.2重新建立initramfs image文件 命令:mv /boot/initramfs-$(uname -r).img /boot/initramfs-$(uname -r).img.bak
命令:dracut /boot/initramfs-$(uname -r).img $(uname -r) 2.3英伟达官网下载显卡驱动 (演示为RTX-A4000) 找到驱动链接可以使用命令:wget +链接下载,需要指定文件夹可CD进入指定文件夹后下载。2.4查看驱动包
可以使用命令:ls,查看文件夹内文件,查看到文件名后给显卡文件权限,给权限命令:chmod u+x 文件名,给完权限后显卡文件名变成绿色。2.5安装显卡驱动
重启centos8.5系统,开始安装显卡驱动,命令:./显卡驱动文件名2.6安装显卡驱动过程
安装过程中会有弹窗提示,一直默认选项敲击回车确认即可,安装完成后重启,验证驱动是否安装成功。
2.7安装显卡驱动完成 命令:nvidia-smi3 下载安装CUDA步骤
ActiveMQ介绍: Apache ActiveMQ 是 Apache 软件基金会所研发的一套开源的消息中间件,它支持 Java 消息服务、集群、Spring Framework 等。随着中间件的启动,会打开两个端口,61616 是工作端口,消息在这个端口进行传递;8161 是 Web 管理控制台。
ActiveMQ任意文件写入漏洞 ActiveMQ 的 web 控制台分三个应用:admin、api和fileserver,其中admin是管理员页面,api是接口,fileserver是储存文件的接口;admin和api都需要登录后才能使用,fileserver无需登录。
fileserver是一个RESTful API接口,可以通过GET、PUT、MOVE等HTTP请求对其中存储的文件进行读写操作,但后来发现其使用率并不高,并且容易出现漏洞。
所以,ActiveMQ在5.12.x~5.13.x版本中,已经默认关闭了fileserver这个应用(可以在conf/jetty.xml中开启);在5.14.0版本以后,彻底删除了fileserver应用。
漏洞详情: 本漏洞出现在 fileserver 应用中,漏洞原理很简单,就是 fileserver 支持写入文件(但不解析jsp),但是支持移动文件(MOVE请求)。我们可以将jsp的文件PUT到 fileserver 下,然后再通过Move指令移动到可执行目录下(admin和api),造成任意文件写入漏洞。
文件写入常用的有下面两种方式:
写入webshell写入cron或ssh key等文件 写入webshell的好处是,门槛低更方便,前面说了 fileserver 不解析jsp,admin和api两个应用都需要登录才能访问,所以存在默认用户登录的情况可以用这种;写入cron或ssh key,好处是直接反弹拿shell,也比较方便,缺点是需要root权限;
环境搭建: 靶场路径:
vulhub/activemq/CVE-2016-3088/ 启动容器:
docker-compose up -d 复现过程: 访问环境:
分别用两种方式复现一下。
1、写入webshell: 本环境的账号密码就是默认的 admin/admin。上传个文件到 fileserver看一下,发现 jsp 类型的文件上传失败,改为 txt 上传成功。(有些情况下是可以直接上传 jsp 的,但是解析不了还是要移动文件)
接着移动到 admin 或 api 路径下并改后缀名为jsp就行了,但是需要知道上传路径,可通过 /admin/test/systemProperties.jsp 查看 ActiveMQ 的绝对路径
移动到 api 下,并且改后缀名
书接上回:数据库调优方案中数据库主从复制,如何实现读写分离
ShardingSphere 实现读写分离的方式是通过配置数据源的方式,使得应用程序可以在执行读操作和写操作时分别访问不同的数据库实例。这样可以将读取操作分发到多个从库(从服务器),从而提高读取性能,同时将写操作发送到主库(主服务器)以确保数据的一致性。
引入依赖 <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.1.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>${mysql-version}</version> </dependency> 配置 # 读写分离配置 spring: shardingsphere: datasource: # 配置真实数据源 names: master,slave1,slave2 # 配置第 1 个数据源 master: driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/sso password: 123456 type: com.zaxxer.hikari.HikariDataSource username: root # 配置第 2 个数据源 slave1: driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/sso_test password: 123456 type: com.zaxxer.hikari.HikariDataSource username: root # 配置第 3 个数据源 slave2: driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://127.0.0.1:3306/slave_test password: 123456 type: com.
原链接如下:
https://www.processon.com/view/link/64e85fe76b2cbb581a3835bc 访问密码:afGw
如图:
一、栈 栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除操作的一端称为栈顶,另一端称为栈底,栈中的数据元素遵守后进先出的原则。
它的插入操作叫做进栈(或进栈/入栈),插入的数据在栈顶;删除操作叫做出栈。出的数据也在栈顶。
它主要通过数组来实现(其实数组或者链表实现均可,但相对而言数组更优),有静态栈和动态栈之分。静态栈拥有两个通过结构体封装的结构体成员——存储数据的定长数组和栈顶元素的下标。
#define N 10 struct Stack { int a[N]; int top; }; 和顺序表类似,存储数据的数组虽然可以由定长数组来充当,但有不确定的容量问题。所以,实际应用一般仍是以拥有动态数组的动态栈为主。 动态栈拥有三个通过结构体封装的结构体成员——存储数据的动态数组、空间容量和栈顶的相关下标,同时拥有一系列函数接口。
typedef int STDataType; typedef struct Stack { STDataType* a; //存储数据的动态数组 int capacity; //空间容量 int top; //栈顶的相关下标 }ST; void STInit(ST* ps); //初始化栈 void STPush(ST* ps, STDataType x); //入栈 void STPop(ST* ps); //出栈 bool STEmpty(ST* ps); //验空 int STSize(ST* ps); //获取有效数据个数 STDataType STTop(ST* ps); //访问栈顶元素 void STDestroy(ST* ps); //销毁栈 1、初始化栈 开辟动态数组的空间,并初始化空间容量和栈顶的相关下标。
void STInit(ST* ps) { assert(ps); //定义动态数组 ps->a = (STDataType*)malloc(sizeof(STDataType) * 4); if (ps->a == NULL) { perror("
文章目录 概要WSL介绍WSL安装安装环境安装方式一:命令行安装(不推荐,可能出现奇怪的问题)安装方式二:通过控制面板安装 WSL 安装Ubuntu22.04(通过Microsoft Store)Ubuntu更换镜像源进入Ubuntu更换镜像源 Ubuntu安装Docker问题处理使用WSL发现其无法ping通宿主机,也无法连接外网WSL迁移到其他磁盘问题描述解决办法 概要 本文主要记录Windows WSL的安装和使用过程,内容包括WSL安装过程、WSL安装Ubuntu、Ubuntu更换镜像源,Ubuntu安装Dcoker并配置等步骤。
WSL介绍 Windows Subsystem for Linux(简称WSL)是一个在Windows 10\11上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层。它是由微软与Canonical公司合作开发,其目标是使纯正的Ubuntu、Debian等映像能下载和解压到用户的本地计算机,并且映像内的工具和实用工具能在此子系统上原生运行。 [1-3]
如果使用Windows 10 2004以上,可以通过WSL 2来窗口化运行桌面应用,也不需要另外安装其他的X 服务器。
参考链接
WSL安装 安装环境 操作系统: Microsoft Windows 11 家庭中文版
版本号: 10.0.22621
虚拟化: 已开启
安装方式一:命令行安装(不推荐,可能出现奇怪的问题) 在cmd中输入: wsl --install
安装方式二:通过控制面板安装 windows+S,搜索控制面板,打开控制面板:控制面板->程序->启用或关闭Windows功能->适用于Linux的Windows子系统,进行勾选后,重启主机,WSL就安装好了。
WSL 安装Ubuntu22.04(通过Microsoft Store) 打开Microsoft Store搜索WSL,即可看到支持的操作系统,选择Ubuntu 22.04安装即可
Ubuntu更换镜像源 进入Ubuntu 打开win11最新的终端,选择Ubuntu 22.04,即可进入Ubuntu子系统。
更换镜像源 # 切换至root用户后,执行下述指令 # 备份旧的镜像源文件 $ mv /etc/apt/sources.list /etc/apt/sources.list.bk # 更换为阿里源 $ vi /etc/apt/sources.list deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse deb-src http://mirrors.
目录
一.思路模型见文末名片,比赛开始第一时间更新
二.国赛常用算法之主成分分析法(PCA)
三.MATLAB代码
代码相对简单,是从司守奎大神的《数学建模算法与应用》一书中学习到的,笔者只不过添加了一点注释,拾人牙慧,惭愧惭愧。将代码文件和txt文件放在一个文件夹中就可以。
四.国赛建模思路获取见此
一.思路模型见文末名片,比赛开始第一时间更新 二.国赛常用算法之主成分分析法(PCA) 主成分分析法(PCA)是一种高效处理多维数据的多元统计分析方法,将主成分分析用于多指标(变量)的综合评价较为普遍。笔者自从本科学习数学建模就开始接触该方法,但是一直没有系统地整理过,借这个机会总结一下,以备不时之需。
该方法的基本思想是运用较少的变量去解释原始数据中的大部分变异,通过对原始数据相关矩阵内部结构关系的分析和计算,产生一系列互不相关的新变量。根据需要从中选取比原始变量个数少的几个新变量,这些新的变量就是所谓的主成分,它们能够充分解释原始数据的变化。因此,主成分分析法本质上是一种降维方法,也多被用于高维数据的降维处理。
主成分分析的步骤:原始数据(X1,X2,⋯⋯, Xn)标准化,建立变量的相关系数阵,计算特征根和相应的特征向量,确定主成分的个数k(k<n),建立主成分(F1,F2,⋯⋯, Fk)的表达式,建立综合指标F的表达式。
数据
数据的形式一般为多个样本的多个指标,如下是18个输油管段在10个指标上的表现,即一个18*10的矩阵。将其保存到空白txt文件中并保存,作为程序的原始数据。下面的数据来源为论文《基于主成分-聚类分析法的管道风险评价方法》。
数据下载链接
链接:https://pan.baidu.com/s/18xfbTn16s-bEJwrNYpSpZQ 提取码:zy1f 三.MATLAB代码 代码相对简单,是从司守奎大神的《数学建模算法与应用》一书中学习到的,笔者只不过添加了一点注释,拾人牙慧,惭愧惭愧。
将代码文件和txt文件放在一个文件夹中就可以。 clc,clear data = load('gd.txt');%将原始数据保存在txt文件中 data=zscore(data); %数据的标准化 r=corrcoef(data); %计算相关系数矩阵r %下面利用相关系数矩阵进行主成分分析,vec1的第一列为r的第一特征向量,即主成分的系数 [vec1,lamda,rate]=pcacov(r); %lamda为r的特征值,rate为各个主成分的贡献率 f=repmat(sign(sum(vec1)),size(vec1,1),1); %构造与vec1同维数的元素为±1的矩阵 vec2=vec1.*f; %修改特征向量的正负号,使得每个特征向量的分量和为正,即为最终的特征向量 num = max(find(lamda>1)); %num为选取的主成分的个数,这里选取特征值大于1的 df=data*vec2(:,1:num); %计算各个主成分的得分 tf=df*rate(1:num)/100; %计算综合得分 [stf,ind]=sort(tf,'descend'); %把得分按照从高到低的次序排列 stf=stf'; ind=ind'; %stf为得分从高到低排序,ind为对应的样本编号 1 输出结果分析
代码输出的结果不少,下面按照主成分分析的步骤进行说明。可以结合运行结果来看这部分,表格不少就不贴了。
首先是数据标准化,主成分分析的结果直接受指标量纲的影响。由于各指标的单位可能不一样,因此进行量化评分得到的数据值大小也是不同的。如埋深的单位是米,相应指标在0.8到2.0之间,而人口密度指标的数据值在280左右,这样会导致分析结果的不准确。因此数据的标准化是主成分分析的前提条件,所以实际中可以先把各指标的数据标准化。标准化结果保存在data中。
完成数据的标准化后,对所得结果计算得到标准化数据的相关系数矩阵(相关系数矩阵保存在r中)。相关系数代表了不同指标之间的相关程度,绝对值越大代表相关性越高。相关性较高的变量之间存在信息上的重叠,信息重叠在很大程度上会影响评价结果的客观性,因此相关性矩阵可以证明进行主成分分析的必要性。
由相关系数矩阵可以计算出特征值与特征向量,计算得到与指标数量n相等的n个待选主成分。n个特征值代表了n个主成分对最终评价结果的贡献程度,特征值保存在lamda中,从大到小排列。主成分的特征向量为n*n的矩阵保存在vec1中,表示主成分和相应的原始数据的相关关系,其绝对值越大,则主成分对该指标的代表性越大。为了方便计算,修改特征向量的正负号,使得每个特征向量的分量和为正,即为最终的特征向量,特征向量保存在vec2中,每一列代表一个特征向量,对应一个主成分。
(待选择的)主成分——特征值——贡献率的对应情况见下表。
在主成分的选取上,对应的特征值大小是一个重要衡量因素,普遍的做法是保存特征值要大于1的主成分,舍弃特征值小于1 的主成分,因此最终的主成分个数会小于指标个数n。也可以根据贡献度大小,累计贡献度达到某个程度,不同标准有70%以上,85%以上或其他。这里选取所有特征值大于1的主成分,选取的主成分个数保存在num中,一共有3个。第1主成分对应的就是vec2中的第一列特征向量,以此类推,具体见下表。
将特征贡献率作为系数,对应的指标作为自变量,可以得出每一个主成分的计算表达式。将标准化数据Xi代入表达式,就可以得到对应的主成分值。形如(关于下面公式的生成,见文章MATLAB编写多元一次方程)
将特征值lamda作为系数,对应的主成分作为自变量,可以确定综合评价值的表达式,F=L1F1+L2F2+……+LkFk,即
带入之前求得的主成分值,得到每个样本的综合评价值(保存在tf中)。将综合评价值从高到低排序(保存在stf中),并输出对应的样本编号(保存在ind中)。
(注意:)有网友说最后综合主成分F的计算错了,很多资料和文献都是用的各个特征值占所提取主成分总的特征值之和的比例作为权重的。这一点大家注意甄别,建议多看看其他资料
四.国赛建模思路获取见此
linux启动jar包时,找不到报错
[root@ebs-141185 xl-admin]# java -Djava.library.path=/home/kabangke/xl-admin/lib -jar /home/kabangke/xl-admin/xl-admin.jar Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:587) Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 16 more 用的maven分离jar打包,没有指定lib目录
加上 -Dloader.path="lib/" 即可
nohup java -Dloader.path="lib/" -jar xl-agent.
报错内容如下 beyond the 'PHYSICAL' memory limit. Current usage: 9.7 GB of 8 GB physical memory used; 14.0 GB of 16.8 GB virtual memory used. Killing container. 经分析hive 执行过程,有3个job,stage-1使用17个mapper使用get_json_object函数处理数据job是执行成功的,处理的数据是一个json字符串。使用lateral view将json转成多列,json字符串总行数是3403397。
stage-3处理阶段只有1个mapper处理,通过日志发现执行过程是有失败重试的。
失败原因是单个container所需内存超过最大内存限制,json字符串中有两列数据是长字符,最大长度是505,初步定位原因是json被拆多列后,两列长字符占用较多内存。通过设置session客户端调大container内存后,hql执行成功。
u-button组件里:customStyle="样式数据名"
在data里申明样式数据名,形式为对象,注意值要加引号,且有-的只要改为驼峰命名如border-Radius
<u-button :customStyle="btnGetCode"></u-button> data(){ return { btnGetCode: { borderRadius: '7px',//驼峰命名注意 height: '34px' } } }
某快递公司邮寄快件的收费标准:每件重量不超过1公斤邮费10元。当超过1公斤时,超过部分每0.5公斤,加收3元,不足0.5公斤,按0.5公斤收费。编写程序,输入邮件重量,计算并输出应付邮费。
此代码适合python新手用来练手。
代码如下:
n=float(input()) a=n-1 if n<=1: print('10.0') elif a%0.5!=0: print(13.0+(a//0.5)*3) else: print(10.0+(a//0.5)*3)
前言 很多抓取最终SQL的方法,都是带着?的。比如:
SELECT value from sys_param where name=? 我们现在想把 ? 给去掉。有什么办法呢
方法1 编写工具类 (该方法有些情况下是不适用的,比如oracle数据库,该工具类就实测不生效),oracle或者其它数据库通用的生效方法见方法2.
工具类参考资料来源:https://www.cnblogs.com/wggj/p/12762648.html
工具类代码:
import oracle.jdbc.internal.OraclePreparedStatement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.PreparedStatement; import java.sql.SQLException; public class SqlUtil { public static final Logger logger = LoggerFactory.getLogger(SqlUtil.class); public static String getSql(PreparedStatement ps) { try { if (ps == null || ps.getConnection() == null) return null; switch (ps.getConnection().getMetaData().getDatabaseProductName().toUpperCase()) { case "ORACLE": OraclePreparedStatement ops = (OraclePreparedStatement) ps; ops.get return ops.getOriginalSql(); case "
vue文件
<template> <view class="invite"> <u-cell title="点击选则" isLink :value="value" @click="change()"></u-cell> <u-picker :show="show" ref="uPicker" :columns="columns" @confirm="confirm" @cancel="show=false" @change="changeHandler" :defaultIndex="defaultIndex"></u-picker> </view> </template> <script> import { address } from '@/static/js/address.js'; // const address = [] export default { data() { return { show: false, columns: [], origiData: address, //获取到的原始数据 value: "", // defaultIndex: [] }; }, mounted() { this.handelData(); }, methods: { change() { this.show = true; }, //初始化开始数据 handelData() { let sheng_s = '130000'; // 后端返回省市区编号 110000 北京市 130000 河北省 let shi_s = '131000'; // 后端返回省市区编号 110100 北京市 131000 廊坊市 let qu_s = '131082'; // 后端返回省市区编号 110101 东城区 131082 三河市 let sheng = []; let shi = []; let qu = []; this.
堆栈溢出问题 堆栈溢出出现的原因 路由重定向递归循环
RouterOS 是由拉脱维亚MikroTik 司开发的一 种基于Linux 内核的路由操作系统。RouterOS在具备现有路由系统的大部分功能,能针对网吧、企业、小型ISP接入商、社区等网络设备的接入,Mikrotik厂家提供带有RouterOS的硬件路由器,同时支持标准的x86构架PC。一台586PC机就可以实现路由功能,提高硬件性能同样也能提高网络的访问速度和吞吐量。完全是一套低成本,高性能的路由器系统。
MikroTik RouterOS是将标准的PC电脑变成功能强大的路由器,添加标准的PC网络接口卡能增强路由器的功能。MikroTik RouterOS基于路由、PPPoE认证、Web认证、流量控制、Web-proxy、专业无线等于一身 ,可以根据需要增加或删除相应的功能,是许多路由器所无法实现的。同时MikroTik RouterBOARD专门为RouterOS设计的路由硬件,能稳定的应用在各种网络环境中。
1、官网下载IGMP拓展包 要想在ROS中配置IPTV设置需要用到IGMP协议包,此拓展包需要的单独到Mikrotik官方网站下载。ROS 7.x版本以上已经默认集成可以不用安装,反之需要手动下载后安装。
注意: 1、选择跟自己设备相对应的拓展包;2、下载后解压,应该为xxx.npk结尾文件。
2、安装IGMP拓展包 拓展包的安装也非常简单,可通过ROS的Files拖拽文件上传或者upload按钮上传,后直接重启ROS路由器会自动加载安装。等重启后查看Routing下IGMP Proxy就说明已安装成功。
3、配置IPTV接口 配置IPTV接口,需要知道光猫iTV的vlan,此可以通过登录光猫后台查看光猫itv的配置获得,或者采用单线复用ITV线路的vlan值(此处假设使用vlan 99)。
如果光猫单线复用,需要为IPTV添加一个vlan来单独跟光猫链路建立通讯。
#单线复用命令 /interface vlan add name=vlan11 vlan-id=11 interface=WAN1 #互联网vlan11 add name=vlan3990 vlan-id=99 interface=WAN1 #IPTV的vlan99 如果直接用iTV接口网线连接过来,则无需配置vlan即可通讯。
另外需要单独指定一个IPTV出口。为了不混淆,标识了一下网口的出口名称。
4、创建IPTV网桥 通过Bridge为IPTV链路单独创建网桥,开启IGMP Snooping,配置IGMP和MLD版本号。
此处主要用于下层如果还需要接交换机设备的话,记录此版本值,保持交换机配置跟此版本值尽量一致,如果非网管型交换或者下行直连IPTV终端盒子可忽略。
然后通过ports选项将IPTV接入网口和下行网口分别添加到IPTV网桥,然后vlan选项中将PVID设置成IPTV vlan值99:
#单线复用命令 /interface bridge add name=WAN1 vlan-filtering=yes pvid=11 add name=iTV-LAN vlan-filtering=no igmp-snooping=yes /interface bridge port add bridge=WAN1 interface=vlan11 pvid=11 add bridge=iTV-LAN interface=vlan99 pvid=99 add bridge=iTV-LAN interface=iTV-out pvid=99 最后给vlan99(单独复用接口)或者IPTV桥配置一个固定IP地址
背景 我们经常使用Gradle中task任务,比如依赖,打包脚本等等主动触发场景,高版本中默认关闭了任务。不知道处于什么原因考虑的。
默认情况 task不在全部显示。
解决方案 进入设置中的最后一栏,勾选这个配置:
点击Apply再点击OK,会到项目,点击同步一次。
同步完成之后,可以看到全部task了。
目录
一、顺序表的问题
二、 链表
· 无头单向非循环链表
1、打印单链表
2、动态申请一个新节点
3、尾插
4、头插
5、尾删
6、头删
7、查找
8、pos前插入
9、pos处删除
10、pos后插入
11、pos后删除
12、销毁链表
· 一些小tips
· 代码汇总
· 带头双向循环链表 1、动态申请一个节点
2、创建一个只有头节点的双向链表
3、打印双向链表
4、验空
5、pos位置(前)插入
6、pos位置删除 7、尾插
8、尾删
9、头插
10、头删
11、查找
12、销毁链表
· 代码汇总 [补] 顺序表和链表的区别
一、顺序表的问题 上篇博客陈述了顺序表,是线性表的一种,本博客将陈述另一种常见的线性表——链表。
顺序表虽然在存储数据时较为方便,但仍存在一些问题:
1. 顺序表中间/头部的插入和删除效率较低(时间复杂度为O(N))
2. 动态数组增容时需要申请新空间、拷贝数据、释放旧空间,会造成不小的内存消耗。
3. 增容一般以2倍增长,这样势必会有一定的空间浪费。(例如当前容量为100,满了以后增容到200,但如果此时只需要再继续插入了5个数据即可,那么就浪费了95个数据空间。)
为了解决以上问题,前人创造了一种新的线性结构来存储数据,它就是链表。 二、 链表 链表是一种物理结构上非连续、非顺序的存储结构,其中的数据元素的逻辑顺序由其中的指针链接次序实现,指针链接的每一个结构体都是一个节点。
链表的结构多种多样,有单向或双向、带头或不带头、循环或非循环之分。
· 单向或双向
· 带头或不带头
· 循环或非循环
但实际中,最常用的是以下两种组合:
· 无头单向非循环链表
· 带头双向循环链表
本博客主要梳理以上两种链表,且通过C语言来模拟实现。
· 无头单向非循环链表 struct SListNode { int data; struct SListNode* next; } 无头单向非循环链表又简称单链表。
这里记录一下使用大佬的模板vue-admin-template,实现按钮级别控制
实现的思路:用户登录之后,返回用户详细信息(将用户的所有权限码发送给前端),然后将权限码保存在全局状态管理对象中,然后在组件中进行判断是否显示
最后,你就可以通过这个值 v-if 进行判断某些按钮是否显示
springboot自动装配原理 1、springboot自动装配的作用2、springboot怎样做到的自动装配(浅谈自动装配原理)2.1@SpringBootConfiguration2.2@ComponentScan2.3@EnableAutoConfiguration(重点)2.3.1@AutoConfigurationPackage2.3.2@Import({AutoConfigurationImportSelector.class})2.3.3按需开启自动配置项2.3.3.1、aop的自动配置案例 2.3.4如何查看自动配置了哪些呢2.3.4.1自己分析,pom.xml文件引入场景对应的自动配置一般都生效了2.3.4.2application.properties文件中配置debug=true就能在控制台打印出来自动配置报告 1、springboot自动装配的作用 springboot的自动装配实际上就是为了从spring工厂文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给spring容器来帮我们进行管理。
2、springboot怎样做到的自动装配(浅谈自动装配原理) 众所周知,@SpringBootApplication注解标明这个类是主配置类,它是一个组合注解,springboot通过运行这个类里面的main()方法来启动程序。
@SpringBootApplication public class AdminApplication { public static void main(String[] args) { SpringApplication.run(AdminApplication.class, args); } } 这个注解主要由三个子注解组成:
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan 下面我们来逐个讲解
2.1@SpringBootConfiguration j进入到SpringBootConfiguration类中发现,它被@Configuration注解标明,说明其实它就是个配置类
2.2@ComponentScan 指定要扫描哪些包
2.3@EnableAutoConfiguration(重点) 也是一个合成注解
2.3.1@AutoConfigurationPackage 自动配置包
给容器注入Register组件
通过Register给容器导入一系列组件,那么是怎么做到的呢,见下方step分解
step1:
AnnotationMetadata metadata
参数传的是这个注解的源信息,比如这个注解标注在哪里。
step2:
(String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0])
获取到标注的主类的包名
也就是通过registerBeanDefinitions这个方法,将某个包下的所有组件,全部注入进去。MainApplication所在包下。
2.3.2@Import({AutoConfigurationImportSelector.class}) step1:要给容器里面导入哪些,看这个selectImports方法返回的string数组里面有哪些,就导入哪些。
step2:
利用getAutoConfigurationEntry(annotationMetadata)]给容器批量导入组件
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
这127个全类名组件就是默认要导入到容器中的。
那么怎么知道这127个组件就是这个导入规则呢?
step3:进入到getCandidateConfigurations方法中,再层层向内进入,最终由loadSpringFactories方法加载得来所有组件。那么究竟是从哪里加载得来这些组件呢,继续往下看
step4:
从"META-INF/spring.factories"位置来加载一个文件,
所以就会默认扫描当前系统下,所有"META-INF/spring.factories"目录下的文件。
并不是所有的包下面都有这个目录,例如:
最核心的是这个包
spring-boot-autoconfigure-2.3.4.RELEASE.jar。那127个需要加载的组件,实际上是在这里写死的。
文件里面写死了,只要springboot一起动,就要给容器加载的类
其实就是在配置文件里面写死了,springboot一起动就要给容器中加载的所有配置类。
step4:虽然127个场景的自动配置springboot一股脑全加载了,但是哪些生效哪些不生效,按照条件装配规则(@Conditional),最终会按需配置,那么接下来就要了解下“按需配置”了。
2.3.3按需开启自动配置项 用两个案例来解释下
nginx.conf配置 找到Nginx的安装目录下的nginx.conf文件,该文件负责Nginx的基础功能配置。
配置文件概述 Nginx的主配置文件(conf/nginx.conf)按以下结构组织:
配置块
功能描述
全局块
与Nginx运行相关的全局设置
events块
与网络连接有关的设置
http块
代理、缓存、日志、虚拟主机等的配置
server块
虚拟主机的参数设置(一个http块可包含多个server块)
location块
定义请求路由及页面处理方式
配置文件示例 一个比较全的配置文件示例如下。
# 全局段配置 # ------------------------------ # 指定运行nginx的用户或用户组,默认为nobody。 #user administrator administrators; # 设置工作进程数,通常设置为等于CPU核心数。 #worker_processes 2; # 指定nginx进程的PID文件存放位置。 #pid /nginx/pid/nginx.pid; # 指定错误日志的存放路径和日志级别。 error_log log/error.log debug; # events段配置信息 # ------------------------------ events { # 设置网络连接序列化,用于防止多个进程同时接受到新连接的情况,这种情况称为"惊群"。 accept_mutex on; # 设置一个进程是否可以同时接受多个新连接。 multi_accept on; # 设置工作进程的最大连接数。 worker_connections 1024; } # http配置段,用于配置HTTP服务器的参数。 # ------------------------------ http { # 包含文件扩展名与MIME类型的映射。 include mime.types; # 设置默认的MIME类型。 default_type application/octet-stream; # 定义日志格式。 log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; # 指定访问日志的存放路径和使用的格式。 access_log log/access.
杂症1:XXX.whl is not supported … 报错长以下这样 ERROR: Failed building wheel for XXX-ERROR: xxx.whl is not a supported wheel on this platform. 解决方案 去清华源地址找到对应的包下载到自定义文件夹并解压
快速查找:https://pypi.tuna.tsinghua.edu.cn/simple/xxx xxx为你的包名cd 到解压的包里边执行 python setup.py install成功 其他问题大多数可以通过升级pip或者换源解决,欢迎留言你遇见的各种pip安装问题,我会定期在这里更新解决方案
目录
LCD液晶显示屏介绍
液晶的组成
物理特性
液晶显示屏内部构造
颜色深度
点亮LCD显示屏
查看原理图
图片显示
保存到工程用户代码的Inc目录下
参数为数组名
字符显示 汉字显示
LCD液晶显示屏介绍 液晶的组成 某些物质在熔融状态或被溶剂溶解之后,尽管失去固态物质的刚性,却获得了液体的易流动性,并保留着部分晶态物质分子的各向异性有序排列,形成一种兼有晶体和液体的部分性质的中间态,这种由固态向液态转化过程中存在的取向有序流体称为液晶。
物理特性 当通电时导通,排列变得有秩序,使光线容易通过,;不通电时排列混乱,阻止光线通过。
液晶显示屏内部构造 颜色深度 RGB三基色组合形成各种颜色。
能显示的颜色数由RGB的数字信号位数来决定。
例如:
以三位数字信号来表示颜色深度
RGB24表示的意思是(24位真彩色)
R:8
G:8
B:8
所以能显示的颜色深度就是 2^8 *2^8 *2^8
STM32G030开发板板载的显示屏是RGB16也称为RGB565,其颜色深度为: 2^5 *2^6 *2^5,是由一个16位的数据控制一个像素点的颜色显示。
让一个像素点显示正红色: 1111 1000 0000 0000 0XF800
让一个像素点显示绿色:
0000 0111 1110 0000 0X07E0
点亮LCD显示屏 查看原理图 图片显示 保存到工程用户代码的Inc目录下 参数为数组名 字符显示 英文字符、数字字符和标点符号已经在font.h中已经生成好了字模,因此不需要再次取模,直接调用字符串显示函数即可。
字符是16*8
汉字显示
问题描述 今天使用 arthas 监控线上问题时,遇到一种情况,无论如何也无法监控到该方法。报错如下:
[arthas@66764]$ watch xxxx.getSql '{params,returnObj,throwExp}' -n 5 -x 3 il getSql '{params,returnObj,throwExp}' -n 5 -x 3n.util.SqlUt Affect(class count: 0 , method count: 0) cost in 21 ms, listenerId: 19 No class or method is affected, try: 1. Execute `sm CLASS_NAME METHOD_NAME` to make sure the method you are tracing actually exists (it might be in your parent class). 2. Execute `options unsafe true`, if you want to enhance the classes under the `java.
一.单例模式 单例模式是一种常见的设计模式,用于确保一个类只有一个实例,并提供全局访问点来获取该实例。在单例模式中,通过限制类的实例化过程,可以防止多个实例的创建,从而保证所有代码都使用同一个实例。
注意
1、单例类只能有一个实例。2、单例类必须自己创建自己的唯一实例。3、单例类必须给所有其他对象提供这一实例。 单例模式的几种实现方式 1、懒汉式,线程不安全 这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
//懒汉式,线程不安全 public class Singleton_Demo01 { private static Singleton_Demo01 instance; // 私有化构造方法,防止外部创建实例 private Singleton_Demo01() { } // 私有化构造方法,防止外部创建实例 public static Singleton_Demo01 getInstance() { if (instance == null) { instance = new Singleton_Demo01(); } return instance; } } 2、懒汉式,线程安全 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。 //懒汉式,线程安全 public class Singleton_Demo02 { private static Singleton_Demo02 instance; // 私有化构造方法,防止外部创建实例 private Singleton_Demo02() {} // 只有在首次调用时才创建实例 public static synchronized Singleton_Demo02 getInstance() { if (instance == null) { instance = new Singleton_Demo02(); } return instance; } } 3、饿汉式(Eager initialization) 这种方式比较常用,但容易产生垃圾对象。
背景:在celery中多worker下多进程并发的情况下,对有些公共数据涉及到进程安全问题,所以需要对这些数据进行加锁操作。
在Python中threading是多线程,而mutiprocessing是多进程。我们这里多worker采用的是mutiprocessing
1. 创建一个锁
lock = multiprocessing.Lock()
2. 获取锁
lock.acquire()
3. 保证redis中num对应值的安全性
Redis.write("num", str(int(Redis.read("num")) + 1), 60 * 60)
4. 释放锁
lock.release()
以下为示例代码
from celery import Celery import random import logging import time import rpy2.robjects as robjects from app.utils.util import Redis import multiprocessing celery_app = Celery(__name__) logger = logging.getLogger(__name__) # 1. 创建一个锁 lock = multiprocessing.Lock() @celery_app.task def test_task(x): logger.info(str(x) + '---start: ' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) robjects.r(''' Sys.sleep(1) print("-------------x--------------") print(%s) ''' % x) time.
文章目录 场景字段对比 自定义注解字典对比枚举类测试对象接口性别实现类对象对比工具类单元对比测试一:简单对象对比单元对比测试二:复杂对象对比使用了字典对比效果亮点细节可扩展性 场景 在很多情况下,尤其是单表的版本控制的时候,需要记录后台人员的操作日志,通常是用到两个java对象去坐对比,告诉后台人员,改了哪些字段,就好比[名字:李四->张三],名字由原来的李四变成了张三。那么不废话了,直接亮出我反射结合注解写的对象对比工具。
字段对比 自定义注解 import java.lang.annotation.*; /** * 字段比较注解 * @author liaoqian * @since 2023/8/11 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface FiledCompara { String value() ; FiledComparaTypeEnum type() default FiledComparaTypeEnum.DEFAULT; } 字典对比枚举类 import lombok.Getter; @Getter public enum FiledComparaTypeEnum { DEFAULT("default", null), SEX("sex", new SexFiledComparaType()); private String type; private IFiledComparaType filedComparaType; FiledComparaTypeEnum(String type, IFiledComparaType filedComparaType) { this.type = type; this.filedComparaType = filedComparaType; } public boolean isDefault() { return DEFAULT.
在Java中,将两个double值转换为String类型,然后使用equals方法进行比较是一个常见的做法,但是这种方法并不是完全可靠,特别是在涉及浮点数的精度时仍然可能会遇到问题。
浮点数在内部以二进制表示,有时会存在舍入误差,这可能会导致两个在数值上非常接近的浮点数在转换为字符串后变得稍有不同。因此,尽管你可以使用字符串比较来避免直接比较浮点数时的精度问题,但这种方法并不是绝对可靠的。
以下是一个示例,展示了使用字符串比较来判断两个double值是否相等:
public class DoubleStringComparison { public static void main(String[] args) { double x = 0.1 + 0.2; double y = 0.3; String xStr = Double.toString(x); String yStr = Double.toString(y); if (xStr.equals(yStr)) { System.out.println("They are equal."); } else { System.out.println("They are not equal."); } } } 虽然这种方法可以避免直接比较浮点数时的精度问题,但是需要注意的是,由于字符串表示法可能会引入额外的舍入或转换误差,因此在某些情况下,仍然可能会得到错误的结果。
在许多编程语言中,使用浮点数(例如double类型)进行相等性比较时可能会遇到精度问题。由于浮点数的存储方式和精度表示的特性,直接比较两个浮点数是否相等可能会导致意外的结果。因此,在判断两个double类型的值是否相等时,应该使用一些容忍误差的方法。
一种常见的方法是使用一个很小的阈值(epsilon)来比较两个浮点数的差异,如果它们的差异小于这个阈值,则认为它们是相等的。这个阈值通常取决于你的应用场景和需要的精度。
以下是一个Java示例:
public class DoubleComparison { public static boolean areEqual(double a, double b, double epsilon) { return Math.abs(a - b) < epsilon; } public static void main(String[] args) { double x = 0.
目录 1.自定义枚举类2.自定义统一返回格式类3.统一返回格式的高级实现4.全局异常处理5.更优雅的全局异常处理6.处理404错误 1.自定义枚举类 public enum ReturnCode { RC200(200, "ok"), RC400(400, "请求失败,参数错误,请检查后重试。"), RC404(404, "未找到您请求的资源。"), RC405(405, "请求方式错误,请检查后重试。"), RC500(500, "操作失败,服务器繁忙或服务器错误,请稍后再试。"); // 自定义状态码 private final int code; // 自定义描述 private final String msg; ReturnCode(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } } 该枚举类为我们和前端约定好的返回状态码和描述信息,可根据自己的需求修改状态码和描述
2.自定义统一返回格式类 @Data public class R<T> { private Integer code; //状态码 private String msg; //提示信息 private T data; //数据 private long timestamp;//接口请求时间 public R() { this.
逆向是一种分析和还原应用程序的过程,它能够揭示应用程序内部的工作原理和代码结构。接下来我们将全面介绍iOS上的逆向,包括其概念、常用工具和具体实例。
1. 什么是iOS逆向? iOS平台逆向是将应用程序的二进制代码(通常是经过编译的)还原为源代码的过程,从而揭示应用程序的内部工作机制。逆向工程师可以通过分析应用程序的代码、数据结构和算法,深入了解应用程序的设计和功能。这对于开发者来说,有助于学习新技术和优化代码;对于安全研究人员来说,有助于发现潜在的漏洞和安全风险。
2. iOS逆向的基本流程 iOS逆向的一个基本流程如下:
(1)获取应用二进制文件: 首先,需要从目标设备或App Store中获取应用的二进制文件(通常是ipa文件)。
(2)解析二进制文件: 使用工具如Hopper Disassembler、IDA Pro等,将二进制文件转换成可读的汇编代码,以便分析。
(3)分析代码结构: 阅读汇编代码,了解应用程序的逻辑、类和方法。这一步骤需要逆向工程师对汇编和Objective-C有一定的了解。
(4)识别关键函数: 找到应用程序中处理关键逻辑的函数,如验证、加密、网络通信等。
动态调试: 使用动态分析工具(如Cycript、LLDB等),在应用运行时观察和修改代码的执行过程。
(5)修改代码: 针对特定需求,通过修改汇编代码、方法调用参数等方式,改变应用程序的行为。
(6)编译和测试: 将修改后的代码重新编译,生成新的可执行文件,并在测试环境中验证修改效果。
3. 逆向所需工具 iOS平台逆向涉及一系列工具,用于分析和修改应用程序。以下是一些常用工具:
Hopper Disassembler: 这是一款功能强大的反汇编工具,可以将应用程序的二进制代码转化为汇编代码。它使逆向工程师能够理解程序的执行流程和底层逻辑。
IDA Pro: 类似于Hopper,IDA Pro也是一款广泛使用的静态反汇编工具。它提供深入的代码分析功能,包括高级的代码导航和交叉引用分析。
Cycript: 这是一款强大的动态分析工具,允许开发者在应用程序运行时与其进行交互。使用Cycript,可以实时修改变量、调用函数,并动态查看应用程序的视图层次结构。
class-dump: 这是一款用于提取Objective-C类定义的工具,帮助逆向工程师了解应用程序中使用的类和方法。
4. 逆向可以做什么 俗话说知己知彼百战百胜。iOS开发学习逆向工程的研究对于深入了解应用程序内部机制、提升技术能力、发现安全漏洞、创新定制、加强安全防御等领域具有重要价值。通过逆向,我们能够探索隐藏在二进制代码背后的算法、逻辑和设计,从而学习新技术、改进安全性,甚至开发插件、扩展应用功能。此外,逆向研究有助于理解攻击方式、设计反制措施,以及在教育和学术研究中应用。
示例一:微信抢红包插件
微信抢红包插件是一个广受欢迎的iOS应用程序扩展,它能够自动检测并抢夺微信聊天中的红包。这是一个典型的逆向示例,因为它需要分析微信应用的通信协议和红包逻辑。
实现这样一个插件需要使用工具进行动态分析,例如通过Cycript监视微信进程,并找到处理红包的函数。以下是一个简化的示例代码:
Class targetClass = NSClassFromString(@"MessageViewController"); Method originalMethod = class_getInstanceMethod(targetClass, @selector(onReceiveRedPacket:)); IMP newImplementation = imp_implementationWithBlock(^void(id _self, id redPacket) { // 修改红包逻辑,自动领取红包 [self performRedPacketHack:redPacket]; // 调用原始方法 ((void (*)(id, SEL, id))originalMethod)(_self, @selector(onReceiveRedPacket:), redPacket); }); // 将新方法替换原始方法 method_setImplementation(originalMethod, newImplementation); 示例二:Pokemon Go 的模拟定位
先上整体代码
text.sh
#!/bin/bash # 设置收件人邮箱 to="123456@qq.com" # 设置发件人邮箱 from="21331@qq.com" # 设置邮件主题 subject="Test Email" # 设置邮件内容 body="This is a test email." # 发送邮件 echo "${body}" | mail -s "${subject}" -r "${from}" "${to}" 再说详细配置,以及思路
一.配置qq邮箱(需要生成授权码)
QQ邮箱-POP服务开启步骤:
1、使用电脑登录mail.qq.com,进入【设置】;
2、换到【账户】选项;
3、在POP3/IMAP… CalDAV服务下,将【POP3/SMTP服务】开启;
4、通过扫一扫/一键验证/手机令牌/短信验证方式获取授权码,并记住此授权码
(注:若POP3/SMTP已开启,直接点击生成授权码,使用授权码登录第三方客户端。用于登录TIM);
5、将收取选项从最近30天改为全部,并勾选以下四个选项;
6、点击【保存更改】完成设置,使用授权码登录邮箱。 二.配置linux环境
1.直接运行以下命令自动追加内容
#未加密的发送方式通过25端口,会被公有云封掉. cat >>/etc/mail.rc <<EOF set from=12121@qq.com set smtp=smtp.qq.com set smtp-auth-user=12121@qq.com set smtp-auth-password=授权码 set smtp-auth=login EOF #加密的方式465端口 cat >>/etc/mail.rc <<EOF set nss-config-dir=/etc/pki/nssdb/ #加密方式配置 set smtp-user-starttls #加密方式配置 set ssl-verify=ignore #加密方式配置 set from=12121@qq.
这里是记录一下使用poi过程中出现的一个问题
文章目录 一、问题复现二、解决思路1.是否文件加密2.编译后的模板文件内容是乱码 总结 一、问题复现 新建一个导出模板之后,放到项目,然后获取模板文件进行处理,结果一直获取不到模板文件。
二、解决思路 1.是否文件加密 因为公司电脑是有加密软件的,一些文档编辑之后会加密。在target目录下找到该模板文件,打开文件,提示文件已被损坏。然后申请解密,解密之后放到项目里,重新编译,这时在target目录下打开的模板文件可以打开,但是文件内容是乱码。
2.编译后的模板文件内容是乱码 重新编译项目,在target目录下找到该模板文件,文件内容是乱码。这个是maven编译项目时因为编码不同导致的,需要在pom.xml里设置maven编译时使用的编码方式,以及不对特定文件进行编码。代码如下。
<configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>doc</nonFilteredFileExtension> <nonFilteredFileExtension>docx</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> 完整位置如下:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>UTF-8</encoding> <nonFilteredFileExtensions> <!--过滤掉不需要编码的文件:过滤后缀为 .doc、.xlsx。。。 的所有文件,不对其进行统一编码--> <nonFilteredFileExtension>doc</nonFilteredFileExtension> <nonFilteredFileExtension>docx</nonFilteredFileExtension> <nonFilteredFileExtension>txt</nonFilteredFileExtension> <nonFilteredFileExtension>ftl</nonFilteredFileExtension> <nonFilteredFileExtension>xls</nonFilteredFileExtension> <nonFilteredFileExtension>xlsx</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </build> 总结 重新编辑项目,打开target目录下的模板文件,可以正常打开并显示文档内容。运行项目,报错解决。
Linux开发工程师怎么样?都说程序员是吃青春饭,Linux开发工作35岁之后还能做吗?
坦白说,如果程序员在35岁的时候,“工作经验”与刚毕业的时候差别不大,则其不可替代性就不高,很难在大龄时具备足够竞争力。大龄程序员,跟应该以专业洞识,理解深邃,广度思维,来完善自己的行业竞争力。
遇到问题到处喊救命很多程序员,一旦出现问题,比如程序死了不动,甚至编译不过,他的第一反应是找高手去问,去求证。也有的稍微debug了一下之后,就开始寻求帮助,比如转向公司的高手,转向各种各样的微信群,转向找高手帮他指点一条明路。这是让自己成功失业的良好习惯。
记住,遇到问题就绞尽脑汁地思考、查阅资料、尝试调试和解决,而不是到处去各个微信群问、找牛逼的同事问。当你碰到问题之后,独立分析和解决,把问题的来龙去脉理个一清二楚,这个过程中,获得的经验值是花再多钱,问再多问题也获取不了的。
如果你不能在知识的广度上面成就自己,每天盯着自己的几行代码,甚至基本的平台知识都不具备,一旦你从事的领域不再热门,这个时候,就可能面对就业市场紧缩的痛苦,而你别无他途,这样,35岁成功迷茫,危机四伏的概率就较高。
反之,哪怕你就是搞一个驱动,但是你会尝试去理清里面所有的同步互斥,理清这一层软件和上一层软件的关系,理清app如何系统调用到你的代码,甚至领悟出软件设计的高内聚和低耦合,这个时候,你虽然是个螺丝钉,但是你时刻在把自己培养为金刚钻。
“天亡我,非用兵之罪也”,“我是大龄码农,所以没人要”,这是借口,不是理由。从来让我们危机四伏的,只有我们自己。所以你还觉得Linux开发工程师是吃青春饭的吗?
收藏关注不迷路
文章目录 前言一、项目介绍二、开发环境三、功能介绍1 普通用户模块2 实验室管理员模块 四、核心代码五、效果图六、文章目录 前言 本文通过信息化管理中预约管理方向进行探究,设计一款实验室预约管理系统,来填补教学示范中心在实验室预约管理方向的空缺,推动本校教学示范中心的发展。是提高教学质量,整合、共享教学资源,深化实验教学改革的重要途径。本预约管理系统可以实现对实验室预约的网络化、信息化管理,能够将学生和教师从繁琐的过程中解放出来。学生可以随时随地查看实验室信息,按自己需求预约。管理人员可以通过网络审批,大幅度加快了审核的速度,减少了管理人员的工作量,提高了实验室资源的利用率。
本系统采用token的登录方式,采用JWT标准,其中token中只包含用户的id和姓名信息,不会暴露用户的密码,联系方式等隐私。此外,能够根据token判断用户身份权限,不会出现用户越级审批的情况。用户的密码也采用MD5加密存储。使用 IntelliJ IDEA 作为开发工具来开发实验室预约管理系统。系统主要分为前后两个部 分,其中前端为普通用户使用,主要包括个人管理和预约服务。后端部分为系统管理员使用,对实验室进行全局把控, 主要功能包括,用户管理,预约管理,设备管理和统计查询。
本系统开发的初衷是促进本校教学示范中心信息化管理平台的建设,为本校师生提供一个实验室预约的平台,让学生能了解到实验室信息并预约,同时提高审核速度以提高实验室资源利用率。盈利并不是本系统的主要目的,若能投入使用,可以寻求学校方赞助,支付日常运行和维护的费用。开发一款实验室预约管理系统,解决当前学校存在的实验室信息不透明,实验室空余时间不清晰,预约实验室过程繁琐费时的问题。提高实验室利用率。
一、项目介绍 开发一款实验室预约管理系统,解决当前学校存在的实验室信息不透明,实验室空余时间不清晰,预约实验室过程繁琐费时的问题。提高实验室利用率。
对于学生,能够随时随地的查询实验室信息,并根据自己的时间安排寻找合适时间预约使用实验室。并能够清晰查看到当前的审核流程。
对于实验室的不同级管理人员,能清晰地看到本级当前的审核任务,查看各个实验室一定时间内的使用量。同时能够根据本级的权限实现对用户或者实验室的管理。
二、开发环境 开发语言:Java
框架:springboot
JDK版本:JDK1.8
服务器:tomcat7
数据库:mysql
数据库工具:Navicat11
开发软件:eclipse/myeclipse/idea
Maven包:Maven
————————————————
三、功能介绍 系统应该分为实验室管理员模块和用户模块。实验室管理员模
块使用者为用户进行录入信息操作,查看实验室信息,设备管理,实验室审核,统计分析。用户可以个人管理,预约服务。
1 普通用户模块 1.查看实验室列表模块:用户登录后,选择实验室查询功能,可输入实验室的部分名称或者实验室功能查询实验室列表。如若不输入查询条件则会显示所有实验室。
2.查看实验室详情模块:普通用户可以登录系统,选择实验室查看实验室的详情信息,点击后会跳转至实验室详情页,包括实验室名称等介绍,实验室拥有的设备,实验室未来七天的空余时间。
3.预约实验室流程模块:用户可通过实验室查询页选择实验室进行预约,用户可选择实验室未来七天内的空余时间进行预约,在选择好预约时间后,点击选择设备会显示出当前时间段空余设备列表,可以选择预约实验室设备。预约默认人数为1人,若同时预约多人,需手动输入预约人数。
4.查看个人预约进度模块:用户可以在个人管理界面查看自己的预约信息列表,点击在预约信息可以查看当前审核进度和实验室技术人员,示范中心和示范中心主任的审核意见。
5.取消预约模块:用户提交预约申请后,可在申请未完成前取消该申请。已经通过的申请或者已被拒绝的申请不可取消。
2 实验室管理员模块 1.用户管理模块:示范中心主任可以使用用户管理功能,其中包括查询、添加、删除用户,修改用户的身份权限,账号状态等信息的功能。
2.设备管理模块:示范中心主任可以使用设备管理功能,可通过条件查询查找设备,修改设备状态,添加或删除设备信息。以满足实验室日常设备更替维护的需求。
3.查看使用情况统计图模块:所有管理员都可使用该功能,该功能可以查看一定时间段内不同实验室的预约使用量和该平台的总预约量。系统会根据统计表的数据显示折线图,并每日凌晨一点更新一次统计数据。
4.预约审核:管理员可以查看当前系统的预约审核信息,包括待审核信息和已审核信息。该系统预约审核为三级审核模式,管理员分为实验室技术人员,示范中心和示范中心主任三个依次递增的等级,每级只能看到上一级已经同意通过的预约信息。各级管理员都有拒绝通过申请的权力,只有三级管理全部审核同意,该预约申请才能通过。
高校实验室预约管理系统的功能模块图,如图 1.1 所示。
图 1.1 实验室预约管理系统的功能模块图
四、核心代码 部分代码:
package com.fc.v2.controller; import com.fc.v2.common.base.BaseController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; /** * 如果有前台这儿写前台访问方法 * @ClassName: IndexController * @author fuce * @date 2019-10-21 00:15 */ @Api(tags = "
字符串匹配问题 1. 字符串匹配问题2. 解决方案2.1 暴力匹配算法2.1.1 算法步骤2.1.2 代码实现 2.2 KMP算法2.2.1 算法步骤2.2.2 next数组计算2.2.2 代码实现 3. 真题3.1 力扣 28. 找出字符串中第一个匹配项的下标3.2 力扣 459. 重复的子字符串3.3 NC149 kmp算法3.4 KMP算法 1. 字符串匹配问题 给定字符串S,和字符串T,查询T在S中出现的位置即为字符串匹配问题;
2. 解决方案 2.1 暴力匹配算法 2.1.1 算法步骤 使用双指针,指针i指向S串进行遍历,指针j指向T进行遍历;一旦某时刻S[I]!=T[j],则说明当前子串不匹配,需要重新开始匹配,即i=i-j+1(S中匹配操作新的起始位置),j=0(T从头开始匹配);当j=T.length时说明匹配成功;
2.1.2 代码实现 package com.northsmile.string; /** * @author NorthSmile * @version 1.0 * @date 2023/8/22&1:20 * 暴力匹配算法解决字符串匹配问题 */ public class StrMatch { public static void main(String[] args) { String s="abdbcabcdef"; String t="abc"; System.out.println(match(s,t)); } public static int match(String s,String t){ if (t.
用于步态识别的动态聚合网络 paper题目:Dynamic Aggregated Network for Gait Recognition
paper是BIT发表在CVPR 2023的工作
paper地址:链接
Abstract 步态识别有利于多种应用,包括视频监控、犯罪现场调查和社会安全等。然而,步态识别在实际场景中常常受到多种外部因素的影响,例如携带条件、穿着大衣、不同的视角等。近年来,各种基于深度学习的步态识别方法取得了可喜的成果,但它们往往使用固定权重的卷积网络来提取显着特征之一,没有很好地考虑关键区域步态特征之间的关系,并且忽略忽略了完整运动模式的聚合。在本文中,我们提出了一个新的观点,即实际步态特征包括多个关键区域的全局运动模式,并且每个全局运动模式由一系列局部运动模式组成。为此,我们提出了动态聚合网络(DANet)来学习更多有区别的步态特征。具体来说,我们在相邻像素的特征之间创建了一种动态注意机制,该机制不仅自适应地关注关键区域,而且还生成更具表现力的局部运动模式。此外,我们开发了一种自注意力机制来选择代表性的局部运动模式并进一步学习鲁棒的全局运动模式。对三个流行的公共步态数据集(即 CASIAB、OUMVLP 和 Gait3D)的广泛实验表明,所提出的方法可以对当前最先进的方法提供实质性改进。
1. Introduction 步态识别旨在远距离检索相同的身份,已广泛应用于社会治安[28]、视频监控[4、15、49]、犯罪侦查[25]等领域。与动作识别[17,53,54]和行人重识别[2,55,60,61]相比,步态识别是最具挑战性的细粒度标签分类问题之一。一方面,轮廓数据是受分割算法[26,62,63]的限制的人的二值图像,偶尔会有孔洞和破碎的边缘。另一方面,在真实场景中,步态识别也会受到各种外部因素的影响,如携带条件、穿着外套、不同的视角等。不同的角度和服装条件会极大地改变同一个人的剪影外观,导致类内差异远远大于类间差异。我们问:如何在各种外部因素的影响下,为每个人自适应地学习更稳健的特征?我们试图从以下几个角度回答这个问题:
(I)局部运动模式。步态,或行走的行为,本质上是身体各部分的协调运动。在步态序列中,我们观察到每个部分都有唯一的代表性运动模式,并且每个运动模式都由一组局部化子运动组成。因此,在各种外界因素的干扰下,准确定位判别部分,获得具有代表性的局部运动模式至关重要。然而,以前的基于步态的方法[7,8,13,14,20,24,33]简单地使用具有非线性激活的卷积网络来模拟动态运动。一旦网络被训练好,参数和非线性函数就只能集中在固定的模式上。为此,我们提出将每个像素的特征编码为具有幅度和相位的向量,如图1所示,这允许学习聚焦相邻像素之间的动态注意映射函数。通过对这种关系进行建模,网络可以进一步关注关键区域的局部运动模式。
图1.每个像素的特征被映射为同时具有幅值和相位分量的矢量。幅值代表上下文信息,而相位分量用于构建关键区域的动态注意模型。卷积运算用∗表示,图中的蓝色圆圈表示动态注意力学习到的关键区域。
(Ii)全局运动模式。步态是一种周期性的运动。我们假设实际的运动模式是一维信号,如图2所示,其中局部运动模式是信号上的点。因此,有必要使用一系列局部运动模式来进一步拟合实际运动模式,以获得可区分的步态特征。然而,最近的基于步态的方法[8,20,33]只使用基于最大或平均的方法来提取其中一个重要的局部特征。这些方法容易受到干扰,不能适应实际的运动模式。根据信号处理理论中的Nyquist-Shannon采样定理[37,39],当以大于信号频率的两倍的频率对连续信号进行采样时,原始信号的信息保持不变。在这方面,我们提出构建一个全局注意模型,并使用它来动态地选择预设数量的可区分局部运动模式(绿色箭头),同时排除噪声(红色箭头)的影响。通过选择足够的区分局部运动模式,网络可以进一步获得稳健的全局运动模式。
图2.实际运动模式与基于最大值的方法、基于均值的方法和全局运动模式聚合器(GMPA)模块的比较。黑色曲线表示受干扰影响的单个周期动作,而绿色曲线表示由GMPA选择的不同局部运动模式组成的合成周期动作。
在此基础上,提出了一种新颖有效的步态识别动态聚集网络(DANet)。如图3所示。DANet由两个设计良好的组件组成,即局部卷积混合块(LCMB)和全局运动模式聚合器(GMPA)。首先将每个像素的特征编码到包括幅度和相位的复数域中,其中幅度项代表上下文信息,而相位项用于建立每个向量之间的关系。通过聚集邻近焦点区域中的矢量的大小和相位来生成局部运动模式。其次,我们利用GMPA模型中的自注意机制动态地选择足够的可区分的局部运动模式,并进一步学习对实际步态模式的拟合。最后,使用我们提出的模型,我们获得了每个人最具代表性的稳定步态特征,并且性能优于最新的SOTA方法,特别是在最具挑战性的变装条件下。
图 3.提出的 DANet 概述。每个阶段都包含局部卷积混合块(LCMB),它利用动态注意力模型来建立感兴趣的相邻像素之间的关系。 HP表示水平池化,GMPA表示全局运动模式聚合器, l l l表示最后阶段的数量。特别地, G M P A j \mathrm{GMPA}_j GMPAj模块负责聚合第 j j j个部分的局部运动模式并产生最终的全局运动模式 v i ˉ {v}_{\bar{i}} viˉ以供识别。
本文的主要贡献如下:
提出了一种新的局部运动模式提取算法,该算法能够动态地对相邻像素的特征之间的关系进行建模,进而准确定位关键区域。
设计了一种有效的全局运动模式匹配算法,用于选择具有区分性的局部运动模式,并对其进行聚合以获得稳健的全局表示。据我们所知,在这项任务中探索自我注意模式的潜力是第一次尝试。
实验结果表明,该方法在CASIA-B[56]、OUMVLP[41]和Gait3D[59]数据集上的性能优于SOTA方法。此外,在CASIA-B[56]上的许多严格的消融实验进一步验证了DANet中每种成分的有效性。
2. Related Works 在这一部分中,我们简要概述了步态识别、局部动作建模和全局动作建模领域的相关研究。
步态架构。步态识别方法主要分为两个典型类别,即基于模型的方法和基于外观的方法。基于模型的方法 [1, 3, 27, 29–31, 44] 尝试将人体姿势结构 [10] 明确地拟合到图像。然而,预定义点是凭经验设计的,并受到低质量图像估计结果不准确的限制。因此,基于模型的方法在性能上通常不如基于外观的方法。基于外观的方法[7,8,13,18,20,21,24,32,33,43,47,51,52,58]是步态的主流框架,并受益于深度学习的快速发展。它大致可以分为三类,即基于模板的方法、基于集合的方法和基于序列的方法。基于模板的方法[18,36,43,47,52,57]通过压缩一系列步态轮廓(例如步态能量图像(GEI))来提取步态时空特征,这不可避免地破坏了判别性局部运动的表示步态序列中的模式。基于集合的方法[8,20,21,23]假设轮廓的外观包含其位置信息,这无法使用连续帧构建局部运动模式。最近一些先进的基于序列的方法[7,24,32,33,51]使用3D卷积(C3D)神经网络从步态序列中提取步态特征并实现SOTA结果。我们的方法属于基于序列的方法,与其他方法相比,我们提出使用可变长度帧作为输入。
局部动作建模。局部动作建模[14,24,32,33]旨在构建短程时空特征,这些特征已在各种文献中被证明有利于步态识别。 GaitPart [14]提出了一种微运动捕捉模块来建模短程时空特征。 MT3D [32]提出了多个时间尺度的 3D 卷积层来提取小和大时间尺度的运动特征。 GaitGL [33]利用局部时间聚合模块来提取局部时间信息。 3DLocal [24]提出了一个定位模块来自适应采样局部动作特征。与这些策略相反,我们提出将步态序列的每个像素映射到复值域,使用相位项来编码步态特征之间的关系。通过充分利用相位项,我们在特征的每个像素之间构建动态注意力模型,以提取关键区域的局部运动模式。
添加mysql用户组和mysql用户 安装依赖libaio yum install -y libaio* 下载Mysql wget https://obs.cn-north-4.myhuaweicloud.com/obs-mirror-ftp4/database/mysql-5.7.27-aarch64.tar.gz 安装mysql 解压Mysql tar xvf mysql-5.7.27-aarch64.tar.gz -C /usr/local/ 重命名 mv mysql-5.7.27-aarch64/ mysql
创建log文件 mkdir -p /usr/local/mysql/logs 授权mysql用户 chown -R mysql:mysql /usr/local/mysql 创建软连接 ln -sf /usr/local/mysql/my.cnf /etc/my.cnf cp -rf /usr/local/mysql/extra/lib* /usr/lib64/ 配置libstdc mv /usr/lib64/libstdc++.so.6 /usr/lib64/libstdc++.so.6.old ln -s /usr/lib64/libstdc++.so.6.0.24 /usr/lib64/libstdc++.so.6 设置开机启动 cp -rf /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld chmod +x /etc/init.d/mysqld systemctl enable mysqld 添加环境变量 vim /etc/profile 在尾部添加
export MYSQL_HOME=/usr/local/mysql export PATH=$PATH:$MYSQL_HOME/bin 刷新配置 source /etc/profile 初始化mysql mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data 启动mysql systemctl start mysqld 查看mysql 状态 systemctl status mysqld 登录mysql mysql -u root 设置密码
文章目录 1、为什么对数据库做优化2、双主架构双主架构的工作方式如下:双主架构的优势包括:但是一般不用这种架构,原因是: 3、主从复制主从复制的工作方式如下:主从复制的优势包括:主从复制的缺点 4、冷热分离冷数据热数据 1、为什么对数据库做优化 对数据库架构进行优化是为了提高数据库系统的性能、可扩展性、稳定性和可维护性。MySQL官方说:单表2000万数据,性能就达到瓶颈了,为了保证查询效率需要让每张表的大小得到控制。
再来说,为什么要提高查询效率呢?
除了普通的用户查询操作,增、删、改操作都包含查询操作,所以说,在一个应用中,查询操作是占比最高的,提高了查询效率,整体性能都会有所提升。
下面介绍几种常见方案
2、双主架构 它旨在提高数据库的可用性和负载均衡。在双主架构中,有两个主数据库实例(也称为主节点),每个主数据库都可以处理读写操作,而不仅仅是一个主数据库处理写操作,另一个主数据库处理读操作。
双主架构的工作方式如下: 数据同步: 两个主数据库之间需要建立数据同步机制,以保持数据的一致性。通常使用主从复制或双向复制来实现数据同步。这意味着任何一个主数据库上的写操作都会同步到另一个主数据库,从而保持数据的同步。读写操作: 由于双主架构允许两个主数据库都处理读写操作,因此应用程序可以同时向这两个主数据库发送写操作和读操作。这可以减轻单个主数据库的负载。故障切换: 如果其中一个主数据库发生故障,应用程序可以切换到另一个正常运行的主数据库,以保持系统的可用性。故障切换时,应该确保切换后的主数据库是最新的,并且可以快速地切换到备用主数据库。
双主架构的优势包括: 高可用性: 双主架构可以提供较高的可用性,因为即使一个主数据库发生故障,另一个主数据库仍然可以继续处理读写操作。负载均衡: 两个主数据库可以分摊读写负载,从而提高数据库的性能和响应性能。容错性: 如果一个主数据库出现问题,可以快速切换到另一个主数据库,从而减少系统的停机时间。 但是一般不用这种架构,原因是: 这种架构只是做了负载均衡,当写操作频繁时,会导致两个主数据库之间的数据同步压力增大。还有就是,现实中,一天可能就会产生1000w条数据,两个主数据库的单表会很大,影响读和写的性能。
3、主从复制 主从复制是一种常见的数据库复制技术,用于在多个MySQL数据库之间实现数据同步。在主从复制中,有一个主数据库(主节点)负责处理写操作,而一个或多个从数据库(从节点)将主数据库的数据复制到自身,用于处理读操作。
主从复制和双主架构都实现了负载均衡,但主从复制将读操作和写操作进行了分离,主数据库只承担写操作,从数据库只承担读操作,从而减轻主库的负载。对于频繁的写操作场景,将读操作分散到从库可以提高主库的性能,从而更好地处理写入请求。
主从复制的工作方式如下: 主库(主节点): 主库负责处理所有的写操作,如插入、更新和删除操作。主库上的写操作会被记录在二进制日志(binary log)中,这是一个记录数据库变更的日志文件。从库(从节点): 从库通过读取主库的二进制日志,将主库的写操作逐一复制到自身。从库会保持与主库的数据一致性。从库可以用于处理查询操作,从而分担主库的负载。 主从复制的优势包括: 高可用性: 主从复制提供了一种冗余备份,如果主库发生故障,可以切换到从库以保持系统的可用性。
负载均衡: 从库可以用于处理读操作,从而减轻主库的负载,提高数据库的性能和响应性。
数据备份: 从库可以用于数据备份和恢复,因为它保留了与主库相同的数据。
主从复制的缺点 不满足强一致性
在MySQL中,主节点入库的时候可以选择采用某种方式来判定入库成功 主节点入库以后,不管从节点是否同步成功,直接返回sql执行成功。 这种方式的特点就是快,但是不满足强一致性:由于延迟和复制过程中的一些异常情况,从库和主库之间可能会出现数据不一致的问题。在复制链路上发生故障或者复制操作出现错误时,可能会导致从库数据与主库不一致。 在存储一些不太敏感的数据(操作记录,日志)时,可以采用。主节点入库以后,等所有的从节点都同步完成以后,才返回sql执行成功,当有一个从节点落库失败,返回执行失败。 这种方式可以满足强一致性,会比较慢。 对于存储敏感数据(跟钱有关),采用这种方式。 同步延迟问题
我刚提交了订单就去查询订单列表,这时主库刚入库,从库还没去主库同步。有可能看不到我新下的订单。还有可能是,我去申请退款并且已经显示了退款成功,我去查订单列表,由于从库还没有同步主库的数据,还会显示购买成功。
可以采用分布式全局锁,等查询从库的时候,如果退款状态是false(未退款),再去redis中查看分布式全局锁是否存在,如果存在就说明主库已经完成退款操作,只是从库还没同步过来,可以通知用户后台正在处理,请稍后再试。如果redis中不存在这个锁,就说明该订单的确未退款。 上述的主从复制对读、写操作进行了分离,将读操作平摊给了注册的从数据库,分担了主数据库的查询压力。但是没有解决表大小的问题,当单表的数据达到2000w后,主数据库的写操作(包含查询)达到瓶颈,从数据库的读操作也达到了瓶颈。针对表大下,于是有了下面的架构
就是将原本要装几千万数据的单表,进行拆分,如下图:
就是在执行入库或查询之前,可以通过数据的id%主库的数量,将操作均分到每个主从复制单位上。
当数据量过亿时,此时要是延续上面的方案,至少需要10个数据库,当数据量再多,过10亿时,至少需要100个数据库,这是不现实的。那么好(哈哈哈哈)下面就来介绍一下,当数据量破亿后,该如何优化。
4、冷热分离 表数据量增长速度快或数据量较大时, 我们就该考虑是否使用冷热分离解决方案了
冷数据 这是不经常被访问的数据(好比打入冷宫),通常是历史数据或者很少被查询的数据。冷数据不需要频繁的访问速度,因此可以存储在较慢但成本更低的存储介质中,如磁盘存储或者分布式文件系统。冷数据可以通过归档、压缩等手段来节省存储空间。
好比你要查询美团外卖的订单,你应该很少或者从不去查询1年以前或者更久远的订单吧。这种冷数据如果和其他表没有关联的话可以直接扔es,es在数据量1TB的情况下,单次查询可达到秒级。
热数据 这是经常被访问的数据,通常是最近的数据,或者是频繁被查询和更新的数据。热数据对于应用的性能至关重要,因此可以采用较快的存储介质,如内存或快速的闪存存储设备。对于关系型数据库,热数据可以存储在主数据库中。
背景 业界对Android的性能监控、hook、系统分析、抓包、逆向等领域的关注和投入在不断提升,作为Linux Kernel中新兴的优美的一套技术框架,bpf逐渐在Android中被用于监控、分析、优化和逆向,产出了众多的工具。此外,Google原生系统的上层服务(如网络流量统计、网络黑白名单)也转向使用ebpf来实现。
bpf可以理解成Kernel的虚拟机字节码,它借助C语言编译成特定的ELF,通过专用的系统调用注册到Kernel,挂载到指定的tracepoint,进行代码流程的hook,与App的插桩、性能优化的检查点非常类似。
本文以Android源码AOSP为基础,讲解一个bpf程序应该如何被编译、集成到系统、在系统中启动/运行,并使用C语言编写了一个可以实际运行的bpf程序(https://github.com/NasdaqGodzilla/cpuprobe)。
编译 常规的C语言bpf程序需要编译为Kernel BPF子系统能够识别的专用字节码,Android采用了一套独特的编译系统(Android.bp)来包装包含bpf程序在内的编译流程。
一个最简单的bpf编译描述如下:
bpf { name: "cpu_stats.o", srcs: ["cpu_stats.c"], cflags: [ "-Wall", "-Werror", ], } 这段写在Android.bp内的bpf代码声明了需要编译一个名称为cpu_stats.o的bpf程序,srcs指定了其源文件,cflags指定了向编译器传递的编译参数。
前面说过,一个bpf程序,从结构上说是一个elf,从逻辑上说是一个被Kernel BPF虚拟机加载后才能执行的字节码(类似JS解释器加载JS),因此它编译期间不会发生链接,不会产生可执行bin文件,也不能直接执行。
通过AOSP的模块编译指令即可编译:
m cpu_stats.o
集成 常规的bpf程序有多种集成方式,包括调用bpf()、通过python、bpftrace等(本质也是bpf())调用。但出于安全和效率的原因,Android屏蔽了bpf(),仅提供了bpf loader在开机阶段加载预置的bpf程序,在开机后,系统就不能再加载任何bpf程序了。
bpf loader会加载存放在/system/etc/bpf目录下的所有bpf程序,因此将我们编译出来的bpf程序放入该路径(或通过Android.bp、Android.mk等预置)即可让系统自动为我们加载我们的bpf程序:
adb push cpu_stats.o /system/etc/bpf adb push cpu_stats_client /system/bin/ 这里我们还push了一个cpu_stats_client,稍后解释它的作用。
push后,重启设备,让Android自动加载这个bpf程序,加载成功的话日志大概长这样:
LibBpfLoader: Loading ELF object /system/etc/bpf/cpu_stats.o with license GPL LibBpfLoader: Loaded code section 3 (tracepoint_sched_sched_switch) LibBpfLoader: Loaded relo section 3 (.reltracepoint/sched/sched_switch) LibBpfLoader: Adding section 3 to cs list LibBpfLoader: bpf_create_map name cpu_stats_map, ret: 27 LibBpfLoader: map_fd found at 0 is 27 in /system/etc/bpf/cpu_stats.
在linux下整合log4cpp日志框架时,出现了下面的错误:当加载共享库时出错,找不到共享库 XXXX
[root@hecs-207177 cworkspace]# ./Log4cppTest ./Log4cppTest: error while loading shared libraries: liblog4cpp.so.5: cannot open shared object file: No such file or directory 通用解决办法: 1、首先使用find命令,查找报错中的共享库路径 此处我以上面报错为例:
find / -name 共享库 [root@hecs-207177 cworkspace]# find / -name liblog4cpp.so.5 /usr/local/lib/liblog4cpp.so.5 /usr/src/log4cpp/src/.libs/liblog4cpp.so.5 2、将上面路径加入到 /etc/ld.so.conf 中 [root@hecs-207177 cworkspace]# vim /etc/ld.so.conf 注意,此处只需要将 lib 目录加入即可,如下图:
3、使用 ldconfig 命令加载刚刚加入的共享库 ldconfig
网上搜一下方法,基本上是2种
现象和原因:
.gitignore中已经标明忽略的文件目录下的文件,git push的时候还会出现在push的目录中. 用git status查看状态,想要忽略的文件还是显示被追踪状态。 原因是因为在git忽略目录中,新建的文件在git中会有缓存,如果某些文件已经被纳入了版本管理中, 就算是在.gitignore中已经声明了忽略路径也是不起作用的, 这时候我们就应该先把本地缓存删除,然后再进行git的提交,这样就不会出现忽略的文件了。 第一种方法 具体做法: git清除本地缓存(改变成未track状态),然后再提交: git rm -r --cached . git add . git commit -m 'update .gitignore' git push -u origin master 需要特别注意的是:
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。想要.gitignore起作用,必须要在这些文件不在暂存区中才可以,.gitignore文件只是忽略没有被staged(cached)文件对于已经被staged文件,加入ignore文件时一定要先从staged移除,才可以忽略。 第2种方法 # 忽略对某个文件追踪 git update-index --assume-unchanged PATH //在PATH处输入要忽略的文件 # 取消忽略 git update-index --no-assume-unchanged PATH
在使用 Vue 进行开发时,下拉框值变动事件 @change 是很常用的。
其传参一般分为两种方式:默认传参和自定义传参。
默认传参
@change 默认会传选中项标识的参数,在传参处不用定义,在方法中直接接受即可。
<template> <el-select v-model="value" placeholder="请选择" @change="onChange"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </template> <script> methods: { onChange(value) { console.log(value); } } </script> 此时控制台会打印下拉框选中项对应的标识值。
自定义传参
我们经常会遇到需要下拉框传递多个参数的场景,这是需要自定义传参方式。
<template> <div v-for="(item, index) in otherFeesList" :key="index" class="item"> <el-select v-model="value" placeholder="请选择" @change="onChange($event, index)"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> <el-input v-model="item.unit"> </div> </template> <script> methods: { onChange(value, index) { console.log(value); console.
有的公司电脑会强制安装一些特定的杀毒软件或者监控软件。
在安装后,我们的 IDEA 可能会出现 Git 相关操作非常缓慢的情况。
虽然用 Git 命令操作不受影响,但终究没有可视化界面直观方便。
解决这一问题非常简单,只需要删除 IDEA 安装目录 bin 下面的 runnerw.exe 即可。
该文件为何会造成 IDEA 的 Git 缓慢尚不清楚,但删除后的效果是非常明显的,Git 恢复了正常速度。
经过多版本的使用体验,删除该文件对 IDEA 的使用没有任何影响。
urls:
from your_app import views path('xxx/', views.your_def), # 视图函数 path('xxx/', views.your_class.as_view()), # 视图类 视图函数:
from django.http import JsonResponse def getFollwerInfo(request): try: if request.method == 'POST': return JsonResponse({'errcode': 200, 'info': 'POST'}, json_dumps_params={'ensure_ascii': False}) else: return JsonResponse({'errcode': 200, 'info': '不是POST请求'}, json_dumps_params={'ensure_ascii': False}) except Exception as e: info = str(e) return JsonResponse({'errcode': 500, 'info': info}, json_dumps_params={'ensure_ascii': False}) 视图类:
from django.http import HttpResponse,JsonResponse class rtx(View): """类视图:处理注册""" # 处理GET请求 def get(self, request): try: print() except Exception as e: logger.
MyBatis-Plus在实际工作中常用到的配置,供自己和大家查阅学习。
mybatis-plus: mapperPackage: com.**.**.mapper # 对应的 XML 文件位置 mapperLocations: classpath*:mapper/**/*Mapper.xml # 实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.**.**.domain # 针对 typeAliasesPackage,如果配置了该属性,则仅仅会扫描路径下以该类作为父类的域对象 #typeAliasesSuperType: Class<?> # 如果配置了该属性,SqlSessionFactoryBean 会把该包下面的类注册为对应的 TypeHandler #typeHandlersPackage: null # 如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 #typeEnumsPackage: null # 启动时是否检查 MyBatis XML 文件的存在,默认不检查 checkConfigLocation: false # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种: # SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句(PreparedStatement) # REUSE:该执行器类型会复用预处理语句(PreparedStatement) # BATCH:该执行器类型会批量执行所有的更新语句 executorType: SIMPLE # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署 configurationProperties: null configuration: # 自动驼峰命名规则(camel case)映射 # 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名 mapUnderscoreToCamelCase: true # 默认枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理 # org.
一、Flutter SDK配置 1、官网地址:https://flutter.dev/ 2、下载配置flutter sdk 2-1、路径:https://docs.flutter.dev/development/tools/sdk/releases 2-2、选择最新版本 2-3、解压zip 2-4 配置环境变量 2-5、flutter --version验证配置是否成功 二、Android studio配置flutter插件 1、安转dart插件 2、安装flutter插件 3、重启Android studio是安装的新插件生效
在 Android 应用开发中,SHA-1(Secure Hash Algorithm 1)值是一种哈希算法,常用于生成应用的数字签名。这个数字签名用于验证应用的身份,并确保应用在发布到设备上时没有被篡改。
以下是生成 Android 应用的 SHA-1 值的步骤:
生成密钥库(KeyStore): 首先,你需要创建一个密钥库文件,通常以 .jks 扩展名结尾。这个密钥库文件将包含应用的数字签名密钥。
生成密钥对: 在密钥库中,你需要生成一个密钥对,包括一个私钥和一个公钥。私钥用于签署应用,而公钥将用于验证签名。
生成数字签名: 使用生成的私钥,你可以对应用进行数字签名。数字签名是将应用的内容和一些元数据通过哈希函数(如 SHA-1)生成的唯一标识。
获取 SHA-1 值: 一旦应用被签名,你可以使用不同的工具来提取数字签名中的 SHA-1 值。一个常用的工具是 keytool,它是 Java 开发工具包(JDK)中的一部分。
打开终端或命令提示符,并导航到包含密钥库文件的目录,然后运行以下命令:
keytool -list -v -keystore your_keystore_filename.jks -alias your_alias_name 替换 your_keystore_filename.jks 为你的密钥库文件名,your_alias_name 为你在密钥库中为应用生成的密钥别名。
运行命令后,会显示密钥的详细信息,其中包括 SHA-1 值。
请注意,SHA-1 已经被认为不再安全,因为在安全研究中出现了碰撞攻击,使得可以伪造具有相同 SHA-1 值的不同数据。因此,建议在实际应用中使用更安全的哈希算法,如 SHA-256,以提高应用的安全性。在 Android 开发中,你也可以通过类似的步骤获取应用的 SHA-256 值。
在第一节课中我们已经学会了PyQty5的安装,以及配置好了两个环境,如果还没有看到的小伙伴可以前去考古:点我。今天我们将会继续学习PyQty5的设计界面的认识,也会带领大家一步一步设计出一个小GUI作品。 首先我们创建一个py文件,然后右击,点击上一节课中配置好的环境进入PyQty5的设计界面 1、点击左上角【File】新建一个【无按钮】的窗口 2、在左边 【Display Widgets】 中把 【Label 】拖入中间的窗体中 3、修改第一个标签的属性 输入 Find &What:,可以双击输入,或者右边改(&作用是加速键 Alt) 4、左边【 Input Widgets 】中把 【LineEdit】(行编辑) 拖入中间的窗体中 5、修改刚刚拖动的【LineEdit】(行编辑) 框的属性,修改名字:【findLineEidt】 修改此行编辑框的对象名(作用是在后面的实际代码编写中,还可以用到,因此取一个有意义的名字) 操作类似代码中:findLineEidt =QLabel() 6、重复上面两个操作,变成下面这样 第二个标签的文本为【Replace w&ith: 】 第二个行编辑框的对象名字为 【replaceLineEidt】 7、在左边 【Buttons】 中把 【check Box】 拖入中间的窗体中 把复选框的文本改为【&Case sensitive】,对象名改为【caseCheckBox】重复上述操作即可 8、重复上述操作 把复选框的文本改为【Wh&ole words】,对象名改为【wholeCheckBox】 9、继续添加一个 Syntax 的标签 标签的文本设置为【&Syntax:】 10、在左边 【Input Widgets】 中把 【Combo Box】 拖入中间的窗体中,取名为:【syntaxComboBox】 11、给组合框添加项目 右键点击组合框,选 Edit Items 输入【Literal text】与【Regular expression】点击ok 12、在左边 【Spacers】 中把 【Vertical Spacer】 拖入中间的窗体中 如果用户重新修改了窗体的尺寸大小,如果希望各个窗口部件能够放在一起而不是分散开来,可以 Combo box 的下面放置一个竖直分隔符(Vertical Spacer) 13、在左边 【Display Widgets】 中把 【Vertical Line】 拖入中间的窗体中 要让这些按钮能够与已经创键的窗口部件在形式上区分开来,可以在它们和其他窗口部件之间放一根竖线。 14、在左边【 Buttons 】中把 【Push Button】 拖入中间的窗体中 按钮的文本为【&Find】,对象名为【findButton】 15、依次重复上述提到的操作,直至到下面的情况 依次输入文本、对象名: 【&Replace】、【replaceButton】; 【Replace &All】、【replaceAllButton】; 【 Close】、【closeButton】。 16设置第一个布局 CTRL+鼠标,选中以下控件,并点击点击网格布局 17、接下来的依次布局即可 对布局和控件,可以继续布局,可以如果选起来不方便,可以在右上角的停靠窗口选择 18、设置伙伴关系,F3 退出此状态 这一步就可以消除之前标签里的&,并且让伙伴功能上线。 19、设置 Tab 顺序 用默认即可,F3 退出 20、绑定 Close 的槽函数,拖动Close按钮至空白区域 依次选择 clicked()、reject()、ok,即把 Close 按钮绑定到主窗体的关闭函数 21、设定窗体类名、标题名、文件名 点击空白窗体处,右边修改窗体类名、标题名。 文件保存时,File->Save或者Ctrl+s 22、ui 转 py 点击我们上一步保存的ui文件 右击,然后利用上一节课的ui 转 py 环境进行转换 会上生成一个同名的 py 文件 尾部加上创建对象的代码,然后右击运行 if __name__ == '__main__': app = QtWidgets.
甘肃百视通九联UNT413A_S905L3A_基于原机备份制作_线刷固件包
特点:
1、适用于对应型号的电视盒子刷机;
2、开放原厂固件屏蔽的市场安装和u盘安装apk;
3、修改dns,三网通用;
4、大量精简内置的没用的软件,运行速度提升,多出大量的存储空间;
5、去除应用安装限制;
6、支持开机自启动、开机密码锁、儿童应用锁、应用隐藏、开机自动进入HDMI等各种花式功能 ;
线刷方法:(新手参考借鉴一下)
1、准备好一根双公头USB线刷刷机线,长度30-50CM长度最佳,同时准备一台电脑,拆开盒子;
2、电脑上安装好刷机工具Amlogic USB Burning Tool 软件 →打开软件 →文件 →导入烧录包 →把【擦除flash】和【擦除bootloader】两项勾选 →点击【开始】 →盒子接电源线 →电源关闭 →把USB线一端插上盒子 →保持短接 →USB另一端插上电脑 →通电开机。 等待提示成功字样后,关闭电源,拔掉刷机线,把机顶盒接上电视机,通电开机,首次开机稍微会有点慢,耐心等待初始化完成即可。
如需短接,有准备晶晨短接神器最佳,没有的话拆机按短接点示意图短接刷机。
刷机固件: 链接: https://pan.baidu.com/s/1v1FfIgNzhZ0VLGCNX3w6YQ 提取码: 8888 备用链接:https://wwt.lanzoux.com/b021zvjkj 提取码:6l1n
固件路径:A《当贝桌面纯净完美版--固件大全》(固件种类更多)>4《九联盒子(UNT)固件合集》>《UNT413A》>《S905L3A芯片》
B合集里面也有的
声明:本安卓固件,仅供内部测试和技术交流使用,任何非法商业使用及商业利益冲突带来的法律纠纷,与本人无关,本人概不负责,请下载后24小时内删除,谢谢合作!刷机既有乐趣也有风险,请慎重选择,一切源于刷机造成的后果自负,本人概不负责!
今天更新一下如何利用vue3和高德地图中的天气api来实现点击某个地区获取其天气情况及未来几天的天气预报效果。强调一下本次是通过vue3实现的具体效果。
1.搭建vue3框架,这个不进行详细说明
2.NPM 安装 Loader npm i @amap/amap-jsapi-loader --save 3.新建 map.vue 文件,这里我放置在名为views的文件夹中,说明一下需要用到router路由
4.创建地图容器:在 map.vue 地图组件中创建 <div> 标签作为地图容器 ,并设置地图容器的 id 属性为 container。
<template> <div id="container"></div> </template> 5.设置地图容器样式
<style lang='less' scoped> #container{ width: 100%; height: 600px; margin: 0; padding: 0; position: relative; } </style> 6.引入JS API Loader :在地图组件 map.vue 中引入 amap-jsapi-loader import AMapLoader from "@amap/amap-jsapi-loader" 7.初始化并创建地图
import { onMounted, shallowRef} from 'vue' const map = shallowRef(null);//定义一个map对象 //初始化地图 const initMap=()=>{ window._AMapSecurityConfig = { securityJsCode:'你自己的安全密钥',//安全密钥 } AMapLoader.
rosbag 是 ROS 中的一种常用的数据记录和回放工具,用于捕获和存储 ROS 消息。但是 ROS1 和 ROS2 的 rosbag 存储格式是不一样的,因此在使用过程中,常常会有 rosbag 格式转换的需求。因此,本文将介绍 ROS1 和 ROS2 中的 rosbag 格式,并演示如何使用 rosbags 工具进行转换。
rosbag 格式 在 ROS1 中,rosbag 的文件后缀是 .bag,它是一种基于二进制的 ROS 消息存储格式。它将消息以二进制形式写入文件,每个消息都包含一个时间戳和一个消息体。这种格式的好处是可以高效地存储大量的消息数据,但也存在一些限制,例如不支持跨平台的消息兼容性和扩展性。
因此,ROS2 对 rosbag 格式进行了一些改进和扩展,采用了一种基于 SQLite 的数据库格式,包括一个 .db3 数据库和一个 .yaml 文件,可以更好地支持跨平台的消息兼容性和扩展性。它将 ROS 消息存储为表格形式,每个表格都包含时间戳、消息类型和消息数据。这种格式的好处是可以更灵活地查询和过滤消息数据,并且支持更多的数据类型和结构。
总的来说,ROS1 的 rosbag 使用基于二进制的格式,而 ROS2 使用基于 SQLite 的数据库格式。前者格式相对较为固定,不支持动态扩展;而后者格式更灵活,具有更好的跨平台兼容性和扩展性,同时支持更灵活的查询和过滤。对于需要在不同平台之间共享和分析 ROS 消息数据的用户来说,ROS2 的 rosbag 格式可能是更好的选择。
常见的 rosbag 转换方法 目前来看,比较常见的转换方法是利用 ros2_bridge 转录,简单来说就是同时启动 ROS1 和 ROS2,通过 ROS2 的 ros2 bag play 命令播放 rosbag 数据,同时通过 ROS1 的 rosbag record 命令录制,从而实现 rosbag 数据格式的转换。
背景 很多Linux发行版都是使用systemd来管理程序进程,但是在WSL中默认是用init来管理进程的。
为了符合长久的使用习惯,且省去不必要的学习成本,就在WSL的发行版(我这里安装的是Ubuntu20.04)中支持systemd,也就可以使用systemctl命令来启停进程。
相关知识 能够支持使用systemctl命令,提供完整 systemd 的项目有很多:
diddledani/one-script-wsl2-systemd: The one-script variant of the systemd hack for WSL2 (github.com)ubuntu-wsl2-systemd-scriptwsl2-hacksgeniesubsystemdAngea 这些项目的核心原理并无大异,无非是细节处理的好坏和附加功能的多少,但最重要的一点可能是工作层次不同。
前三个脚本都工作在图中的** shell **层,要依赖外置命令执行系统调用。
genie 工作在应用程序层,它使用 C# 编写,通过 shell 执行系统调用,比前三个还多了一层。
最后两个虽然也是应用程序,但它们由 Rust 编写,不经 shell,而直接由 C system call wrapper 执行系统调用,依赖最少,动态链接编译后只有几百 K。
systemd
在较新的Linux系统上,都使用systemd 管理进程,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。
systemd为系统启动和管理提供了完整的解决方案。它提供了一组命令。字母d是守护进程(daemon)的缩写。
init
WSL2 的发行版均拥有微软提供的 init,它是一种 systemd 的替代方案,不支持 systemctl 命令,
WSL2 本身是由 Windows 负责运行的,因此使用 tree 或 ps 命令时会看到根进程不是 systemd,这将导致无法启动 Linux 系统服务的守护进程 (deamon)。
当我们执行 systemctl 命令的时候,会显示出我们的 init system (PID 1) 并非 systemd,而是微软提供的 init。
通俗理解什么是ADC 学懂,用熟练之后,从头介绍一些概念时,总是比较困难的。很难站在一个什么都不懂的角度去讲明白一个概念。
入之不深,则有浅易之病;出之不显,则有艰涩之患。
文章目录 通俗理解什么是ADC什么是ADCADC的采样率采样位数采样精度 建议看完“什么是ADC”后,去实操ADC采集直流。实操结束后再往后看。
ADC实际没有这么的简单,深入了解需要去学各种寄存器之间如何协作,信号如何走通。这些概念在后面会有讲解。
什么是ADC 我们在高中物理学习时都了解过电压表,在生活中也都见过。红表头、黑表头分别去触碰待测电路两端,就可以测出来这段的分压。如果让黑表头去触碰电源的负极,那么测出来的就是红表头所在的地方的电压。
如果测试点是1V,电压表就显示1V,2V呢就显示2V。可以说他们有如下的对应关系
测试点电压万用表显示的值0.00V01.65V1.653.3V3.3 于是我们有了概念:万用表是一种感知电压大小的器件。
ADC也是这样的器件。不过呢ADC不能显示小数,我们以STM32F1单片机12位ADC为例。他只能显示0-4095这些整数。
4095 = ( 1111 1111 1111 ) 二进制 = 2 12 − 1 4095=(1111\ 1111\ 1111)_{二进制}=2^{12}-1 4095=(1111 1111 1111)二进制=212−1,这就是12位ADC的含义。
那么ADC的电压对应关系就要改一改,没有像电压表一样一一对应。具体关系如下
测试点电压ADC的测试值0.00V01.65V20483.3V4096 表1 这个关系如果写成如下公式。
掌握表1对应关系就可以,没必要背公式
A D C 的返回值 = 待测电压 3.3 V ∗ 4096 ADC的返回值= \frac{待测电压}{3.3V}*4096 ADC的返回值=3.3V待测电压∗4096
比如我用ADC去测量1V的电压,那么ADC返回的数值是 1 3.3 ∗ 4096 = 1241 \frac{1}{3.3}*4096=1241 3.31∗4096=1241,当单片机收到ADC返回的1241,单片机就可以知道待测电压是1V了。
ADC的采样率 采样率这个概念需要在使用中去感受,这里就简单提下,在后续的文章中,我们会对他有更加准确的认识
之前我们都是在讨论用ADC去采集直流电压,比如一个稳定的1V。可是如果我们要采集的是一个在不断变化的信号呢?
比如采集1hz正弦信号。我们可以每1s采集一次,那么完全看不出这个信号的变化和波形;但如果我们每100ms采集一次呢,一个信号周期内就采集了10个点,可以大致看出这个信号的波形;如果我们每1ms,每1us采集一次呢?那么这个信号的波形就完全被我们知道了。
上面的1s,100ms,1us分别对应的是1 sps、10 sps、1M sps采样率。采样率表示的是ADC的采样速度。对于不同ADC,有自己的采样率上限的。比如STM32F103的单个ADC采样率支持1hz-1Mhz。
拿1M采样率去采集1K信号,一个周期有1000个点,效果非常好;但是如果1M去采集1M信号,这和每1s去采集一个1hz信号一样,一个周期1个点,根本看不出波形
常用单位:
1、打开SQL Server 2019配置管理器
2、SQL Servere 网络配置(启用 Named Pipes 和 TCP/IP)
3、修改TCP/IP协议(右键选择属性—IP地址),具体如下图所示:
4、重启SQL Server服务
matlab时频分析之连续小波变换cwt 1 小波分析简介2 小波分析基本原理3 cwt的matlab实现4 cwt的边缘效应与影响锥5 cwt的重构——icwt6 增加cwt的分辨率的wsst (2020年7月更新,第3节绘制了一个实部、虚部的关系图) 1 小波分析简介 和傅里叶变换比,小波变换和短时傅里叶变换都有着相同的优点,就是可以同时在时域和频域观察信号。所以小波变换非定常信号的分析中有很大的作用。
有关短时傅里叶变换的文章,可以参见我之前写的:
matlab时频分析之短时傅里叶变换 spectrogram
https://blog.csdn.net/weixin_42943114/article/details/88735799
和短时傅里叶变换相比,小波变换有着窗口自适应的特点,即高频信号分辨率高(但是频率分辨率差),低频信号频率分辨率高(但是时间分辨率差),而在工程中常常比较关心低频的频率,关心高频出现的时间,所以近些年用途比较广泛。
在数学上,小波还有正交化等优点,应用领域广泛。
但是,本文只讨论如何利用matlab实现cwt的时频分析
2 小波分析基本原理 小波的含义,即为时间上衰减快,和傅里叶的正弦波相比要短。
一个典型的morlet小波如下图:
matlab有很多自带的小波函数,利用wavemngr(‘read’,1)可以进行小波的查看,利用waveinfo可以查看小波的相关信息。
在时间域上,可以通过小波在时间上的移动,逐一比较不同位置的窗口信号,得到小波系数,小波系数越大,则证明小波与该段信号的拟合程度越好。计算中用小波函数与该窗口信号的卷积,作为该窗口下的小波系数。窗口的长度和小波的长度是相同的。
在频率域上,通过拉伸或压缩小波的长度,来改变小波的长短和频率,实现不同频率下的小波系数。相应的,窗口长度也会随着小波长度变化。由于高频处小波被压缩,时间窗变窄,使得时间分辨率更高。
将不同频率下的小波系数组合起来,便得到了时频变换的小波系数图。
从图上可以看到,低频处频率分辨率要好于高频处的。小波时频图的特点为整体呈现高频处高而瘦,低频处矮而宽。
小波中,一般用尺度scale来衡量小波的频率f,两者之间的转换关系为:
s c a l e ∗ f = F s ∗ w c f scale * f=Fs * wcf scale∗f=Fs∗wcf
公式中,Fs代表信号的采样频率,wcf为小波的中心频率(wave central freq),在matlab里可以用 centfrq(wavename) 来查询。
3 cwt的matlab实现 matlab自带的有两种实现方式,一种是2006年版本推出的函数cwt,一种是2016年版本推出的函数cwt。两个函数名称相同,用法不同。
(我也不知道为什么会这样。。。-_-||)
由于名称一样,在使用中,要想调用不同的版本,只能用输入输出格式来区分。
旧版本cwt用法为:
coefs = cwt(x,scales,'wname') 新版本cwt用法为:
[wt,f] = cwt(x,wname,fs) 最明显的区别在于,新版本取消了自定义尺度函数scales的功能。同时新版本还更新替换了一部分小波函数。旧版本支持 ‘haar’,‘db’,‘sym’,‘cmor’,‘mexh’,‘gaus’,‘bior’等小波,新版本支持’morse’, 'amor’和 'bump’小波。
Eth-trunk SW1+SW2 interface Eth-Trunk 0 q interface GigabitEthernet0/0/2 eth-trunk 0 interface GigabitEthernet0/0/3 eth-trunk 0 VLAN+TRUNK SW1+SW2 vlan 2 q interface Eth-Trunk0 port link-type trunk port trunk allow-pass vlan 2 interface GigabitEthernet0/0/4 port link-type trunk port trunk allow-pass vlan 2 interface GigabitEthernet0/0/5 port link-type trunk port trunk allow-pass vlan 2 SW3+SW4 vlan 2 q interface GigabitEthernet0/0/1 port link-type trunk port trunk allow-pass vlan 2 interface GigabitEthernet0/0/2 port link-type trunk port trunk allow-pass vlan 2 interface Ethernet0/0/2 port link-type access port default vlan 2 STP SW1 stp region-configuration region-name v1 //定义组的名字 instance 1 vlan 1 instance 2 vlan 2 active region-configuration //激活当前配置 stp instance 1 root primary //定义本地为组1的主根 stp instance 2 root secondary //定义本地为组2的备份根 SW2 stp region-configuration region-name v1 instance 1 vlan 1 instance 2 vlan 2 active region-configuration stp instance 1 root secondary stp instance 2 root primary SW3 stp region-configuration region-name v1 instance 1 vlan 1 instance 2 vlan 2 active region-configuration interface Ethernet0/0/1 stp edged-port enable //进入连接PC的接口,进行端口加速 interface Ethernet0/0/2 stp edged-port enable SW4 stp region-configuration region-name v1 instance 1 vlan 1 instance 2 vlan 2 active region-configuration interface Ethernet0/0/1 stp edged-port enable //进入连接PC的接口,进行端口加速 interface Ethernet0/0/2 stp edged-port enable SVI+VRRP SW1 interface Vlanif1 ip address 172.
一、定义: STP(Spanning Tree Protocol)是生成树协议的英文缩写,可应用于计算机网络中树形拓扑结构建立,主要作用是防止网桥网络中的冗余链路形成环路工作。但某些特定因素会导致STP失败,要排除故障可能非常困难,这取决于网络设计 [1] 。生成树协议适合所有厂商的网络设备,在配置上和体现功能强度上有所差别,但是在原理和应用效果是一致的。
二、功能介绍 生成树协议是IEEE 802.1D中定议的数据链路层协议,用于解决在网络的核心层构建冗余链路里产生的网络环路问题,通过在交换机之间传递网桥协议数据单元(Bridge Protocol Data Unit,简称BPDU),通过采用STA生成树算法选举根桥、根端口和指定端口的方式,最终将网络形成一个树形结构的网络,其中,根端口、指定端口都处于转发状态,其他端口处于禁用状态。如果网络拓扑发生改变,将重新计算生成树拓扑。生成树协议的存在,既解决了核心层网络需要冗余链路的网络健壮性要求,又解决了因为冗余链路形成的物理环路导致“广播风暴”问题 [2] 。
但是,由于协议机制本身的局限,STP保护速度慢(即使是1s的收敛速度也无法满足电信级的要求),如果在城域网内部运用STP技术,用户网络的动荡会引起运营商网络的动荡。在MSTP 组成环网中,由于SDH保护倒换时间比STP协议收敛时间快的多,系统采用依然是SDH MS-SPRING或SNCP,一般倒换时间在50ms以内。但测试时部分以太网业务的倒换时间为0或小于几个毫秒,原因是内部具有较大缓存。SDH保护倒换动作对MAC层是不可见的。这两个层次的保护可以协调工作,设置一定的“拖延时间”(hold-off),一般不会出现多次倒换问题。
三、协议不足 1、拓扑收敛慢,当网络拓扑发生改变的时候,生成树协议需要50-52秒的时间才能完成拓扑收敛。
2、不能提供负载均衡的功能。当网络中出现环路的时候,生成树协议简单的将环路进行Block,这样该链路就不能进行数据包的转发,浪费网络资源。
四、端口状态编辑 语音 Blocking(阻塞状态):此时,二层端口为非指定端口,也不会参与数据帧的转发。该端口通过接收BPDU来判断根交换机的位置和根ID,以及在STP拓扑收敛结束之后,各交换机端口应该处于什么状态,在默认情况下,端口会在这种状态下停留20秒钟时间。
Listening(侦听状态):生成树此时已经根据交换机所接收到的BPDU而判断出了这个端口应该参与数据帧的转发。于是交换机端口就将不再满足于接收BPDU,而同时也开始发送自己的BPDU,并以此通告邻接的交换机该端口会在活动拓扑中参与转发数据帧的工作。在默认情况下,该端口会在这种状态下停留15秒钟的时间。
Learning(学习状态):这个二层端口准备参与数据帧的转发,并开始填写MAC表。在默认情况下,端口会在这种状态下停留15秒钟时间。
Forwarding(转发状态):这个二层端口已经成为了活动拓扑的一个组成部分,它会转发数据帧,并同时收发BPDU。
Disabled(禁用状态):这个二层端口不会参与生成树,也不会转发数据帧。
五、STP潜在故障编辑 语音 1、生成树算法不稳定
STP协议工作在第二层,在交换机端口之间传递网络协议单元获取网络拓扑,并通过STA算法阻断环路形成树形逻辑网络拓扑。但如果网络拓扑过于复杂,STA算法有时会存在失效的情况,这时根桥、根端口和指定端口的选举失败,导致环路的产生,使网络瘫痪。这一问题的根本原因理论上还无定论,多数人认为是STP协议本身不稳定的问题,比如STP生成树收敛过慢,导致网络协议单元数据包丢失过多,STA误以为网络中出现了单点故障,从而使处于阻塞状态的端口变为转发状态,网络出现环路导致网络瘫痪。此种故障出现的概率很低,但出现了很难排除。
2、端口工作方式导致端口工作模式不匹配
交换机的端口工作模式有单工(Simplex)、半双工(half-duplex)和全双工(full-duplex)三种模式,一般在配置时都采用自动协商的方式。在配置时如果将交换机一端人工设置为全双工,另一端仍然采用自动协商方式,在有些品牌的交换机中,将使通信链路在半双工模式下工作;更有一种极端的方式,将一端交换机的端口工作方式设置为全双工模式,而将链路对端交换机的端口设置为半双工模式,这都会导致双工不匹配的问题。其结果是工作在全双工模式下的端口在发送数据前不载波侦听链路是否处于空闲状态,直接发送数据,而工作在半双工模式下的端口在发送数据前先执行载波侦听且当链路处于空闲状态时才发送数据,此时,如果全双工端口持续性的有大量数据需要发送,那么半双工状态的端口将不会有数据传送给对端。STA在计算的时候,由于半双工状态的端口发送不了网络协议单元,STA会将处于阻塞状态的端口打开,从而形成环路。
3、单向链路故障
在采用光纤为通信介质的网络中,往往采用两组光纤收发链路来保证网络的可靠性和稳定性(一组通信,一组冗余),由于光纤收发器的故障、任意一组收发对中的某一条链路故障或者两组链路中的某一条链路出现了交叉连接,都会导致本端收发器能收到对端收发器发送的报文,但对端收发器收不到本端收发器发送的报文,这种故障称为单链路现象,隐蔽性高,不易排错。由于单链路故障影响了STP的网桥协议单元的发送,致使STA计算出现错误码,将本应处于阻断状态的端口转变为转发状态,从而导致环路的产生。
4、数据帧被损坏
交换机是二层通信,如果物理链路的通信质量不高(通信介质质量问题或干扰问题等),将导致数据帧在传输时被损坏,从而被丢弃。网桥协议单元在传输时因信道质量不高而损坏达到一定量后,会使STA误认为出现单点故障而将已阻断的端口打开通信。一般对于STP协议来讲,如果阻塞端口丢失网桥协议单元的状态超过50秒,就会出现故障。
5、网络设备资源不足引起故障
STP协议的执行及其网桥协议单元的处理都由网络设备(主要是交换机)的CPU来进行,如果交换机的CPU本身处理能力不强或被其他问题过渡占用,使交换机无法及时发出或接收网桥协议单元,引起STP无法正常工作的故障。
6、配置Por tFast快速端口引起的故障
在运行STP的网络中,如果将交换机上直接连接主机的端口配置为Port Fast,可以使端口直接从阻断状态转变为转发状态,从而使STP网络快速收敛。如果网络管理员在配置交换机是,将用于连接其他交换机的某个端口也设置为Port Fast,那么当该端口被启用时会直接进入转发状态,从而导致网络中短时存在环路,当环路中的数据流量相当大时,网络会瘫痪 [2] 。
其中有部分摘自百度百科https://baike.baidu.com/item/STP/2813395?fr=aladdin
生成树协议:
企业网三层架构—》冗余----》线路冗余—》二层桥接环路
导致问题: 1、 广播风暴
2、 MAC地址表翻滚 —在一台交换机上,同一个MAC地址只能映射唯一的接口;但同一个接口可以映射多个不同的MAC地址;
3、 同一数据帧的重复拷贝
4、 以上3个条件最终导致设备工作过载,导致重启保护
生成树:在一个二层交换网络中,生成一棵树型结构,逻辑的阻塞部分接口,使得从根到所有的节点仅存在唯一的路径;当最佳路径故障时,自动打开部分阻塞端口,来实现线路备份的作用;
生成树在生成过程中,应该尽量的生成一棵星型结构,且最短路径树;
存在算法: 802.1D PVST PVST+(CISCO) RSTP(802.1w) MSTP(802.1S)
一、802.1D 一个交换网络内仅存在一棵生成树实例; 交换机间使用BPDU—桥协议数据单元 – 交换机间沟通互动收发的数据
作者:bug菌
博客:CSDN、掘金、infoQ、51CTO等
简介:CSDN/阿里云/华为云/51CTO博客专家,博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者,全网粉丝合计10w+,硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费领取简历模板/学习资料/大厂面试真题/职业规划等海量资料。
网络上关于Spring Boot杂而不精,很难系统化、全面地了解Spring Boot。如果想要对最新的技术要点进行系统的梳理、解读及应用, 推荐你看《滚雪球学Spring Boot》
该专栏分为【基础篇】和【进阶篇】两个阶段;目的是为了由浅入深、循序渐进式的引导大家轻松入门Spring Boot;为了方便同学们可以吃透,bug菌特地将其理论知识与实战项目教程结合到了一起,以图文并茂的展示方式,最大程度的帮助你们弄明白。
所以,大家可以放心进行收藏&&订阅,便于同步学习;目前活动促销价9.9,活动结束后会恢复原价99;早买不会亏,投资自己学习性价比最高,一起拔高学习吧。
专题目标:该专栏会一直不断更新,致力打造全网最全最新最有价值的Spring Boot 学习教程,让学习者从入门到精通,欢迎大家持续关注。
SpringBoot学习路线汇总 如下我整理了Spring Boot从入门到精通的完整学习路线,其中对所有技术点都做了难易程度标识,以便于大家能精准投入对应的学习时长。
1. Spring Boot 是什么? 随着动态语言流行(Ruby,Scala,NodeJs等),Java 开发变得相对笨重,配置繁琐,开发效率低下,部署流程复杂,以及第三方集成难度也相对较大,针对该环境,Spring Boot被开发出来,其使用“习惯大于配置目标”,借助Spring Boot 能够让项目快速运行起来,同时借助Spring Boot可以快速创建web 应用并独立进行部署(jar包 war 包方式,内嵌servlet 容器),同时借助Spring Boot 在开发应用时可以不用或很少去进行相关xml环境配置,简化了开发,大大提高项目开发效率。
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,让Spring Boot在蓬勃发展的快速应用开发领域(rapid application development)成为领导者.
2. 为什么要学习Spring Boot? 针对这个疑问,我分别从以下三个层面进行分析概述,告诉大家为什么Spring Boot 为什么非学不可!
2.1 从Spring官方来看 我们打开 Spring 的官方网站,可以看到下图,你们能看到什么?
表明官方对 Spring Boot 的定位是 :Build Anything, Build任何东西。Spring Boot旨在尽可能快地启动和运行,并且只需最少的 Spring 前期配置。 同时我们也来看一下官方对后面两个的定位:
SpringCloud:Coordinate Anything,协调任何事情。SpringCloud Data Flow:Connect everything,连接任何东西。 仔细品味一下,Spring 官网对 Spring Boot、SpringCloud 和 SpringCloud Data Flow三者定位的措辞非常有味道,同时也可以看出,Spring 官方对这三个技术非常重视,是现在以及今后学习的重点(SpringCloud 相关达人课课程届时也会上线)。
marked在vue项目中改变超链接跳转方式和图片放大预览 这里我是另起一个js文件对marked的配置做了修改,参考如下
import marked from 'marked' let renderer = new marked.Renderer() const linkRenderer = renderer.link const imgRenderer = renderer.image // 超链接使用新窗口打开 renderer.link = (href, title, text) => { const html = linkRenderer.call(renderer, href, title, text) return html.replace(/^<a /, '<a target="_blank" ') } // marked解析过程中解析到图片的回调,为每个img标签绑定点击事件,并传递当前事件以及href图片链接 renderer.image = function (href, title, text) { const img = imgRenderer.call(renderer, href, title, text) // 在图片元素上添加点击事件处理函数 return `<img width="800" height="500" οnclick="showMarkedImage('${href}')" src="${href}" alt="${text}" title="${title ? title : '' }"
文章目录 1、首先说一下,什么是高速缓存?2、典中典(多线程操作同一个资源容易产生相互覆盖) 1、首先说一下,什么是高速缓存? 高速缓存(Cache)是计算机体系结构中的一种关键性技术,用于提高数据访问速度和系统性能。它在处理器和主内存之间充当了一个临时存储器层,用于暂存常用的数据和指令,以减少处理器对主内存的访问次数,从而提高数据访问速度。
高速缓存往内存更新的时机是不确定的,如果数据更新回内存,高速缓存中的数据一定会清除,下次再计算需要重新在内存拷贝一份到高速缓存计算。
2、典中典(多线程操作同一个资源容易产生相互覆盖) 两个线程t1,t2,各线程一共需要对i加10次,t1在高速缓存中加了9次刷新回去,内存中a=9,线程切换,t2+了1次刷新回去,覆盖,此时a=1。t2又被选中执行,将a=1从内存读取到高速缓存中,t2+了剩下的9次,在高速缓存中,t2的a=10,还没来得及往内存刷新,切换线程,t1将内存中的a=1读取到,+了剩下的1次,此时在高速缓存中,t1的a=2,没来的及刷新回内存,切换线程,t2执行,将a=10刷新回内存,此时内存中a=10;t2线程结束,当等到t1线程执行,将a=2刷新回内存,此时内存中a由t2的a=10,被覆盖为t1的a=2;
环境介绍
技术栈
springboot+mybatis+mysql
软件
版本
mysql
8
IDEA
IntelliJ IDEA 2022.2.1
JDK
1.8
Spring Boot
2.7.13
mybatis
2.3.1
springboot是基于spring 4.0,springboot2是基于spring5.0,springboot2由pivotal公司在2018发布,这个框架主要用来简化ssm开发,核心思想“约定大于配置”。
上传图片,数据库存储图片路径,但前端页面无法显示图片的问题有
1、windos与linux的路径不同
2、mysql存储路径的长度不够
前端界面
<form id="form-changeAvatar"
class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-2 control-label">选择图片:</label>
<div class="col-md-5">
<img id="img-avatar" src="../images/index/user.jpg" class="img-responsive" />
</div>
<div class="clearfix"></div>
<div class="col-md-offset-2 col-md-4">
<input type="file" name="file">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input id="btn-changeAvatar" type="button" class="btn btn-primary" value="上传" />
</div>
</div>
</form>
前端ajax
<script type="text/javascript"> $(document).
#这里选择内网接口下发地址。
#地址绑定可以下发指定地址。
#还有域名租期什么的。
PC机获取到的ip地址。
#因为这里是继上一知识点继续做的所以可以直接访问公网。
首先下载php的安装包,选择合适版本的安装包 下载链接 PHP For Windows: Binaries and sources Releases
将安装解压 打开Viscode安装扩展 配置环境 将路径写入 这里注意用的是在家解压安装包后的地址,并且\要换成/ 注意,这里若是运行后数据库报错,则需要将安装包下的php.ini-development 改为php.ini
"php.validate.executablePath": "d:/PHP安装/php-8.0.29-nts-Win32-vs16-x64/php.exe", "php.debug.executablePath": "d:/PHP安装/php-8.0.29-nts-Win32-vs16-x64/php.exe", "phpserver.phpConfigPath": "d:/PHP安装/php-8.0.29-nts-Win32-vs16-x64/php.ini", "phpserver.phpPath": "d:/PHP安装/php-8.0.29-nts-Win32-vs16-x64/php.exe" 返回文件,右键reload 如果觉得对你有帮助,请一键三连哈哈,谢谢兄弟
知识点:编辑器漏洞,领导讲话的图片很可能来自于编辑器这个路径,从图片路径找到编辑器路径进行突破。
根据提示,在源码中搜索editor,ctrl+u查看源代码,ctrl+f查看editor关键字 输入路径 着重看插入文件 浏览网站目录var/www --->html--->nothinghere--->.txt文件 上传发现路径,进行url访问,发现目录错啦,因为我们访问的是绝对路径 应该是网站根目录下的路径地址url/nothinghere/fl000g.txt,可以每次删除一小个目录尝试
启动靶场 发现底部的document可以单击 进入了一个paf文件,里面给出了的用户和密码,以及后台登录地址 your-domain 代表你的网域,靶场地址
输入url/system1103/login.php
登录后获得flag
1:修改docker配置文件docker.service vi /usr/lib/systemd/system/docker.service 2:找到 ExecStart,在最后面添加 -H tcp://0.0.0.0:2375 # for containers run by docker ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always 3:开放系统端口 3-1:关闭防火墙 systemctl stop firewalld 3-2:防火墙开放端口 添加 --permanent永久生效,没有此参数重启后失效 firewall-cmd --zone=public --add-port=2375/tcp --permanent 重新载入 firewall-cmd --reload 查看所有打开的端口: firewall-cmd --zone=public --list-ports 4:重启docker 4-1:如果docker启动了执行命令 [root@localhost ~]# systemctl stop docker.socket 4-2:执行启动命令 [root@localhost ~]# systemctl daemon-reload && systemctl start docker 4-3:通过docker启动状态可以查看是否读取了配置文件和开启了监听2375端口 [root@localhost ~]# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.
一:使用注解来实现IoC(Inversion of Control,控制反转) 使用注解来实现IoC就是通过在代码中添加特定的注解,告诉IoC容器如何创建和管理对象,并自动注入到需要的地方。借助于注解,开发者无需手动创建对象、处理对象之间的依赖关系,而是委托给IoC容器来完成这些工作。
几个常用的注解,用于实现Spring IoC: @Component:用于标识一个普通的Java类为一个组件(Bean),由Spring容器进行管理。@Repository:用于标识一个数据访问组件,通常与持久层相关。@Service:用于标识一个服务层组件,通常用于业务逻辑处理。@Controller:用于标识一个控制器组件,通常用于Web应用程序中的请求处理。 依赖注入的注解: @Autowired:自动装配依赖,可用于构造方法、属性、Setter方法上。@Qualifier:用于指定具体的Bean实例,配合@Autowired使用。@Value:用于注入简单类型的值或表达式。 二:一个示例,展示如何使用注解实现Spring IoC: 1.为了启用注解驱动的IoC功能,还需要在applicationContext.xml配置文件中添加以下代码 <!--注解扫描包 --> <context:component-scan base-package="com.cskt.mapper,com.cskt.service"/> 上述配置指定了要扫描的基础包路径,Spring容器会扫描该路径下的组件,并进行相应的管理和依赖注入。
2.@Repository标识持久层组件 package com.cskt.mapper; import com.cskt.pojo.User; import org.springframework.stereotype.Repository; import java.util.List; @Repository("userMapper")//这里的括号类似ID来标识 public class UserMapperImpl implements UserMapper{ @Override public List<User> getUserAll() { System.out.println("执行了查询所有!!!"); return null; } } 标识持久层组件:使用 @Repository 注解可以将一个类标识为持久层组件。这样,Spring 在进行组件扫描时会自动检测到该类,并将其实例化为一个 Bean,由 Spring 容器进行管理
3.@Service标识服务层组件 package com.cskt.service; import com.cskt.mapper.UserMapperImpl; import com.cskt.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service("userService")//这里的括号类似ID来标识 public class UserServiceImpl implements UserService{ @Autowired private UserMapperImpl userMapper; @Override public List<User> getUserAll() { userMapper.