vlookup四个条件匹配公式

在Excel中,VLOOKUP函数用于根据给定的条件在垂直范围内进行查找,并返回匹配条件的结果。然而,VLOOKUP函数本身只支持一个条件的匹配。如果你需要使用四个条件进行匹配,可以使用一些组合函数来实现。 一种常见的方法是使用组合函数如INDEX和MATCH来实现多条件匹配。以下是一个示例公式,展示了如何使用四个条件进行匹配: =INDEX(return_range, MATCH(1, (condition1_range = condition1) * (condition2_range = condition2) * (condition3_range = condition3) * (condition4_range = condition4), 0)) 在这个公式中,需要做以下替换: return_range:表示要返回值的范围,也就是根据四个条件匹配后要提取值的范围。 condition1_range:表示第一个条件的范围,也就是要与第一个条件进行匹配的数据的范围。 condition1:表示第一个条件的值,也就是要匹配的具体条件1。 condition2_range、condition2、condition3_range、condition3、condition4_range、condition4:同上,表示其他三个条件的范围和值。 这是一个数组公式,需要使用Ctrl + Shift + Enter键来输入该公式,而不是普通的Enter键 该公式会在给定的条件下,在匹配的范围内查找并返回相应的值。根据自己的具体数据和条件,可能需要适当调整公式中的范围和条件

STM32单片机(四)第二节:OLED显示屏

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。 🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。 ⭐️ 专栏主要内容: 主要学习STM32单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。 🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。 💑专栏主页:http://t.csdn.cn/HCD8v 本学习过程参考:https://space.bilibili.com/383400717 STM3单片机安装软件、各种资料以及源码的路径: 链接:https://pan.baidu.com/s/1snD0uuTfMhchFqOMWvAiHA?pwd=asdf#list/path=%2F 提取码:asdf 链接里压缩包的解压密码:32 本大节主要学习OLED调试工具,包含两部分,第一小节主要学习OLED的基础知识,第二小节是写一个简单的程序进行练习,即OLED显示屏,最终提供一个OLED显示屏的驱动函数模块,可以在OLED上显示我们需要的调试信息; 本小节主要是学习如何使用驱动函数,使OLED显示屏上显示我们所需要的内容以及调试信息。 文章目录 一、本节目标二、OLED显示屏2.1 接线图2.2 代码实现 一、本节目标 在OLED屏幕上显示一些我们需要输出端的信息,包含字符和数字等: 二、OLED显示屏 2.1 接线图 从上图可以看到,把OLED插在了面包板的右下角,以后就一直把这个屏幕插在这里,方便调试; 可以看出我们使用的是4引脚的OLED屏幕,GND和VCC需要接电源的负极和正极; 将OLED插到PB6到PB9这四个口,SCL接到PB8,SDA接到PB9; 硬件电路如下图所示 2.2 代码实现 准备好的OLED驱动函数模块都放在了STM32入门教程资料\程序源码\STM32Project\1-4 OLED驱动函数模块\4针脚I2C版本这个路径下: 以上文件可以直接复制的我们对应的工程中直接使用, 例如本节,将以上文件复制到:STM32入门教程资料\程序源码\STM32Project\4-1 OLED显示屏\Hardware 源码路径: STM32入门教程资料\程序源码\STM32Project\4-1 OLED显示屏\User里存放的是main函数 #include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" int main(void) { OLED_Init(); OLED_ShowChar(1, 1, 'A'); OLED_ShowString(1, 3, "HelloWorld!"); OLED_ShowNum(2, 1, 12345, 5); OLED_ShowSignedNum(2, 7, -66, 2); OLED_ShowHexNum(3, 1, 0xAA55, 4); OLED_ShowBinNum(4, 1, 0xAA55, 16); while (1) { } } OLED.

计算机组成原理---第 六 章总线系统

一、总线的概念和结构形态 总线的基本概念 ⑴概述 总线是构成计算机系统的互联机构,是多个系统功能部件之间进行数据传送的公共通路。 ⑵ 分类 总线的分类方式有很多:如被分为外部总线和内部总线、系统总线和非系统总线、片内总线和PCB板级总线、串行总线和并行总线、高速总线和低速总线、同步总线和异步总线。专用总线和通用总线等。 如以用途分类:一个单处理器系统中的总线,大致分为三类: ①CPU 内部连接各寄存器及运算部件之间的总线,称为内部总线; ②CPU 同存储器、通道等计算机系统的其他高速功能部件互相连接的总线,称为系统总线; ③中、低速 I/O 设备之间互相连接的总线,称为 I/O 总线。 ⑶ 特性 ①物理特性 ②功能特性 ③电气特性 ④时间特性 ⑷ 性能指标 衡量总线性能的重要指标是总线带宽,即总线本身所能达到的最高传输速率,单位是兆字节每秒(MB/s)。设总线的总线周期为 T,其在一个总线周期中共传输 D 个字节,则总线带宽为 D/T。 ⑸ 2. 总线的连接方式 外围设备通过适配器与计算机连接,从而实现高速 CPU 与低速外设之间工作速度上的匹配和同步,并完成计算机和外设之间的所有数据传送和控制,适配器通常简称为接口。 ⑴ 单总线结构 在许多单处理器的计算机中,使用单一的系统总线来连接 CPU、主存和 I/O 设备,称为单总线结构,如图8.22 所示。 单总线结构有以下特点: ①连接到总线上的逻辑部件必须高速,从而避免不必要的时间延迟; ②当 CPU 读取指令时会将程序计数器中的地址同控制信息送至总线,而只有地址与总线传输的地址相对应的设备才会执行数据传送操作; ③在单总线系统中,对输入/输出设备的操作,完全与对主存的操作方法一样; ④在单总线系统中,某些外围设备也可以指定地址;(访问存储器和访问外设指令相同,由地址来区分) ⑤单总线结构容易扩展成多 CPU 系统。 ⑥总线简单,使用灵活、易于扩展 ⑦任意两设备之间理论上都可以直接交换信息。 ⑧所有设备分时工作,仅适用于低速的计算机系统中。 ⑵多总线结构 由于单总线系统的信息传送效率和吞吐量都受到极大限制,因此产生了多总线结构,如图 所示。 多总线结构有如下几个特点: ①CPU 和 cache 之间采用高速的 CPU 总线,主存连在系统总线上,通过桥,CPU 总线、系统总线和高速总线彼此相连; ②高速总线通过扩充总线接口与扩充总线相连,扩充总线可以连接串行工作方式的 I/O 设备;

安全测试--AppScan

目录 一、测试工具 二、测试步骤 三、AppScan使用特别注意事项 一、测试工具 AppScan,即 AppScan standard edition。其安装在 Windows 操作系统上,可以对网站等 Web 应用进行自动化的应用安全扫描和测试。 简单理解,就是AppScan工具先抓取出所有的接口,接着利用自身的安全用例库,对接口传各种参数,验证接口是否有安全漏洞。 二、测试步骤 1、打开AppScan,文件--新建--扫描Web应用程序 2、填写起始URL地址 这里有个坑:填写登录页面的地址,最好是未登录之前,因为有的页面没有做重定向处理,后续测试的时候会一直提示登录。 比如登录页面的地址是https://XXX/Login,最好别填登录进去后的某个地址例如:https://XXX/Login/index 注意:第一次启动时,会询问是否使用代理,选择不使用代理,点击下一步,下次不会再询问。 3、填写登录管理信息 登录系统的方式,有三个选项: 1)记录:点击“记录”按钮,进行录制登录操作。操作类似于用LR做脚本录制,适用于没有验证码的场景。 2)自动:输入用户名和密码,扫描时会自动根据这个凭证登录应用程序,推荐没有验证码时,使用该场景。 3)提示:根据扫描地址,每次需要登录时会弹出相应登录页面,如遇后台登录有验证码时推荐使用此场景。 记录和自动的差别不大,都是适用于没有验证码的场景,而且都只需要输入一次用户名和密码,不同之处在于 「记录 」是在浏览器登录页面输入密码,「自动 」是直接在AppScan的页面输入密码。 4、测试策略 在实际测试过程中,要完整的测试就选「完成」策略,一般情况下选「缺省值」策略。 简单介绍下7种测试策略: 1)缺省值:包含多有测试,但不包含侵入式和端口侦听器 2)仅应用程序:包含所有应用程序级别的测试,但不包含侵入式和端口侦听器 3)仅基础结构:包含所有基础结构级别的测试,但不包含侵入式和端口侦听器 4)侵入式:包含所有侵入式测试(可能影响服务器稳定性的测试) 5)完成:包含所有的AppScan测试 6)关键的少数:包含一些成功可能性较高的测试精选,在时间有限时对站点评估可能有用 7)开发者精要:包含一些成功可能性极高的应用程序测试的精选,在时间有限时对站点评估可能有用 5、测试优化 自主选择即可 6、完成 1)启动全面自动扫描:会自动探索URL,而且边探索边扫描页面,也就是边扫描边测试 2)仅使用自动“探索”启动:自动探索URL,不做扫描,只是探索出所有的接口,不对接口进行任何操作 3)使用“手动探索”:手动去访问页面,AppScan会自动记录你访问页面的url 4)我将稍后启动扫描:AppScan不做任何操作,需要自己手动去启动扫描 7、保存文件 8、进行第一遍的探索结果 9、扫描结束点击工具栏的“扫描”中的“仅测试”,查看测试结果 10、导出报告 三、AppScan使用特别注意事项 【1】AppScan扫描过程中,会向服务器发送较多请求,会占用一定的正常请求访问的资源,可能导致一些垃圾数据,建议只在本地测试环境执行 【2】使用AppScan之前,请提前备份好数据库的数据,假若扫描致使服务器异常关闭,则需重启服务;若扫描产生的请求数据过多,或Web程序出现异常,可能需要从备份数据恢复还原。一般情况下,正常扫描Web程序很少可能出现Web服务异常的情形 【3】AppScan扫描配置时,有区分为Web Application(Web应用程序)和Web Service(Web服务)的扫描方向。若只对Web程序本身的漏洞检测,就选Web Application扫描即可; 若选择Web Service扫描,则需提前告知服务器维护的负责人,建立异常情况发生的处理机制,最好避开访问请求的高峰or办公人员集中使用的时间,比如下班后自动扫描 【4】AppScan扫描的结果并不代表完全真实的情况,受限于所用扫描器版本的漏洞规则库的规则,以及操作者的配置策略,扫描过程中有可能会使得扫描器出现误判or漏测。 如有必要,还需对扫描的结果进行人工校验,可对同一Web应用分次进行扫描对比差异性 【5】扫描配置时,一般按照默认的测试策略-WASC威胁分类即可;若服务器本身所能承受的性能压力不强,or存在较多漏洞的时候,不宜选择“侵入式”策略,该策略存在着可能会入侵服务器、关闭服务、破坏数据库等风险 【6】使用破解版的AppScan扫描Web应用时,若Web网站本身结构比较复杂、模块众多、涉及的url数目巨大(几万-十多万), 则不宜一次性全站扫描,有可能连续扫描几个小时都不能探索完网站的所有结构。持续时间过长还可能造成AppScan出现卡顿,显示“正在扫描中”,但实际上已经没有继续再扫描。 因此,当第一次探索了大概的网站结构和容量之后,若容量巨大,最好分而治之,按模块结构分批进行扫描测试 【7】结果分析(Analysis) 在APPScan扫描结果基础上,根据不同的严重级别进行排序、手工+工具验证的方式对漏洞验证可靠性,排除误报的情况,并尽可能找出漏报的情况,把本次扫描结果汇总,对以上已验证存在的安全漏洞排列优先级、漏洞威胁程度,并提出每个漏洞的修复建议 然后,再把此次安全漏洞整理的报告提交给项目负责人,由负责人决定哪些漏洞转给开发工程师修复,而后再由安全测试工程师进行回归验证修复的状况

github Actions知识点与git仓库备份实践

github Actions知识点与git仓库备份实践 Github Actions 是 GitHub 推出的持续集成 (Continuous integration , 简称 (I) 服务 , 它提供了配置虚拟服务器环境 , 基于它可以进行构建 、 测试 、 打包 、 部署项目 。 GitHub Actions 为每个任务 (job) 都提供了一个虚拟机来执行 , 每台虚拟机都有相同的硬件资源 : 2-core CPU7 GB RA M 内存14 GB SSD 硬盘空间 ( 实测硬盘总容量为 90G 左右 , 可用空间为 30G 左右 ) 使用限制: 每个仓库只能同时支持 20 个 workflow 并行 。每小时可以调用 1000 次 GitHub API 。每个 job 最多可以执行 6 个小时免费版的用户最大支持 20 个 job 并发执行 , macOS 最大只支持 5 个私有仓库每月累计使用时间为 2000 分钟( 超过后 $ 0 , 008 / 分钟 , 公共仓库则无限制 ) 配置 核心概念与层次关系:workflow/job/step/action

github下载的项目如何上传到gitee

1、安装git 省略 2、github下载项目 如何注册、登录省略 3、上传到gitee 注册账号 省略 新建仓库 iot-plat创建过了,用iot-plat1演示 创建完的仓库 此处的https地址要记住,等会要用到 到本地项目目录 项目里面 Git命令操作 空白处右键,选中 Git Bash Here 配置用户名和邮箱 全局操作,配置过的,就不用配置了,可以略过 git config --global user.name "xxx" git config --global user.email "xxx" 初始化本地仓库 git init 添加项目文件至本地仓库 git add . 提交添加注释 first submit是自己定义的注释内容 git commit -m 'first submit' 连接本地仓库与远程仓库 先清掉github远程仓库信息 git remote rm origin 再建立gitee的远程仓库连接 注:https这个链接就是上面gitee创建完仓库的那个连接 git remote add origin https://gitee.com/XXX/iot-plat1.git push本地仓库内容到远程仓库 git push -u origin master gitee上查看项目内容 看到项目文件,则证明上传成功。

中文网页自动导航挑战赛——lora微调ChatGLM经验分享

继续前一篇文章,ChatGLM-6B-int4模型精度稍低,效果不理想,需要微调更大的模型。为此,租了一台32GB的 TESLA V100,来完成这次比赛。本文记录ChatGLM的lora微调下的模型调优过程。 环境配置 本文使用的环境是: Miniconda-conda3-Python3.8(ubuntu18.04)-Cuda11.3安装必要的工具包 !pip install peft !pip install cpm_kernels !pip install icetk !git clone https://github.com/THUDM/ChatGLM-6B.git cd ChatGLM-6B !pip install -r requirements.txt 配置GPU import torch device = torch.device('cuda:0') 导入工具包 import os import torch import numpy as np import json from transformers import AutoTokenizer, AutoModel, AutoConfig, TrainingArguments, Trainer from peft import LoraConfig, get_peft_model, TaskType from torch.utils.data import Dataset 配置模型及微调参数 导入模型 checkpoint = "THUDM/chatglm-6b" tokenizer = AutoTokenizer.from_pretrained(checkpoint, trust_remote_code=True) model = AutoModel.

kkfileview介绍安装及使用

背景 开发中网页端管理系统中会有各种类型的文件,比如(pdf、doc、docx、xls、ppt、png等),文件上传后数据库存放的都是文件的链接,除了图片能简单地实现在线预览外,其他文件基本上都需要下载了才能看到里面的内容。而有时候我们只是想看看里面的内容,但要我们自己在代码中实现这么多文件都能在线预览的工作量是很大的,还可能会有浏览器和文件的兼容问题。 项目介绍 kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等。项目作者也列出了支持预览的20多种大种类的文件。 官方支持的预览文件 软件安装 下面是Windows、Linux、docker三种安装方式,大家可以根据自己的需要进行安装。 开发工具演示 开始Windows版本使用前,我们先使用idea编辑器进行简单的演示,最后用idea将其打成jar,以备后续的其他系统的使用。 1、下载源码文件 码云上搜索 kkFileView 2、Idea运行 运行ServerMain中的main方法就可以。 3、本地预览 项目启动后会自动打开页面,端口号等配置都是可以在config文件夹中修改application.properties配置信息就行修改。具体的配置项代表意思可以进入其官网查询。 本地预览 4、使用maven插件将其打包 打包完的文件就会有Windows和Linux的版本的包。 Windows版本安装 1、将上面打包好的zip的包解压 2、运行bin文件夹中的startup.bat 查看log文件夹中的kkFileView.log文件,出现如下图所示的信息(服务启动完成,演示页访问地址)则表示启动成功。 3、输入地址进行访问,后续操作就和在编辑器上启动时是一样的了。 Docker版本安装 1、拉取镜像: docker pull keking/kkfileview 2、运行: docker run -dit -p 8012:8012 keking/kkfileview 3、进入运行起来的容器中,然后可以进入 /opt/kkFileView-4.2.1-SNAPSHOT/bin 安装目录, 运行命令 ./showlog.sh 查看日志 具体使用 普通文件下载url预览 <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script> var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址 window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url))); http/https下载流url预览 很多系统内不是直接暴露文件下载地址,而是请求通过id、code等参数到通过统一的接口,后端通过id或code等参数定位文件,再通过OutputStream输出下载,此时下载url是不带文件后缀名的,预览时需要拿到文件名,传一个参数fullfilename=xxx.xxx来指定文件名,示例如下 <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script> var originUrl = 'http://127.0.0.1:8080/filedownload?fileId=1'; //要预览文件的访问地址 var previewUrl = originUrl + '&fullfilename=test.

【操作系统】僵尸进程与孤儿进程总结

【操作系统】僵尸进程与孤儿进程总结 参考资料: 什么是僵尸进程,如何找到并杀掉僵尸进程? 孤儿进程与僵尸进程总结 一、僵尸进程与孤儿进程是什么? 我们知道在unix / linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。 1.1、孤儿进程 孤儿进程:一个父进程退出,此时父进程调用wait()或waitpid()函数等待子进程完成再退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。 1.2、僵尸进程 僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait()或waitpid()获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。 二、僵尸进程有什么危害? 2.1、Unix 提供的进程退出机制 Unix 提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。 这种机制就是: 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait()/ waitpid()来取时才释放。 但这样就导致了问题,如果进程不调用wait()/ waitpid()的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。 2.2、僵尸进程有什么危害? 僵尸进程的 PID 还占据着,意味着海量的子进程会占据满进程表项,导致后来的进程无法 fock();僵尸进程的内核栈无法被释放掉(1K 或者 2K大小),为啥会留着它的内核栈,因为在内核栈的最低端,有着thread_info 结构,它包含着 struct_task 结构,这里面包含着一些退出信息。 2.3、为什么孤儿进程没有危害? 孤儿进程是没有父进程的进程,孤儿进程这个重任就落到了init进程身上,init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。 2.4、如何避免僵尸进程? 在Linux系统中,避免僵尸进程的方法包括: 使用wait()或waitpid()函数: 在父进程中调用wait()或waitpid()函数,等待子进程结束并返回状态码,这样可以确保子进程退出后,其资源能够被正常回收,避免产生僵尸进程。使用信号处理程程序:在父进程中注册SIGCHLD信号处理程席,当子进程结束时会向父进程发送该信号,父进程可以在信号处理程序中调用wait()或waitpid()函数回收子进程资源。fork() 两次:第一次fork的子进程在fork完成后直接退出,这样第二次fork得到的子进程就没有爸爸了,它会自动被老祖宗 init 进程收养,init会负责释放它的资源,这样就不会有"僵尸”产生了,

BAT脚本--一键打开多个应用/微信多开

Windows BAT脚本入门--一键打开多个应用/微信多开 前言BAT代码-多个应用(举例abc三个)BAT代码-多开微信(举例abc三个)总结 前言 这段代码是一个Windows批处理脚本,用于启动指定的应用程序。具体解释如下: @echo off:关闭命令行窗口的回显功能,避免输出命令执行过程中的信息。 rem a:注释,表示该行代码是一个注释,不会被执行。 start "" "C:\Program Files\bililive\livehime\livehime.exe":启动“哔哩哔哩直播姬”客户端程序,路径为“C:\Program Files\bililive\livehime\livehime.exe”。 rem b:注释,表示该行代码是一个注释,不会被执行。 start "" "D:\Program Files\Genshin Impact\launcher.exe":启动“原神”游戏启动器程序,路径为“D:\Program Files\Genshin Impact\launcher.exe”。 rem c:注释,表示该行代码是一个注释,不会被执行。 start "" "C:\Users\Administrator\Documents\BBB.appref-ms":启动“BBB”应用程序,路径为“C:\Users\Administrator\Documents\BBB.appref-ms”。 pause:暂停脚本的执行,等待用户按下任意键后继续执行下一步操作。 BAT代码-多个应用(举例abc三个) @echo off rem a start "" "C:\Program Files\bililive\livehime\livehime.exe" rem b start "" "D:\Program Files\Genshin Impact\launcher.exe" rem c start "" "C:\Users\Administrator\Documents\BBB.appref-ms" pause BAT代码-多开微信(举例abc三个) @echo off rem a start "" "C:\Program Files (x86)\Tencent\WeChat\WeChat.exe" rem b start "" "C:\Program Files (x86)\Tencent\WeChat\WeChat.exe" rem c start "

Java List<实体类> 单字段,多字段去重,条件过滤

业务代码 import com.shsnc.perform.vo.Student; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; public class EntityUtil { public static void main(String[] args) { List<Student> stuList = new ArrayList<>(); stuList.add(new Student(1, "tome", 10, "京爷")); stuList.add(new Student(2, "jack", 20, "沪爷")); stuList.add(new Student(3, "lucy", 30, "津爷")); stuList.add(new Student(4, "tome", 40, "沪爷")); stuList.add(new Student(5, "any", 50, "京爷")); stuList.add(new Student(5, "any", 50, "京爷")); System.out.println("init 初始化"); for (Student student : stuList) { System.out.println(student); } // 取出 List<Student> 集合中 name 作为 list System.

Unity 如何基于addressable来做资源管理

一、什么是Addressable系统 Addressable系统是Unity 2018.3版本中推出的一种资源管理方案,它可以帮助我们更好地管理游戏中的资源。在以往的游戏开发中,我们通常使用Resources来进行资源加载,但是这种方式存在很多问题,比如加载速度慢、内存占用高等。Addressable系统可以解决这些问题,它可以实现资源的异步加载、动态加载、按需加载等功能,从而提高游戏的效率和用户体验。 对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。 二、Addressable系统的优势 1、异步加载 Addressable系统可以实现资源的异步加载,这意味着游戏中的资源可以在后台加载,不会影响游戏的运行。这种方式可以提高游戏的加载速度,同时也可以减少内存占用,从而提高游戏的性能。 2、动态加载 Addressable系统可以实现资源的动态加载,这意味着游戏中的资源可以在运行时加载,而不是在游戏启动时加载。这种方式可以提高游戏的灵活性,同时也可以减少游戏的启动时间。 3、按需加载 Addressable系统可以实现资源的按需加载,这意味着游戏中只有需要的资源才会被加载,而不是所有的资源都被加载。这种方式可以减少内存占用,从而提高游戏的性能。 三、Addressable系统的使用 1、安装Addressable系统 在Unity中安装Addressable系统非常简单,只需要在Unity Hub中选择“Add Modules”->“Addressables”即可。安装完成后,Unity会在项目中自动创建一个“Addressable Assets”文件夹,用于存放资源。 2、创建Addressable Group 在Addressable系统中,我们需要创建一个或多个Addressable Group来管理资源。在“Addressable Assets”文件夹中右键选择“Create”->“Addressable Group”即可创建一个新的Addressable Group。在创建过程中,我们可以选择不同的打包方式、压缩方式、加载方式等。 3、添加资源 在创建完Addressable Group后,我们需要将资源添加到这个Group中。在“Addressable Assets”文件夹中右键选择“Create”->“Addressable Asset”即可创建一个新的Addressable Asset,并将其添加到指定的Addressable Group中。 4、打包资源 在添加完资源后,我们需要将这些资源打包成AssetBundle,以便在游戏运行时进行加载。在Unity中,我们可以使用Addressable系统提供的打包工具来进行打包操作。在打包完成后,Unity会在“Addressable Assets”文件夹中自动生成一个“AssetBundles”文件夹,用于存放打包后的资源。 5、加载资源 在游戏运行时,我们可以使用Addressable系统提供的API来加载资源。比如,我们可以使用Addressables.LoadAssetAsync方法来异步加载资源: Addressables.LoadAssetAsync<GameObject>("prefab"); 在加载过程中,我们可以使用异步回调函数来处理加载完成后的逻辑: Addressables.LoadAssetAsync<GameObject>("prefab").Completed += OnLoadCompleted; 6、释放资源 在游戏运行过程中,我们需要释放不再使用的资源,以减少内存占用。在Addressable系统中,我们可以使用Addressables.Release方法来释放资源: Addressables.Release(asset);

sqli-labs-master靶场搭建

新搞一台虚拟机来搭建一波! Sql-labs靶场需要进行数据库的连接,所以我们先把数据库以及相关的一些web组件安装到位。这里就是用小皮面板直接梭哈下载了。 官方网址:Windows版phpstudy下载 - 小皮面板(phpstudy) 按照提示将小皮安装下来 直接启动WNMP(windows+nginx+mysql+php) 将sqli-labs项目下载下来,github上面有:https://github.com/Audi-1/sqli-labs 下载完成之后,将它放入这个文件夹下,因为小皮启动本地web服务后,直接读取www文件夹下面的内容 整好之后,我们解压文件,然后打开浏览器进行访问 http://127.0.0.1/sqli-labs-master/ 第一次进入,需要安装一波,直接点进去自动化操作。 这个报错是因为php版本过高引起的,面板中下载低版本的php,然后启用低版本的php使用。 再次刷新页面 这个报错说明数据库配置文件中存在问题,进去检查查看。 OK,原来是密码没写,补充进去哈。 再次刷新页面 OK!!!全部都是success,这就搭建成功啦!

git本地用户名及邮箱的配置(解决在gitlab不出现unKnown的情况) 补充:git本地与远程代码通过命令比较

文章目录 问题说明环境说明解决的方法补充内容小结 问题说明 提示:这里可以添加技术概要 问题:如果没有通过git配置提交者的身份信息,在gitlab的界面会出现unknown的信息。 并且在git commit -m 的时候会出现提示信息: 环境说明 windows10终端 解决的方法 这个 git commit 命令执行后,出现了一段提示信息。这段信息告诉我们,在提交时 Git 没有找到提交者的身份信息(name 和 email),因此默认使用了当前用户名和主机名来作为提交者的身份信息,并建议我们检查并更新这些信息以确保正确性。 设置 Git 的全局用户信息,可以使用以下命令: // git 设置邮箱及用户名命令 git config --global user.name "Your Name" git config --global user.email "your-email@example.com" 添加完成后再使用命令: // git 提交命令 git push origin master 提交完之后的gitlab显示信息为: 发现此时的gitalb已经能够显示用户信息。 这些git信息不需要重新配置。一旦你在本地设置了 Git 的全局用户信息,Git 就会将这些信息保存在你的本地计算机上的一个配置文件中,无论是否新拉取了代码,这些信息都会一直保留。因此,在之后的 Git 操作中,你不需要再次手动配置你的名称和电子邮件地址。 如果要在某个特定的 Git 仓库或项目中使用不同的用户名和邮箱地址,你可以在该项目的根目录下使用 git config 命令来覆盖全局的用户信息。例如: git config user.name "Your Name" git config user.email "your-email@example.com" 要看当前git用户的用户名及邮件命令:

通过Visual Studio诊断工具定位软件CPU瓶颈

通过VS诊断工具定位软件CPU瓶颈 前情提示:正常情况下我们使用调试模式会看不到诊断工具窗口,控制台会报“无法启动标准收集器。请尝试修复 Visual Studio 的安装。 (HRESULT: 0xe1110002)”这样的错误。 解决方式:通过[Downloads - Visual Studio Subscriptions Portal](https://my.visualstudio.com/Downloads?q=remote tools visual studio 2019) 链接下载对应的版本安装便可以解决。 下面我主要讲解我是如何通过VS诊断工具去定位代码中CPU占用过高的问题。 操作步骤: 1、将代码使用debug方式运行起来; 2、使用“诊断工具”中的“记录CPU配置文件”按钮记录操作软件CPU情况; 3、停止记录分析CPU的占用比例; 如下图: 上图可以清晰的看出除了"外部调用",opencv是占比最大的 通过代码(我们只需双击我们熟悉的接口就行)比如CaptureThread这里的采集线程接口;该接口主要通过使用UWP获取RGB中的视频流,我们双击便可获取到调用堆栈 这里有opencv调用的地方,虽是占比不高但通过阅读代码这里的是调用opencv最主要的入口;我通过分析代码发现在每次取出RGB数据帧时原始格式是NV12,需要使用opencv将NV12转成bgr格式供外部使用;外部一般只有流模式情况下才会使用bgr格式,其他时间这种转化是在浪费CPU。 故而,我优化我们代码逻辑,在流模式时进行转换,在非流模式时不转化,大大降低了非流模式(大部分时间)CPU的使用率。 效果如下: 非流模式下CPU占用非常的低,之前高占用的opencv也不见了。。。。 参考:分析性能探查器中的 CPU 使用情况 - Visual Studio (Windows) | Microsoft Learn

前后端分离架构下使用 Sa-Token 完成登录认证

一、架构分析 目前绝大多数系统都已经采用 “前后端分离” 架构来设计了,传统的Session模式鉴权也不再适合这种架构(或者需要额外写很多的代码来专门适配)。 Sa-Token 是一个 java 轻量级权限认证框架,专为前后端分离架构打造,主要解决登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相关问题。 Gitee 开源地址:gitee.com/dromara/sa-… 本文将介绍在 Springboot 架构下的前后端分离项目,如何使用 Sa-Token 方便的完成登录认证。 首先在项目中引入 Sa-Token 依赖: xml复制代码<!-- Sa-Token 权限认证 --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.34.0</version> </dependency> 注:如果你使用的是 SpringBoot 3.x,只需要将 sa-token-spring-boot-starter 修改为 sa-token-spring-boot3-starter 即可。 二、无 Cookie 模式 无 Cookie 模式:特指不支持 Cookie 功能的终端,通俗来讲就是我们常说的 —— 前后端分离模式。 常规 Web 端鉴权方法,一般由 Cookie模式 完成,而 Cookie 有两个特性: 可由后端控制写入。每次请求自动提交。 这就使得我们在前端代码中,无需任何特殊操作,就能完成鉴权的全部流程(因为整个流程都是后端控制完成的) 而在app、小程序等前后端分离场景中,一般是没有 Cookie 这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊? 见招拆招,其实答案很简单: 不能后端控制写入了,就前端自己写入。(难点在后端如何将 Token 传递到前端)每次请求不能自动提交了,那就手动提交。(难点在前端如何将 Token 传递到后端,同时后端将其读取出来) 三、后端将 token 返回到前端 首先调用 StpUtil.login(id) 进行登录。调用 StpUtil.

Web系统常见的几种漏洞及防护方案

利用漏洞对计算机进行攻击渗透,前提是服务器能正常通信。服务器提供各种服务给客户端进行使用的。它是依靠端口来进行通信,黑客也是根据端口来进行入侵的。那么也不排除一些物理攻击的方式,例如社会工程学①等。 一、越权访问 不同权限账户之间的存在越权访问。 不同权限用户之间连接访问造成的功能、数据越权。 不同权限用户之间替换用户cookie造成的越权。 不同权限用户之间修改id造成的越权。 检测方法: 使用工具抓取A用户功能链接,然后登录B用户对此链接进行访问。 使用抓包工具抓取A用户ID并将此ID改成B用户的ID,查看是否可以操作B用户的功能或查看B的用户数据 使用抓包工具替换不同用户cookie的方法进行测试。 防护方案:在后台服务做严格的用户权限验证。 二、SQL注入 攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取web shell或者服务器系统权限。 检测方法: 识别用户输入。SQL注入漏洞可能在系统输入参数中,这些参数执行数据库操作。 GET、POST参数中。 COOKIE参数中。 http请求头。主机头、引用站点(referer)、User-Agent和X-Forwarded-For等。 检测SQL注入。使用SQL注入测试语句对输入参数进行测试。 特殊符号:单引号,分号,web服务器响应报错。 条件响应:and 1=1、and 1=2、’ or ‘1’=‘1、’ or ‘1’='2,两次web服务器响应不同。 时间延时:sleep(5)、waitfor delay ‘0:0:5’,系统服务器延迟响应。 参数相加:对数字类型进行加减运算,字符类型使用数据库连接符号进行连接。系统服务器响应与原来的响应相同。 利用SQL注入。对以上测试进一步利用,手工构造SQL注入语句或者使用SQLMAP检测脚本构造注入语句。 防护方案:对输入参数进行过滤、校验或者采用参数预处理的方式。 三、XSS跨站脚本漏洞 攻击者的输入没有经过严格的控制,最终显示给来访的用户,攻击者通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java, VBScript, ActiveX, Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到更高的权限(如执行一些操作)、个人网页内容、会话和cookie等各种内容。XSS漏洞包括但不仅限于:存储型XSS、反射型XSS、链接注入、框架钓鱼等。 检测方法: 查找可能出现XSS跨站的位置,网站搜索框、信息存储等。 对可能出现XSS跨站的位置进行输入,常用测试语句为: 查看网站网页源代码,测试语句是否在系统响应HTML代码中输出。没有输出则不能进行XSS跨站利用。 对有测试语句输出的响应HTML代码,进行构造使XSS测试代码能当做JavaScript代码执行。 防护方案:对用户的输入参数进行过滤、校验;输出的参数进行html实体编码。过滤、校验或者实体编码要覆盖的系统内所有参数;过滤规则强大可以有效的防止注入;系统前后端都要进行过滤。 四、任意文件上传漏洞 在应用系统的运营过程中,不可避免地要对网站的某些页面或者内容进行更新,这时便需要使用到网站的文件上传的功能。如果不对被上传的文件进行限制或者限制被绕过,该功能便有可能会被利用于上传可执行文件、脚本到服务器上,进而进一步导致服务器沦陷。 检测方法: 找到系统中可以上传文件的地方。 上传系统要求的合法文件,确定上传点可用。 上传Web Shell。 访问上传Web Shell文件的链接地址。 防护方案: 对文件格式限制,只允许某些格式上传。 对文件格式进行校验,前端和服务器都要进行校验(前端校验扩展名,服务器校验扩展名、Content Type等)。 将上传目录防止到项目工程目录之外,当作静态资源文件路径,并且对文件的权限进行设定,禁止文件下的执行权限。 五、目录遍历攻击漏洞 攻击人员通过目录便利攻击可以获取系统文件及服务器的配置文件等等。一般来说,他们利用服务器API、文件标准权限进行攻击。严格来说,目录遍历攻击并不是一种web漏洞,而是网站设计人员的设计“漏洞”。如果web设计者设计的web内容没有恰当的访问控制,允许http遍历,攻击者就可以访问受限的目录,并可以在web根目录以外执行命令。 检测方法: 爬行或者暴力破解系统目录结构。 在浏览器地址栏输入网站目录,http://www.test.com/test/,查看test文件夹内的文件能否被列出来。 防护方案: 净化数据:对用户传过来的文件名参数进行硬编码或统一编码,对文件类型进行白名单控制,对包含恶意字符或者空字符的参数进行拒绝。 web应用程序可以使用chrooted环境包含被访问的web目录,或者使用绝对路径+参数来访问文件目录,时使其即使越权也在访问目录之内。www目录就是一个chroot②应用。 六、关键会话重放攻击 不断恶意或欺诈性地重复一个有效的数据包,重放攻击者可以拦截并重复发该数据到服务端,服务器端未对用户提交的数据包重放进行有效限制。如:可以抓取HTTP包中固定账号破解密码、固定密码破解账号、破解用户名和重放提交投票数据包。

分享5种常用计算机编程算法及示例代码提升效率的关键

五种算法如下: 1. 搜索算法(例如深度优先搜索和广度优先搜索):搜索算法用于在数据集中查找目标元素或满足特定条件的元素。它们广泛应用于图形遍历、路径搜索、解决迷宫问题等领域。例如,深度优先搜索可用于解决迷宫问题,以下是一个使用深度优先搜索算法找到迷宫路径的示例: void DepthFirstSearch(int[][] maze, int startX, int startY, List<(int, int)> path) { // 检查是否到达终点 if (startX == maze.Length - 1 && startY == maze[0].Length - 1) { path.Add((startX, startY)); // 输出路径 foreach (var point in path) { Console.WriteLine($"({point.Item1}, {point.Item2})"); } return; } // 检查当前位置是否有效 if (startX < 0 || startX >= maze.Length || startY < 0 || startY >= maze[0].Length || maze[startX][startY] == 1) { return; } // 标记当前位置已访问 maze[startX][startY] = 1; path.

【操作系统】什么是用户态和内核态?用户态和内核态是如何切换的?

【操作系统】什么是用户态和内核态?用户态和内核态是如何切换的? 参考资料: 用户态到内核态切换 什么是用户态和内核态? 「操作系统」什么是用户态和内核态?为什么要区分 一、什么是用户态和内核态? 1.1、概述 用户态和内核态是操作系统的两种运行状态。 内核态:处于内核态的 CPU 可以访问任意的数据,包括外围设备,比如网卡、硬盘等,处于内核态的 CPU 可以从一个程序切换到另外一个程序,并且占用 CPU 不会发生抢占情况,一般处于特权级 0 的状态我们称之为内核态。 用户态:处于用户态的 CPU 只能访问受限资源,不能直接访问内存等硬件设备,不能直接访问内存等硬件设备,必须通过「系统调用」陷入到内核中,才能访问这些特权资源。 1.2、为什么要区分用户态和内核态? 在 CPU 的所有指令中,有一些指令是非常危险的,如果错用,将导致整个系统崩溃,比如:清空内存,修改时钟等。如果所有的程序代码都能够直接使用这些指令,那么很有可能我们的系统一天将会死 n 次。 所以,CPU将指令分为 特权指令 和 非特权指令 ,对于较为危险的指令,只允许操作系统本身及其相关模块进行调用,普通的、用户自行编写的应用程序只能使用那些不会造成危险的指令。 基于安全的考虑,CPU 提供了特权分级机制,把区域分成了四个 Ring,越往里权限越高,越往外权限越低。 操作系统根据 CPU 的特权分级机制,把进程的运行空间分为「内核空间」和「用户空间」,分别对应着上图中, CPU 特权等级的 Ring 0 和 Ring 3。 二、什么时候会从用户态陷入内核态? 有三种方式程序会从用户态陷入内核态: 系统调用:这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。 这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用可以认为是用户进程「主动」发起的,异常和外围设备中断则是「被动」的。 三、什么是系统调用?过程是怎么样的? 当程序需要访问硬件资源的时候,比如内存、硬盘等,就需要通过「系统调用」陷入到内核中,才能访问这些特权资源。系统调用可以理解为内核实现的函数,比如应用程序要通过网卡接收数据,会调用 Socket 的 read 函数。 程序在执行系统调用的过程中会从用户态切换到内核态,再从内核态切换到用户态,过程如下: 系统调用的过程: 从用户态到内核态:当应用程序使用系统调用时,先将系统调用名称转换为系统调用号,接着将「系统调用号」和「请求参数」放到寄存器里,然后执行中断指令(int $0x80 指令),产生一个中断,CPU 陷入到内核态。执行内核态逻辑:CPU 跳转到中断处理程序,先将当前用户态的寄存器(用户态的代码段、数据段、保存参数的寄存器)保存到内核数据结构,接着将系统调用号从寄存器里面取出来,最后根据系统调用号,在「系统调用表」中找到相应的系统调用函数进行调用,并将寄存器中保存的参数取出来,作为函数参数。从内核态到用户态:执行完系统调用后,执行中断返回指令(iret 指令),将原来用户态保存的现场恢复回来,包含代码段、指令指针寄存器等。这时候 CPU 恢复到用户态,用户态进程恢复执行。 一次系统调用过程中的,会发生两次「 CPU 上下文切换」(所谓的 CPU 上下文就是 CPU 寄存器和程序计数器):

Mybatis之Collectin标签多层嵌套使用

一、前言 关于该篇文章,主要是通过例子展示,当编写mybatis的xml文件中,出现需要使用嵌套Collection标签时候的有效写法,以此分享给大家,同时也是作为自己在业务开发中问题解决的记录 二、原数据格式及目标数据格式映射 根据业务需求,我们的数据查询结果如下: f_idparent_namechild_name其他字段1xxxx_c_1 ...1xxxx_c_2...1testtest_c_1...1testtest_c_2...1ptpt_c_1...1hhnull... 我们希望将查询结果映射出来的对象格式(通过json体现会比较形象)如下: { "id": 1, "names": [ { "parentName": "xx", "childNames": ["xx_c_1", "xx_c_2"] }, { "parentName": "test", "childNames": ["test_c_1", "test_c_2"] }, { "parentName": "pt", "childNames": ["pt_c_1"] }, { "parentName": "hh", "childNames": [] } ] } 接下来我们需要设计类 三、类创建 @Data pulbic class ResultPO{ private Integer fId; private List<NamePO> Names; } @Data public class NamePO{ private String parentName; private List<String> childNames; } 接下来就是xml中的resultMap写法了 四、mybatis之resultMap设计 <resultMap id="myResultMap" type="xxx.ResultPO"> <id column="