linux 联网脚本

0,使用平台:imx6sl 1,自动监测: # cat /sbin/auto_switch_netif.sh #/bin/sh status_old=0 status=1 mlan0_mac=$(ifconfig mlan0 | grep 'HWaddr' | awk '{print $5}') eth0_mac=00:53:${mlan0_mac:0-11} ifconfig eth0 hw ether $eth0_mac /etc/init.d/networking restart while true do if [ -f "/tmp/auto_test.sh" ]; then exit 0 fi result=$(ethtool eth0 | grep "Link detected: yes") if [[ "$result" != "" ]]; then echo "eth0 link" status=1 else echo "eth0 not link" status=0 fi if [ $status_old != $status ]; then status_old=$status /etc/init.

HTTP状态码大全(常见 HTTP Status Code 含义查询)

原文地址 1、 HTTP Status Code 1xx 请求信息 这一组状态码表明这是一个临时性响应。此响应仅由状态行和可选的HTTP头组成,以一个空行结尾。由于HTTP/1.0未定义任何1xx状态码,所以不要向HTTP/1.0客户端发送1xx响应。 Http状态码Http Status CodeHttp状态码含义中文说明100100 Continue请继续请求101101 Switching Protocols请切换协议102102 Processing将继续执行请求 2、 HTTP Status Code 2xx 成功状态 这一组状态码表明客户端的请求已经被服务器端成功接收并正确解析。 Http状态码Http Status CodeHttp状态码含义中文说明200200 OK请求成功201201 Created请求已被接受,等待资源响应202202 Accepted请求已被接受,但尚未处理203203 Non-Authoritative Information请求已成功处理,结果来自第三方拷贝204204 No Content请求已成功处理,但无返回内容205205 Reset Content请求已成功处理,但需重置内容206206 Partial Content请求已成功处理,但仅返回了部分内容207207 Multi-Status请求已成功处理,返回了多个状态的XML消息208208 Already Reported响应已发送226226 IM Used已完成响应 3、 HTTP Status Code 3xx 重定向状态 这一组状态码表示客户端需要采取更进一步的行动来完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明。 Http状态码Http Status CodeHttp状态码含义中文说明300300 Multiple Choices返回多条重定向供选择301301 Moved Permanently永久重定向302302 Found临时重定向303303 See Other当前请求的资源在其它地址304304 Not Modified请求资源与本地缓存相同,未修改305305 Use Proxy必须通过代理访问306306 (已废弃)Switch Proxy(已废弃)请切换代理307307 Temporary Redirect临时重定向,同302308308 Permanent Redirect永久重定向,且禁止改变http方法 4、 HTTP Status Code 4xx 客户端错误 这一组状态码表示客户端的请求存在错误,导致服务器无法处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。这些状态码适用于任何请求方法。浏览器应当向用户显示任何包含在此类错误响应中的实体内容。

模型自动压缩工具实战:YOLOv7模型缩小75%,部署加速163%!

众所周知,YOLO系列算法在检测场景中获得了广泛应用,但是工程师追求“更准、更小、更快”的效率能力永无止境。本文为大家介绍一个低成本、高收益的AI模型自动压缩工具(ACT, Auto Compression Toolkit),在YOLO系列模型上利用基于知识蒸馏的量化训练方法,无需修改训练源代码,通过几十分钟量化训练,即可获得非常好的收益。举例来看:该方法在YOLOv7上模型体积降低75%,GPU上推理速度可提升163%。 图1 自动压缩工具在YOLO系列模型上的模型压缩和速度提升 【测试环境与补充说明】 1.测试数据与指标:mAP的指标均在COCO val2017数据集中评测得到。 2.测试环境:Tesla T4的GPU环境下开启TensorRT 8.4.1,batch_size=1测试获取 3.测试模型输入图像尺寸:640*640; 注:YOLOv6原论文精度Baseline是mAP43.1%,由于模型导出是固定shape,所以导成ONNX后有掉点(-0.7%),实测精度42.4%;YOLOv7在原论文Baseline mAP 51.2%,导成ONNX后实测精度51.1%。 本文将从以下五个方面进一步技术解读,全文大约2300字,预计阅读时长3分钟。 模型自动压缩工具-动机和思考 模型自动压缩工具-量化蒸馏训练技术解析 模型自动压缩工具-量化蒸馏训练技术实战(以YOLOv7为例) 模型自动压缩工具-推理部署 未来工作展望 传送门: https://github.com/PaddlePaddle/PaddleSlim/tree/develop/example/auto_compression/pytorch_yolo_series 模型自动压缩工具 动机与思考 模型量化是提升模型推理速度的手段之一,实际使用中有如下几点困难: 模型参数分布不均匀,导致量化误差大 过度训练是导致参数分布不均匀的原因之一。例如在YOLOv6s迭代过程中,为了让模型更好地收敛,通常需要延长模型训练周期。但随之也会带来一些隐患,比如模型在COCO数据集上出现了过拟合,某些层的数值分布极端化,这些状况增加了量化的噪声,我们分析了YOLOvs6每层Conv的量化精度,发现某些层精度下降的特别严重,由此导致了YOLOv6s模型离线量化后在验证集上的精度下降了10%,无法达到业务要求。 图2 YOLOv6s卷积层量化损失评估 我们对比分析了YOLOv6s的权重分布情况,发现量化损失较小的层数值分布相对平稳,数值处于-0.25到0.25之间,而量化损失较大的层数值分布非常极端,绝大部分值趋近于0,且数值处于-0.1到0.1之间,尽管看上去都是正太分布,但大量数值为0不利于量化统计scale值。 图3 权重数值分布对比 任务复杂度高,模型精度受量化误差的影响大 任务复杂度越高,模型量化带来的精度损失越大。目标检测融合了目标定位和目标分类两种任务,整体的复杂度相对较高,因此它的精度受量化的影响更大。普通的离线量化无法改变模型激活值的数值分布,只会让量化scale适应该分布。遇到数值分布不均匀的激活值,离线量化的量化误差会很大。 量化训练需修改训练代码,难度大,技术门槛高 相比离线量化(Post Training Quantization),量化训练能减少离线量化的精度掉点程度。量化训练方法在训练过程中,可以不断地调整激活的数值分布,使激活的分布更适合量化。但是,量化训练使用成本比较高,体现在以下两方面:一方面是人力成本高:为了实现量化训练,需要修改模型的组网和训练代码,插入模拟量化操作,另一方面时间成本高:训练时需要加载完整训练集做训练。 量化蒸馏训练技术解析 本文介绍的自动压缩工具(ACT)针对YOLO系列模型,利用知识蒸馏技术,自动为推理模型添加训练逻辑;无需修改训练代码,仅拿训练好的模型和部分无标注数据,训练几十分钟,即可达到预期效果。具体步骤包括如下3步,详细过程如下图所示。 构造教师模型 加载推理模型文件,并将推理模型在内存中复制一份,作为知识蒸馏中的教师模型,待量化模型则作为学生模型。 添加loss 自动地分析模型结构,寻找适合添加蒸馏loss的层,一般是最后一个带可训练参数的层。比如,检测模型head有多个分支的话,会将每个head最后一个conv作为蒸馏节点。 蒸馏训练 教师模型通过蒸馏loss监督原模型的稀疏训练或量化训练,完成模型压缩的过程。 ACT还支持更多功能,包括离线量化超参搜索、算法自动组合和硬件感知等。功能详情以及ACT在更多场景的应用,请参加自动压缩工具首页介绍。 近期我们会将自动压缩代码提到YOLOv5、YOLOv6、YOLOv7、PP-YOLOE的官方repo中,这样大家在原模型项目中也可使用该能力。 量化蒸馏训练技术实战(以YOLOv7为例) 准备预测模型 导出ONNX模型。 git clone https://github.com/WongKinYiu/yolov7.git cd yolov7 python export.py --weights yolov7-tiny.pt --grid 准备训练数据&定义DataLoader 准备COCO或者VOC格式的数据。定义数据预处理模块,其中,数据预处理Reader的设置如下: class COCOValDataset(paddle.io.Dataset): def __init__(self, dataset_dir=None, image_dir=None, anno_path=None, img_size=[640, 640]): self.

Redis(十) 布隆过滤器

速记 为什么使用布隆过滤器? 1.为了省内存,提高速率 2.因为1所以布隆过滤器不需要百分百正确 3.说存在不一定存在,说不存在一定不存在 4.在解决缓存穿透的问题时,拦截了大部分的请求,只有小部分携带了大量信息的恶意请求访问到了数据库 5.不准确的原因是可能会和别的key发生冲突,所以位数组越大精确度越高,但是占用内存越多。所以在设置布隆过滤器的时候,这个容错率是多少是百分之一还是百分之十,是否牺牲内存来提高容错率这个我们要权衡一下。 6.专门用来解决缓存穿透的问题 一. Bloom Filter 1.1 布隆过滤器介绍 Bloom Filter 专门用来解决我们上面所说的去重问题的,使用 Bloom Filter 不会像使用缓存那么浪费空间。当然,他也存在一个小小问题,就是不太精确。即说存在不一定存在,说不存在一定不存在 Bloom Filter 相当于是一个不太精确的 set 集合,我们可以利用它里边的 contains 方法去判断某一个对象是否存在,但是需要注意,这个判断不是特别精确。一般来说,通过 contains 判断某个值不存在,那就一定不存在,但是判断某个值存在的话,则他可能不存在。 1.2例子 实际案例1 以今日头条为例,假设我们将用户的浏览记录用 B 表示,A 表示用户没有浏览的新闻,现在要给用户推送消息,先去 B 里边判断这条消息是否已经推送过,如果判断结果说没推送过(B 里边没有这条记录),那就一定没有推送过。如果判断结果说有推送过(B 里边也有可能没有这条消息),这个时候该条消息就不会推送给用户,导致用户错过该条消息,当然这是概率极低的。 实际案例二 前面所说的新闻推送过滤算是一个应用场景。 解决 Redis 穿透或者又叫缓存击穿问题。 假设我有 1亿 条用户数据,现在查询用户要去数据库中查,效率低而且数据库压力大,所以我们会把请求首先在 Redis 中处理(活跃用户存在 Redis 中),Redis 中没有的用户,再去数据库中查询。 现在可能会存在一种恶意请求,这个请求携带上了很多不存在的用户,这个时候 Redis 无法拦截下来请求,所以请求会直接跑到数据库里去。这个时候,这些恶意请求会击穿我们的缓存,甚至数据库,进而引起“雪崩效应”。 为了解决这个问题,我们就可以使用布隆过滤器。将 1亿条用户数据存在 Redis 中不现实,但是可以存在布隆过滤器中,请求来了,首先去判断数据是否存在,如果存在,再去数据库中查询,否则就不去数据库中查询。 1.3 布隆过滤器原理 每一个布隆过滤器,在 Redis 中都对应了一个大型的位数组叫做位数组以及几个不同的 hash 函数。 所谓的 add 操作是这样的: 首先根据几个不同的 hash 函数给元素进行 hash 运算一个整数索引值,拿到这个索引值之后,对位数组的长度进行取模运算,得到一个位置,每一个 hash 函数都会得到一个位置,将位数组中对应的位置设置位 1 ,这样就完成了添加操作。

Feign整合Sentinel

步骤一:在feing-api项目中定义类,实现FallbackFactory: 代码: import cn.itcast.feign.clients.UserClient; import cn.itcast.feign.pojo.User; import feign.hystrix.FallbackFactory; import lombok.extern.slf4j.Slf4j; @Slf4j //记录日志 public class UserClientFallbackFactory implements FallbackFactory<UserClient> { @Override public UserClient create(Throwable throwable) { return new UserClient() { /* 在这个方法中编写降级的业务逻辑 返回 友好提示、一个默认值...,都可以在这个方法里面写 */ @Override public User findById(Long id) { //在这个方法中编写降级的逻辑 log.error("查询用户异常",throwable); return new User(); } }; } } 步骤二:在feing-api项目中的DefaultFeignConfiguration类中将UserClientFallbackFactory注册为一个Bean: 代码: //将UserClientFallbackFactory注册到bean @Bean public UserClientFallbackFactory userClientFallbackFactory(){ return new UserClientFallbackFactory(); } 步骤三:在feing-api项目中的UserClient接口中使用UserClientFallbackFactory: 代码: import cn.itcast.feign.clients.fallback.UserClientFallbackFactory; import cn.itcast.feign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.

BERT详解

bert base使用12层encoder(不是transformer) bert large使用24层encoder Bert输入部分详细解读 cls、sep存在因为bert预训练任务中有nsp任务(判断两个句子之间的关系) 将cls的输出向量接一个二分类器,去做一个二分类任务 预训练之MLM详解 bert在预训练的时候,使用的是大量的无标注的语料 认为mask是相互独立的,然而mask不是相互独立的 预训练之NSP任务详解 主题预测:两个样本是不是来自同一文档(很简单) 连贯性预测:两个段落是不是上下文关系 如何提升Bert下游任务表现 领域——>任务——>微调 bert是静态mask,我爱吃饭每次mask吃 脱敏数据如何使用bert

Mac卸载java解决安装最新版java SE报错Unable to locate an executable at “/Library/Java/JavaVirtualMachines/jdk-1

操作系统: Mac Catalina version 10.15.1 搭建java环境时不能安装最新jdk,否则使用 sudo apt install 软件的时候会提示: Unable to locate an executable at “/Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/Home/bin/apt” (-1) 解决方法: 卸载本机目前安装的java,重新更换jdk版本 sudo rm -fr /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin sudo rm -fr/Library/PreferencesPanes/JavaControlPanel.prefpane``` 查询本机jdk版本: ls /Library/Java/JavaVirtualMachines/ 删除: #这里的jdk版本是14.0.2 sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk

二进制安全:经典栈溢出手法笔记总结

二进制安全基础概念 应用程序内存空间布局 Linux x86的ELF内存布局: 高1GB空间是内核所使用并由所有用户态应用程序共享的。 栈自底向上增长,尺寸动态变化,默认临界大小是8M。 Stack和mmap间有个随机偏移量用于防止栈溢出污染mmap。 Mappings区间主要布置动态链接库。 默认进程堆自顶向下增长。 0x08048000开始的低地址映射ELF各个节区成段。 Linux 2.6.7内核以前mmap方向相反 X64的mmap方向也相反 经典栈溢出手法的应运而生 追溯到1996年著名的黑客杂志‘‘phrack’’第49期刊载的一篇文章:《Smashing The Stack for Fun and Profit》 经典栈溢出的手法概要: 1.先决条件:栈的局部变量可控,存在溢出(strcpy) 2.通过栈空间精心布局,布置shellcode,并用shellcode初始地址覆盖栈帧stack frame的ret addr。 3.Payload =[Nop sled +]Shellcode + Pad +Shellcode’s Addr 存在问题 1.Shellcode的地址在不同PC上不确定 2.每次运行地址都会变化(ALSR保护机制) 栈帧 = 局部变量 + 函数调用上下文 栈是一种LIFO的数据结构。 应用程序有一到多个用户态栈。 栈自底向上增长,由指令PUSH和POP引起其动态变化。 局部变量布局在栈中。 调用函数时参数由栈传递,返回地址也存储于栈中。 函数调用上下文与局部变量共同组成了栈帧——Stack Frame. 栈帧实际上只是一个通俗的说法,关于栈帧的上下界历来有两种说法,一曰以EBP和ESP之间的栈空间视为栈帧,这也是主流说法;一曰以调用参数和ESP之间的栈空间视为栈帧,我个人更倾向于这种说法,因为它便于理解。

阿里云服务器怎么重装系统?

阿里云服务器怎么重装系统? 好多客户对于服务器重装系统不是很了解,我们今天来说一下,跟大家理解的我们本地电脑的重装系统是不太一样的哈,但是重新系统的要求是一样的,重装系统前需要先保存服务器里的数据。 第一步:登录阿里云账号--右上角控制台 -云服务器ECS -实例 -上方地域选择服务器所在地域 第二步:看到服务器实例后选中服务器先停止,停止后点击右侧的更多选项--云盘和镜像--更换操作系统 第三步:在弹出的对话框中选择确定更换操作系统 第四步:进入公共镜像选择要换的系统即可,并设置服务器密码 第五步:设置好密码后点击确认更换即可。 经过上面的介绍,现在大家是不是对服务器更换操作系统有所了解了呢?一定要注意的是:更换系统前,一定一定要做好数据备份哦!不然数据就丢了,大家记得哦!

JS数组的操作方法 :增、删、改、查

JS数组的操作方法 :增、删、改、查 1. 增-------------------------------------------------------------- push()unshift()splice()concat() 1.1 push() 在数组的末尾追加任意数量元素 let arrs= []; // 创建一个数组 let count = arrs.push("a", "b"); console.log(arrs) // ['a','b'] console.log(count ) // 2 1.2 unshift() 在数组开头添加任意数量元素 let arrs= ['c']; // 创建一个数组 let count = arrs.unshift("a", "b"); console.log(arrs) // ['a','b','c'] console.log(count ) // 2 1.3 splice() 替换/添加/删除 一段元素 三个参数 : 必填。整数,指定在什么位置添加/删除元素,使用负值指定从数组末尾开始的位置。选填。要删除的元素数。如果设置为 0,则不会删除任何项目。选填。要添加到数组中的新元素。 let arrs= ['a','b','c']; // 创建一个数组 let count = arrs.splice(1,0,"d", "e"); // 从索引为1开始,删除0个元素,添加 'd','e' console.log(arrs) // ['a','d','e','b','c'] console.

ubuntu找不到ifconfig

Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools 出现这样的提示就是说没有找到ifconfig的命令,可以进行安装,按照提示中的命令安装相关的工具包 sudo apt install net-tools 安装完成就可以使用ifconfig。 unbuntu使用yum 切换为root用户 sudo -s 检测是否安装了build-essential程序包,输入命令: apt-get install build-essential (安装过) 参考链接

mysql安装密码问题

mysql安装密码问题 mysql-8.0.30-winx64 win10 问题描述 mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO/YES) 问题原因 安装时未设置密码,输入密码显示YES,不输入显示NO 解决方案 关闭mysql服务net stop mysql在mysql所在目录的my.ini中添加skip-grant-tables 跳过密码输入 示例: [mysqld]skip-grant-tables # 设置3306端口 port=3306 # 设置mysql的安装目录 basedir=D:\\SoftWare\\mysql\\mysql-8.0.30-winx64 启动服务net start mysql登录mysql -u root -p,输入密码时直接回车登录成功变成mysql>输入ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';12345是要设置的密码接着输入flush privileges;更新权限此时正常是输入quit退出,我直接关闭powershell重开了一个,然后重启mysql服务 net stop mysql net start mysql测试密码是否修改成功 myql -u root -p Enter Password>'新密码'成功

安卓bottomnavigationview和drawlayout实现底部导航和侧滑布局

文章目录 1.遇到的问题2.实现3.隐藏系统底部导航栏4.兼容刘海屏5.代码 1.遇到的问题 最近在开发一款app,初步的框架就是实现类似于qq布局的框架样式。那么就分为了两个部分。首先就是底部导航栏,使用bottomnavigationview和fragment可以实现,当然在创建项目时也可以使用AS默认的底部导航来进行项目创建。然后就是使用drawlayout实现侧滑的抽屉式布局。 虽然分析起来很简单,单独实现一样也很简单,但是小编在实操过程中遇到了些小问题就很蛋疼,总结如下: (1)两者合并之后竟然出现了两个actionbar,我滴个乖乖 (2)合并之后运行项目竟然闪退 (3)隐藏actionbar失效? 2.实现 (1)单独实现 使用默认的可选择方案进行单个项目的创建 在单个项目创建完成之后,跑一下项目,发现和预想的差不多,改改ui啥的就能投入使用。 然后就是合并的过程了。 两种合并方式,一种是将抽屉布局侧滑加入到底部导航的项目中,另一种则相反,各有优缺点,实现方法一致。 根据项目需要,我选择第一种合并方式,因为在侧滑菜单里的点击事件是准备跳到新的activity去进行业务实现,而并非使用当前的activity。 注意,这里有个坑,千万不要将drawlayout合并到底部导航栏的fragment里面去,小编在这儿绕了好半天呢。总之会出现各种问题,喜欢钻研的小伙伴可以去试试这种方式,最后可能会解决好问题也不一定。 (2)合并: 改变底部导航栏部分main.xml的根标签 为drawlayout,不是在fragment里面。最简单的方法就是把之前单独创建的drawlayout布局的根标签拿过来替换一下。 现在标签结构如下 <drawlayout> <BottomNavigationView></BottomNavigationView> <fragment></fragment> </drawlayout> 接着改造 把抽屉布局的NavigationView搬过来呀。 <drawlayout> <BottomNavigationView></BottomNavigationView> <fragment></fragment> <NavigationView></NavigationView> </drawlayout> 到这一步运行的话,你会发现很有趣的东西,底部导航栏并不在底部,而是跑到中间去了。 接着改 <drawlayout> <ConstraintLayout> <BottomNavigationView></BottomNavigationView> <fragment></fragment> </ConstraintLayout> <NavigationView></NavigationView> </drawlayout> 搞一个ConstraintLayout把底部导航栏的东西嵌套起来,然后底部导航栏回去了。但是这时你会发现有两个actionbar,惊不惊喜,意不意外。如果你有两个actionbar的,那把include过来的actionbar砍掉。然后就只剩一个了。 3.隐藏系统底部导航栏 首先采用修改manifest文件的方式: 选一个noactionbar的主题试试 Theme.AppCompat.Light.NoActionBar 如果你的activity是继承自AppCompatActivity的话,主题也要对应一致,不然闪退那是必须的。 但是在继承自Theme.AppCompat.Light.NoActionBar之后也闪退,没门啊。 原来是这一行出错了。 NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); 这儿设置了actionbar,我不是不要actionbar吗,你设置个冒险,滚蛋,注释了。 然后运行成功。 接着好玩的来了,主题颜色变得稀奇古怪的。 底部导航栏点击之后颜色不变深了,甚至字都看不见了。 我玩个毛线。 但是呢,遇到事情不要慌,先看看默认的apptheme是什么鬼,因为要用到底部导航的样式,所以给换回去先。 跑到style.xml下面去瞅瞅样式是啥,然后就改呀。把对应的parent改成如下。 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="

3种内网穿透方式连接家用宽带服务器

1、背景 之前做开发用的是Windows笔记本,换了MBP之后就一直放着。这本子i7的CPU、12G内存,全固态硬盘。卖了觉得可惜,放着又吃灰。最近免费升级了家里的600M的移动宽带。所以决定把这台笔记本重新装个Linux系统。但问题来了,不在家的时候,怎么连回这台服务器呢。 众所周知,家用的宽带是没有固定IP的,所以本文教大家在公网连接一台无固定IP的家用服务器(PC)。 2、穿透方法 穿透方式是否需要公网服务器速度国内/国外Ngrok不需要慢国外Frp需要快 PS:取决于你的公网云服务器国内Zerotier不需要一般国外Zerotier-Moon需要快国外 本文重点讨论的是,如何通过22端口ssh服务器,其实也可通过内网穿透,共享出TCP端口。 2.1、使用Ngrok内网穿透 https://www.ngrok.com/ 这个是最简单的方法 2.2、使用Frp内网穿透 https://gofrp.org/docs/ 2.3、使用Zerotier内网穿透 https://www.zerotier.com/ 2.4、使用Zerotier-Moon内网穿透

Service Worker 简单学习

文章目录 1. 前提Scope 限定其拦截请求范围2. 背景demo3. 加入sw Service Worker 是PWA核心,是一种 事件驱动的具有生命周期的独立于浏览器的主线程可以根据所在的目录来拦截所有网络请求可以访问缓存和IndexDB支持推送和缓存文件版本管理 特点:无法操作DOM、只能使用HTTPS和localhost 1. 前提Scope 限定其拦截请求范围 Service Worker 会根据其所在目录进行请求拦截,所以对于有离线访问需求的文件目录,可以在其中建立sw.js (目前只在根目录下测试缓存成功。。。) 2. 背景demo 页面: <select onChange="onChange(this.value)"> <option value="">--请选择--</option> <option value="/">首页</option> <option value="/login">登录</option> <option value="/register">注册</option> <option value="/data">数据</option> </select> <div id="data"></div> <script> function onChange(e) { if (e === "") return; fetch( "http://localhost:9988" + e, { method: 'GET', }).then(res => { return res.text(); }).then(res => { document.getElementById('data').innerHTML = res }) } </script> 改变选则时请求数据并显式在div中 利用sw的缓存功能,可以将一些资源进行缓存,以便下次请求时使用 3. 加入sw html引入一个app.

【Hexo】本地local4000打不开解决方法

原文链接 准备前面的工具和环境后,在本地生成博客之后却本地怎么也访问不了Hexo的网址,根据网上的解决措施,(1)改写端口,(2)自动设置代理,(3)重置Internet属性都一无所获,直到最后看见了一个大佬的解决方法,这下开心坏了,决定依此记录。 出现问题 解决措施: 在浏览地址后面加上“//”就行了。 http://localhost:4000//

【Spring注解必知必会】深度解析@Component注解实现原理

概述 想必@Component注解大家一直在使用,只要类上加上它,就可以被Spring容器管理,那大家有想过它是怎么实现的吗?本篇文章就带领到家揭秘。 注解介绍 用来标记的类是一个“组件”或者说是一个Bean,Spring会自动扫描标记@Component注解的类作为一个Spring Bean对象。 注解源码: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Indexed public @interface Component { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any (or empty String otherwise) */ String value() default ""; } 复制代码 属性说明: value: 自定义当前组件或者说bean的名称,可以不配置, 不配置的话默认为组件的首字母小写的类名。 元注解说明: 该注解只能使用在类,接口、枚举、其他注解上该注解的生命周期是运行时JVM@Indexed元注解在spring 5.0引入,用于项目编译打包时,会在自动生成META-INF/spring.components文件,简历索引,从而提高组件扫描效率,减少应用启动时间。 注解使用 定义Person类,被@Component注解修饰 检查Person类是否在扫描路径下 获取bean验证 小结: 通过添加@Component能够将类转为Spring中的Bean对象,前提是能过够被扫描到。

gitlab+Jenkins自动化搭建部署

目录 部署环境 关闭selinux和防火墙 或者防火墙设置,开启gitlab和Jenkins要用的端口和http服务 安装依赖包 (Jenkins和gitlab都装) 一,开始Jenkins安装配置 1、Java包安装 2、安装Jenkins 3、启动Jenkins服务 4、修改jenkins配置文件 5、重启Jenkins服务 查看端口是否起来 6、打开网页界面 http://192.168.100.11:8080/ Jenkins正在配置启动中,比较慢 7、 选择插件来安装 8、选择“无”​编辑 9、创建管理员用户 10、选择安装插件路径Manage Jenkins—Manage Plugins—Plugin Manager—Advanced然后下拉到底 11、安装插件 12,生成公钥私钥对出来,命令:ssh-keygen 私钥id_rsa 公钥 id_rsa.pub 二,开始gitlab的部署 1、配置yum源地址 2、配置 hosts及改主机域名 3、启动postfix邮件服务 4、安装gitlab 5、加载初始化命令执行 6、启动gitlab服务 7、登录gitlab 网页 http://192.168.100.12/ 账号密码为 8、更改为中文页面 ​9、修改初始化密码 10、创建新的项目 11、选择上传一个文件 12、项目建成功上传 13、 然后就是配合Jenkins部署这个项目 在Jenkins生成的ssh-keygen 14,在Jenkins配置凭据 也可以配置一个ssh秘钥的模式。如下 key 是私钥id_rsa 开始生成的 15,添加JDK,Git,Maven,路径 查询JDK,Git,Maven,路径 三,新建项目 1、添加个项目描述,选择git构建 2、源码管理URL地址添加 3、打开Jenkins服务器,添加gitlab的ip域名解析配置 4、项目构建完成 四,项目构建成功 1、变绿色对号代表构建成功 2、查看详细构建 控制台输出 3,然后我们的项目构建成功在Jenkins的/var/lib/jenkins/workspace/demo路径,查看下 已经有demo项目了 部署环境 Centos7版本CentOS Linux release 7.

使用MATLAB对于Excel表格进行处理

在数学建模中,常常需要对于Excel表格中的数据进行处理,下面利用MATLAB编程语言对于Excel表格进行处理,其中最主要的操作包括读取和写入操作。 目录 1. 读取操作 2. 写入操作 1. 读取操作 使用MATLAB对于Excel表格中的数据进行读取操作如下所示: xlsread('文件名','sheet_name','起始位置:结束位置'); 例如读取如下图所示的Excel表格: 对进行该表格的数据进行读取并显示,代码如下所示: x=xlsread('D:\data.xlsx','sheet1','A1:C20'); x 执行后的结果如下所示: 可以看出使用MATLAB的xlsread函数可以实现对于Excel文件数据的读取操作。 2. 写入操作 对于表格进行写入操作同样也是对于数据处理的重要部分,对于表格中的数据进行写入操作的格式如下所示: xlswrite('文件名',写入的数据,'sheet_name','起始位置'); 例如,将原来读取的数据乘上2在重新写入到另一个文件中,代码如下: x=x.*2; xlswrite('D:\Data\data.xlsx',x,'sheet1','A4'); 执行后的效果如下所示: 除此之外,还有其他的写入方法。例如,MATLAB中的table和twritetable函数,在MATLAB中,table函数的作用是用来创建一个表格,writetable的作用是将表写入到文件中。MATLAB中可以使用这两个函数对于Excel表格进行写入操作。 例如,将原来的数据利用table函数和tablewrite函数写入到另一个表格中,代码如下所示: table1=table(x); writetable(table1,'D:\Data\data1.xlsx'); 效果图如下所示:

VisionPro与C# 实时取像

VisionPro 在C#项目程序中实现实时取像方式,有两种: 1.在界面中添加CogAcqFifoTool控件,程序上对控件属性赋值,最终运行起来与在VisionPro软件中操作一致; 2.在界面中添加 CogRecordDisplay 控件,通过程序实现相机连接,实时取像并显示到CogRecordDisplay 控件上。 输入显示控件名称,相机编号,示例代码如下: using System.Windows.Forms; using Cognex.VisionPro; using Cognex.VisionPro.ToolBlock; public CogFrameGrabbers mFrameGraber; public ICogAcqFifo mCogAcqFifo = null; /// <summary> /// 实时显示 /// </summary> /// <param name="cogDisplay">显示控件</param> /// <param name="cameraN">相机编号</param> public void VisionLive(CogRecordDisplay cogDisplay, int cameraN) { try { if (cogDisplay.LiveDisplayRunning) { //关闭光源 cogDisplay.StopLiveDisplay(); } else { mFrameGraber = new Cognex.VisionPro.CogFrameGrabbers(); int CameraCounts = 1;//设置项目相机数量 if (mFrameGraber.Count < CameraCounts) { //throw new Exception("Failed to create the CogFrameGrabbers object.

golang学习笔记(9)-gorm原生sql

gorm使用原生sql功能 目录 gorm使用原生sql功能准备工作原生查询 SQL 和 Scan命名参数Row & Rows 准备工作 建立数据库连接 import ( "fmt" _ "github.com/go-sql-driver/mysql" "gorm.io/driver/mysql" "gorm.io/gorm" "log" ) var db *gorm.DB func OpenDB() { dsn := "root:adss123@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True&loc=Local" res, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) db = res if err != nil { log.Fatal(err) } fmt.Printf("成功:%v\n", db) } 建立模型 type TestTb2 struct { Username string Password string TestTb2User1ID uint gorm.Model } 数据表预存数据 原生查询 SQL 和 Scan raw原生语句 type Result struct { ID int Name string Age int } var result Result db.

java基础|file类的创建、相对路径的三种写法【建议收藏】

java中常用的工具类就包括file类,使java语句能够通过idea等编译器和电脑中的文件发生联系。本篇文章就简要介绍常用的文件工具。 一、file类 这是属于java.io.File的类。如果要看详细的API介绍,可以移步这个文章API在oracle中的查询步骤 1、创建file对象 File file=new File("c:\\Guqi"); 2、判断是文件还是目录 file1.isDirectory(); file1.isFile() 返回布尔值 【只能在文件存在的时候,进行判断。如果不存在,就只会返回false】 3、创建目录 File file2=new File("c:\\Guqi\\set\\myfile"); if(!file2.exists(){ file2.mkdirs(); } mkdirs是创建多级目录。没有s后缀,只能创建一级。 4、创建文件【可以不写后缀,创建个普通文件。】 if(!file1.exists()){ file1.createNewFile(Guqi.txt); } 二、相对路径和绝对路径 绝对路径就是从盘开始写,直到文件的那级 "c:\\Guqi\\set\\myfile" 而相对路径则是指将当前文件作为参考对象,然后来找目标文件。 相对路径只有三种情况 1、和当前目录属于同一级 直接写文件名称 File file1=new File("小顾日记.txt"); 【由于idea中的java文件比较特殊,是以src这个文件夹为主位置,而不是编写的java文件所存储的位置。 可以通过创建新文件来查看 File file1=new File("小顾日记.txt"); try { file1.createNewFile(); } catch (IOException e) { e.printStackTrace(); } 如果想要直接以java文件为参考位置的话,需要通过cmd来操作。】 2、当前文件的子文件夹 通过\连接 File file3=new File("src\\com"); System.out.println(file3.exists()); 3、上级文件夹 通过…\ 比如 File file3=new File("..\\测试\\1.txt"); System.out.println(file3.exists()); “C:\Guqi\set\测试\1.txt” C:\Guqi\set\inputAndout\src 这表示的是先跳转回上一级目录,再进入到测试这个文件夹,选中1.txt文件。 温馨提示💓 如果在运用时遇到问题,可以直接关注并私信我,发送报错问题,我看到后会第一时间回复~

nuxt.js服务端渲染项目性能优化总结

众所周知,Vue作为前端开发的三大框架扛把子之一,在国内众多小微厂使用还是很多的,都知道Vue一般作为客户端渲染模式,在某些业务场景可能十分不友好,比如电商业务;为啥说不友好呢,因为Vue一般是使用客户端渲染,数据都是通过Ajax请求回来的,搜索引擎无法抓取到动态的内容,所以要用到服务端渲染,服务端有多种实现方式,Vue官方也自带SSR解决方案,Vue服务端渲染 由于项目前端使用的是Nuxt实现的SSR,在其中也踩了不少坑,做过几轮性能优化,下面通过实际项目经验总结一下: 从项目基础配置方面 页面布局结构化,例如:footer,header,main等解构语义标签的应用 <!--default.vue--> <header> <!--网站公用头部--> </header> <main> <!--网站试图渲染--> <Nuxt /> </main> <footer> <!--网站公用底部--> </footer> 使用Webpack这个工具进行合理的文件拆包,Webpack用好之后十分强大,最后项目文件编译之后包文件大小是固定的,如果拆包粒度过小,导致并发请求多,每个请求中TTFB里等待时间较长,如果拆包粒度过大,导致下载时间较长,需要不断调试,寻找适合项目的平衡点;Webpack拆包文档第三方包组件安装依赖按需引入加载,如果是协助辅助开发环境的npm包或辅助编译的包不要安装在生产环境,会被打包进包文件中,导致包文件过大;分析打包之后的文件包含的依赖,移除无用的plugins(如移动端的vconsole工具);一般脚手架都自带分析工具指令,如package.json下"build:ana": "nuxt build --analyze",运行npm run build:ana,会展示编译后包文件包含的大小,将不需要的资源移除;合理使用vue-lazy-hydration水合组件,合理使用客户端渲染,可有效防止页面偏移分数和LCP分数;合理使用CDN缓存,如脚本资源、图片等放CDN;合理引入加载第三方脚本,如livechat、 googleMap等脚本的初始化脚本,如非必要可使用滚屏加载初始化脚本或在需要使用的模块使用初始化脚本;图片大小优化,如单张占位图可压缩后使用大小缩小了5.5倍;压缩链接 除了项目基础配置能大幅提高项目测试评分外,还有很大一部分源于各位编程大佬的编码风格和程序稳定性,小厂一般都没啥规范,规范也不容易推行起来,下面我们从项目规范方便再讲一讲: 从项目编码规范方面 首页首屏加载移除无用的网络加载请求,看不到的地方使用滚屏加载(可以判断是否是爬虫),真正实现所看即所得,首页删除多余的相同功能的组件引入;项目组件引入懒加载,如初始状态组件不需要展示的组件可优先不渲染组件(v-if);项目中组件粒度的合理拆分和组件封装复用;项目编码删除冗余的嵌套HTML标签,融合可以减少的HTML嵌套标签,减少组件之间的嵌套层级,嵌套层级越深,DOM层级就越深;正确的使用HTML标签嵌套,p、h1~h5等标签含有语义,里面不可嵌套块级标签,尽可能不嵌套其他HTML标签;首页banner使用原生HTML标签使用背景图占位,可加快FCP和LCP的速度,Element-UI 的bannerUI组件解析渲染速度相对较慢; <!--index.vue--> <div style="150px" v-if="!bannerList.length"> <!--使用CSS背景占位,加快首屏渲染和最大页面元素渲染--> <div> <el-carousel height="150px" v-else> <el-carousel-item v-for="item in 4" :key="item"> <h3 class="small">{{ item }}</h3> </el-carousel-item> </el-carousel> <!--to do ...--> <script> // ... data() { return { bannerList: [] // 通过ajax拿到数据赋值 } } </script> 服务端asyncData使用安全的解构语法(let { data } = res || {};)解构服务端数据,服务端数据解构异常报错不会体现在浏览器上,出现问题十分难排查;合理使用公共方法,将页面中大量的逻辑判断条件抽离成函数或计算属性; 附上相关链接:

关于解构赋值的修改

可以看到从aa对象中结构出来的a和aa对象中的a不是同一个,在结构赋值过程中重新给a开辟空间,所以修改a并不会影响aa对象

java String 最长长度和占用内存大小

一 序 String在内存中的最大长度理论上是int型变量的最大值,Integer.MAX_VALUE, String的字面常量的最大长度为CONSTANT_Utf8_info表决定,一般为65535. 二 介绍 1、String的内部实现 通过一个字符数组来维护字符序列,其声名如下: private final char value[]; 2 所以,String的最大长度取决于字符数组的最大长度,因为字符数组长度只能是byte,char,short,int而不能是long型,所以这也说明最大长度,另一方面,我们知道String类有一个方法,str.length() 它的返回值是int型变量,声明如下: public int length() 3 所以这也说明了最大长度的理论值,但在实际中,要比理论值小, public class mainClass { public static void main(String[] args) { // TODO Auto-generated method stub char[] value=new char[Integer.MAX_VALUE]; System.out.println(""); } } 这个错误是内存溢出错误,所以系统无法分配这么大的内存空间。 现在的问题是,计算机系统可以分配多大的内存呢? 三 分析源码 java.lang.String.java public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; java String类以char[]数组存储字符元素,因而,String类的最大长度实际上取决于char[]数组能够包含的数组长度。

使用 virtualBox 安装 ubuntu

1.在官网上下载virtualBox windows用户点击如下图开始下载: 2.下载好VirtualBox-6.1.34a-150636-Win.exe文件后运行,一直点击下一步完成安装 3.在ubuntu镜像站下载Ubuntu,如下图: 4.打开VirtualBox,开始新建: 点击下一步: 创建虚拟硬盘: 5.点击设置: 安装盘片: 点击上图圈出的按钮,选择安装虚拟盘,找到刚才下载的ubuntu-20.04.4-desktop-amd64.iso: 6.启动: 启动后出现如下界面: 选择 中文简体: 点击 安装ubuntu: (看不到 继续 按钮的,按住win+鼠标左键 ,或者alt+f7 来拖动安装界面) 点击现在安装: 点击继续: 选择一个时区: 设置账号: 点击继续开始安装,要等一段时间: 如果遇到如下问题: 重启这台虚拟电脑即可 共享文件夹的方法: 设置VirtualBox共享文件夹的方法_爱自然的李老师的博客-CSDN博客_virtualbox 共享文件夹

Linux中jsoncpp的编译使用

旧版jsoncpp编译 1、预备条件: JsonCPP类库http://sourceforge.net/projects/jsoncpp/?source=dlp SCONS编译器http://sourceforge.net/projects/scons/?source=dlp Pythonhttp://www.python.org/ JsonCPP类库需要Scons编译器来编译,而Scons需要Python安装了才能使用。具体安装步骤请参见文件夹下的ReadMe文件。 2、 安装scons: sudo apt-get install scons 解包jsoncpp: tar -zxf jsoncpp-src-0.5.0.tar.gz jsoncpp安装: 解包后进入其目录。输入以下命令: scons platform=linux-gcc 就会安装成功 3、 上述已经完成jsoncpp的编译,在解压目录jsoncpp-src-0.5.0/libs/linux-gcc-7/下可以看到生成了两个文件: libjson_linux-gcc-7_libmt.a libjson_linux-gcc-7_libmt.so 把.a 和.so 文件拷贝到/usrl/lib 目录下(参考了不同资料,说法并不统一,有的是拷贝到/lib下,有的则是/usr/local/lib),可以为了方便编译给它改个名字libjsoncpp.a 同样,将解包目录下的(jsoncpp-src-0.5.0)的include拷贝到/usr/lib下面。 sudo mv include/json/ /usr/include/ 代码测试: #include<json/json.h> #include<iostream> using namespace std; int main(int argc, char** argv) { Json::Value root; Json::FastWriter fast; root["ModuleType"]= Json::Value("你好"); root["ModuleCode"]= Json::Value("22"); root["ModuleDesc"]= Json::Value("33"); root["DateTime"]= Json::Value("44"); root["LogType"]= Json::Value("55"); cout<<fast.write(root)<<endl; return 0; } 编译的语句: huqin@ubuntu:~/bstr/json$ g++ main.cpp -o main -L/home/huqin/bstr/json/Deps/lib32/libjsoncpp.

linux文件结构浅析

linux文件结构 /bin:引导启动所需的命令或普通客户可能用的命令(可能在引导启动后) /sbin:系统管理员使用的管理程序,这 里存放的是系统管理员使用的管理程序。 /dev:设备特别文件。 /dev/console:系统控制台,也只是直接和系统连接的监视器。/dev/hd:ide硬盘驱动程序接口。如:/dev/hda指的是第一个硬 盘,had1则是指/dev/hda的第一个分区。如系统中有很多的的硬盘,则依次为/dev /hdb、/dev/hdc、. . . . . .;如有多个分区则依次为hda1、hda2 . . . . . .、/dev/sd:scsi磁盘驱动程序接口。如系统有scsi硬盘,就不会访问/dev/had, 而会访问/dev/sda。/dev/fd:软驱设备驱动程序。如:/dev/fd0指 系统的第一个软盘,也只是往往一般所说的a盘,/dev/fd1指第二个软盘,. . . . . .而/dev/fd1 h1440则表示访问驱动器1中的4.5高密盘。/dev/st:scsi磁带驱动器驱动程序。/dev/tty:提供虚拟控制台支持。如:/dev/tty1指 的是系统的第一个虚拟控制台,/dev/tty2则是系统的第二个虚拟控制台。/dev/pty:提供远程登陆伪终端支持。在进行telnet登录时就要用到/dev/pty设 备。/dev/ttys:电脑串行接口,对于dos来说只是“com1”口。/dev/cua:电脑串行接口,与调制解调器一起使用的设备。/dev/null:“黑洞”,全部写入该设备的消息都将泯灭。例如:当想要将屏幕 上的输出消息掩藏起来时,只要将输出消息输入到/dev/null中就可。 /etc:目录存放着各种系统配置文件,之中包括了客户消息文件/etc/passwd, 系统初始化文件/etc/rc等。linux正是靠这些文件才得以正常地运行。 参考文章 apt的源文件在 /etc/apt/sources.list。而apt安装的软件在/usr/bin, /usr/lib,/usr/share,/usr/share/man /lib:标准程序设计库,又 叫动态链接共享库。根文件系统上的程序所需的共享库,存放了根文件系统程序运行所需的共享文件。这些文件内含了可被超级多程序共享的代码,以避免每一个程序都包含有相同的子程序的副本,故应该使得可执行文件变得更小,节省空间。 /lib/modules目录包含系统核心可加载各种模块,尤其是那些在复原损坏的系统时重 新引导系统所需的模块(例如网络和文件系统驱动)。 /tmp:公用的临时文件存储 点。存放程序在运行时发生的消息和资料。但在引导启动后,运行的程序最好使用/var/tmp来 代替/tmp,因为前者可能坐拥一个更大的磁盘空间。 /boot:目录存放引导加载器(bootstrap loader)使用的文件 /root:系统管理员的主目录。 /usr:最超大的目录,要用 到的应用程序和文件几乎都在这种目录。全部程序安装在这里。/usr里 的全部文件往往一般来自linux发行版; /usr/x11r6:存放x window的目录。/usr/bin:众多的应用程序。研究了几乎全部客户命令,是系统的应用库。另一些命令在/bin或/usr/local/bin中。安装的程序地址,都在usr下/usr/sbin:超级客户的一些管理程序。/usr/doc:linux文档。/usr/include:linux下研究和编译应用程序所需要的头文件。内含了c语言的头文件,这些文件多以.h结尾,用来描述c 语言程序中用到的资料结构、子过程和常量。为了坚持一致性,这实际上大概放在/usr/lib下,但习惯上一直沿用了这 个名字。/usr/lib:常用的动态链接库和应用包的配置文件。内含了程序或子系统的不变的资料文件,包括一些site – wide配置文件。名字lib来源于库(library); 编程的原始库也存在/usr/lib 里。当编译程序时,程序便会和之中的库进行连接。也有超级多程序把配置文件存入之中。opencv的安装目录就是这/usr/man:帮助文档。/usr/src:源代码,linux内核的源代码就放在/usr/src/linux 里。/usr/local:本地安装的程序和很多的东西在/usr/local下,因为这样应该在升级进化新版系 统或新发行版时无须从头开始安装全部程序。这里主要存放那些手动安装的应用,即 不是通过“新立得”或apt-get安装的应用 。它和/usr目录有着相类似的目录结构 。让应用包管理器来管理/usr目录,而把自己定义设置的脚本(scripts)放到/usr/local目录下面。 /usr/local/bin:本地增加的命令。/usr/local/lib:本地增加的库根文件系统。 /usr/share:此目录都是一些共享信息,里的信息时跨平台的,最常被用到的就是/usr/share/man这个目录,/usr/share/doc:放置一些系统帮助文件的地方; /var:一般运行时要变化的资料。往往一般这些资料所在的目录的大小是要总是变化或扩充 的。原来/var目录中一些内容是在/usr中的,但为了坚持/usr目录的相对稳固,就把那些需要总是变化的目录放到/var中了。 /var/catman:包括了格式化过的帮助(man)页。帮助页的源文件往往一般存在 /usr/man/catman中;一些man页可能有预格式化的版本,存在/usr/man/cat中。而很多的的man页在第一次看时都需要格式化,格 式化完的版本存在/var/man中,这样很多的人再看相同的页时就无须等待格式化了。(/var/catman总是被 清除,就像清除临时目录一样。)/var/lib:存放系统正常运行时要变化的文件。/var/local:存放/usr/local中 安装的程序的可变资料(即系统管理员安装的程序)。小心,如果必须,即便本地安装的程序也会使用很多的/var目录,例如/var/lock 。/var/lock:锁定文件。超级多程序服从在/var/lock中 发生一个锁定文件的约定,以用来支持他们正在使用某个特殊的设备或文件。很多的程序小心到这种锁定文件时,就不会再使用这种设备或文件。/var/log:各种程序的日志(log)文件,尤其是login (/var/log/wtmplog纪 录全部到系统的登录和注销) 和syslog (/var/log/messages 纪录存储全部核心和系统程序消息)。/var/log 里的文件总是不确认地增长,大概定时清除。/var/run:保存在下一次系统引导前有效的关于系统的消息文件。例如,/var/run/utmp包 含目前登录的客户的消息。/var/spool:放置“假脱机(spool)”程序的目录,如mail、 news、打印队列和很多的队列事件的目录。每一个不一样的spool在/var/spool下有自己的子目录,例如,客户的邮箱就存放在/var/spool/mail 中。/var/tmp:比/tmp允许更大的或需要存在较很长时间的临时文件。小心系统管理 员可能不允许/var/tmp有很旧的文件。

微信小程序游戏开发│石头剪刀布游戏(附源码)

石头剪刀布游戏功能中一方是电脑,另一方是玩家。游戏时电脑一直快速切换出拳显示,当玩家选择底部的剪子、石头、布后,则电脑出拳停止,并在紫色方块中显示用户的出拳图片。游戏判断出输赢结果,记录玩家赢的次数。对战一局后可以单击“再来!”按钮重新一局。运行效果如图1所示。 (a)玩家出拳前 (b)玩家出拳后 ■ 图1 石头剪刀布游戏运行效果 01、程序设计的思路 1. 控制剪子、石头、布的快速切换 猜拳游戏的核心就是快速切换剪子、石头、布三个图像,电脑的出拳一直是动态切换的,一直到用户选择剪子、石头、布的图片后才停止。这里将这三个图像文件名存储在一个srcs数组中,并使用定时器快速从这个数组中依次循环获取图像文件名,并将该文件名指定的图像显示到image组件中即可。 data: { srcs: [ '/images/shitou.png', '/images/jiandao.png', '/images/bu.png', ] , imgAi: '', // 电脑随机显示的图片 imgUser: '/images/wenhao.png', // 用户选中的图片 }, //设置电脑每间隔0.2s随机显示石头剪刀布 timerGo() { timer = setInterval(this.change, 200); //200毫秒 }, //设置电脑随机显示石头剪刀布,0对应石头,1对应剪刀、2对应布 change() { this.setData({ imgAi: this.data.srcs[parseInt(Math.random() * 3)], }) }, 这里涉及到两个主要变量:srcs(图片数组)和imgAi(电脑出拳),这两个都定义在data对象中。 本游戏对石头、剪子、布进行编号,其中0对应石头,1对应剪刀、2对应布。所以电脑随机出拳就是产生0~2之间的随机自然数。 这里使用了Math中的parseInt()函数和Math中的random()函数,其中random()函数会产生0~1之间的小数,当Math.random() * 3时,random函数就会生成0~3之间的一个随机小数,然后通过parseInt()函数进行取整处理得到0~2之间的随机自然数。接着通过this.data.srcs[parseInt(Math.random()*3)]就完成了使电脑随机选择石头剪刀布中的一种情况。 2. 用户出拳 用户出拳比较简单,这里提供3个图像组件(image)供用户单击选择。对此3个图像组件分别绑定单击事件,单击事件获取并识别那个image图像组件,从而得知玩家用户的出拳。 02、程序设计的步骤 新建一个微信小程序后,在app.json中修改原有的"window"值,实现导航条标题文字为"石头剪刀布游戏",具体如下: "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "石头剪刀布游戏", "navigationBarTextStyle": "black" 1. 游戏布局 猜拳游戏的布局是纵向显示4个文本组件(text)、5个图像组件(image)和1个按钮组件(button)。在创建小程序工程时,默认建立了两个页面:index和logs。我们不需要管logs,在这个例子中只需修改和index页面相关的文件,index是小程序第一个显示的页面,其中index.

golang 学习笔记(8)-gorm实现删除功能

gorm实现删除功能 目录 gorm实现删除功能准备工作删除一条记录根据主键删除批量删除阻止全局删除软删除查找被软删除的记录永久删除删除标签 准备工作 建立数据库连接 import ( "fmt" _ "github.com/go-sql-driver/mysql" "gorm.io/driver/mysql" "gorm.io/gorm" "log" ) var db *gorm.DB func OpenDB() { dsn := "root:adss123@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True&loc=Local" res, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) db = res if err != nil { log.Fatal(err) } fmt.Printf("成功:%v\n", db) } 建立模型 type TestTb2 struct { Username string Password string TestTb2User1ID uint gorm.Model } 数据表预存数据 删除一条记录 删除一条记录时,删除对象需要指定主键,否则会触发 批量 Delete,例如: // Email 的 ID 是 `10` db.Delete(&email) // DELETE from emails where id = 10; // 带额外条件的删除 db.

计算机网络知识之交换机、路由器、网关、MAC地址

目录 1、交换机 1、交换机的概念 2、交换机的作用 3、交换机的工作原理 4、交换机的功能 5、交换机的应用 6、交换机的三种交换方式 1、直通式(Cut Through) 2、存储转发(store & Forward) 3、碎片隔离(Fragment Free) 7、交换机分类 2、 路由器(Windows下叫默认网关,网关就是路由,路由就是网关) 1、路由器的概述 2、路由器的作用功能 3、路由器的工作原理 3、网关 1、网关的概念 4、MAC地址 1、MAC地址的概述 2、查看MAC地址 1、交换机 1、交换机的概念 交换机(switch)是按照通信两端传输信息的需要,用人工或设备自动完成的方法,把要传输的信息送到符号要求的相应路由上的技术统称。广义的交换机switch就是一种通信系统中完成信息交换功能的设备。这个过程就是通过人工方式建立起来的交换。当然我们现在已经普及了程控交换机,交换的过程都是自动完成的。 交换机是一种在局域网中常用到的设备,它能实现相连计算机之间的高速数据交流。在同一时刻可以进行多个端口之间的数据传输。每一个端口都可以视为是独立的网段,连接在其他网络设备独自享有全部的带宽,无需同其他设备竞争使用。当节点A向节点D发送数据时,节点B可同时向节点C发送数据,而且这两个传输都享有网络的全部带宽,都有着自己的虚拟连接。 交换机是一种基于MAC地址识别,能完成封装转发数据包功能的网络设备。交换机可以“学习”MAC地址,并把其存放在内部地址表中,通过在数据帧的始发者和目标接收者之间建立临时的交换路径,使数据帧直接由源地址到达目的地址。 交换机可以分为: 2层交换机:只是交换功能。3层交换机:具有路由功能,可以当路由器使用LVS和nginx:4层负载均衡:传输层7层负载均衡:应用层 2、交换机的作用 本质意义上讲,交换是一个技术概念,即完成信号由设备入口到出口的转发。因此,只要是符合该定义的所有设备都可以被称为交换设备。“交换”是一个涵义广泛的词语,当它被用来描述数据网络第二层的设备时,实际指的是一个桥接设备,而当它被用来描述数据网络第三层的设备时,指的是一个路由设备。而以太网交换机实际是一个基于网桥技术的多端口第二层网络设备,它为数据帧从一个端口到另一个任意端口的转发提供了低时延、低开销的通路。 交换机的作用就是组建局域网。交换机内部核心处应该有一个交换矩阵,为任意两个端口之间的通信提供通路,或者是一个快速交换总线,以使由任意端口接收的数据帧从其他端送出。在实际的设备中,交换矩阵的功能往往是由专门的芯片(ASIC)完成的。 3、交换机的工作原理 交换机是工作在网络数据链路层,从物理划分网段的。 交换机的工作原理就是:先学习后转发。交换机里面含有mac地址表,mac地址表存放在内存中。 交换机的学习原理:学习源mac地址写到mac地址表里,mac地址表就会存入内存中,停电就会失效。mac地址表中存放的是:端口号、mac地址、vlan号(默认都为vlan1),mac地址表存入交换机中。交换机的转发原理:根据目的mac转发。如果目的mac地址在交换机的mac地址表里面没有,交换机就会复制帧给交换机的每个接口都转发一份(广播),来的那个接口不发。如果地址表里有目的mac地址(知道mac地址)就进行单播,不知道目的mac地址的时候会进行广播。目的mac地址全是FF的帧就叫广播地址,收到的mac地址全是F的就进行广播行为。 交换机的工作原理举例详细解说: 首先,交换机的工作原理可以分为两个特点:是先学习后转发。假设,一个交换机中连接了三台电脑,A电脑和B电脑进行连接通信,A电脑的mac地址是111,B电脑的是222,接下来,A电脑会把数据封装好,源mac地址填自己的,目的mac填222,接下来通过封装,封装到物理层,物理层通过网线送给交换机,交换机收到数据帧之后进行解封装,解封装的时候会先进行学习,先学习帧里面的源mac地址,然后看一下自己的mac地址表里面(交换机里面有个mac地址表)有没有源mac,如果没有就将源mac地址写到mac地址表里面去,并且知道它是哪个接口的(从哪里mac地址来对应哪个接口); 然后学习完之后再进行转发操作,然后看它的目的mac地址在mac地址表里面有没有,有的话直接转发到对应接口,没有的话进行广播,广播就是给交换机的每个接口都转发一份,来的那个接口不发,这样的话,所有的接在交换机上的电脑都会收到数据,收到数据的电脑在进行解封装的时候会看目的mac是不是自己的,如果目的mac是自己的,就会进行回复,如果不是自己的就不回复,直接扔掉;然后B电脑收到之后,它的mac地址就是222,就会给出回复,回复的时候会封装好,源mac也是222,目的mac是111,当这个数据包到达交换机的时候,交换机又会进行先学习,看源mac222在不在mac表里面,如果有就不学习,没有就写入mac表中去。 交换机与交换机之间需要接一根线:防止形成环路。 防范形成环路:物理上检查不要形成环路;交换机的系统启用STP协议。 4、交换机的功能 交换机的主要功能是:物理编址、网络拓扑结构、错误校验、帧序列以及流程、VLAN(虚拟局域网)、链路汇聚、防火墙。 交换机除了能够连接同种类型的网络之外,还可以在不同类型的网络(如以太网和快速以太网)之间起到互连作用。一般来说,交换机的每个端口都用来连接一个独立的网段、但是有时为了提供更快的接入速度,我们可以把一些重要的网络计算机直接连接到交换机的端口上。这样,网络的关键服务器和重要用户就可以拥有更快的接入速度,支持更大的信息流量。 5、交换机的应用 作为局域网的主要连接设备,以太网交换机成为应用普及最快的网络设备之一。随着交换技术的不断发展,以太网交换机的价格急剧下降,交换到桌面已是大势所趋。 如果你的以太网上拥有大量的用户、繁忙的应用程序和各式各样的服务器,而且你还没有对网络结构做出任何调整,那么整个网络的性能可能会非常低。解决办法之一就是在以太网上添加一个10/100Mbps的交换机,它不仅可以处理10Mbps的常规以太网数据流,而且还可以支持100Mbps的快速以太网连接。 如果网络的利用率超过了40%,并且碰撞率大于10%,交换机可以帮你解决一点问题。带有100Mbps快速以太网和10Mbps以太网端口的交换机可以全双工方式运行,可以建立起专用的20Mbps到200Mbps连接。 在不同网络环境下交换机的作用各不相同,在同一网络环境下添加新的交换机和增加现有的交换端口对网络的影响也不相同,使用交换机的目的就是尽可能的减少和过滤网络中的数据流量。所以如果网络中的某台交换机由于安装位置设置不当,几乎需要转发接收到的所有数据包的话,交换机就无法发挥它优化网络性能的作用,反而会降低了数据的传输速度,增加网络延迟。 6、交换机的三种交换方式 1、直通式(Cut Through) 直通的方式的以太网可以理解为在各端口之间是纵横交叉的线路矩阵电话交换机。它在输入端口检测到一个数据包时,检查该包的包头,获取包的目的地址,启动内部的动态查找表转换成相应的输出端口,在输入与输出交叉处连通,把数据包直通到相应的端口,实现交换的功能。优点是:不需要存储,延迟非常小、交换非常快。缺点是:因为数据包内容并没有被以太网交换机保存下来,所以无法检查所传送的数据包是否有误,不能提供错误检测能力。由于没有缓存,不能将具有不同速率的输入、输出端口直接连通,而且容易丢包。 2、存储转发(store & Forward) 存储转发方式是计算机网络领域应用最为广泛的方式。它把输入端口的数据包先存储起来,然后进行CRC(循环冗余码校验)检查,在对错误包处理后才取出数据包的目的地址,通常查找表转换成输出端口送出包。所以就会存在存储转发方式在数据处理时延大的缺点,优点就是它可以对进入交换机的数据包进行错误检测,有效地改善网络性能。最重要的是它可以支持不同速度的端口间的转换,保持高速端口与低速端口中间的协调工作。 3、碎片隔离(Fragment Free) 这是介于前两者之间的一种解决方案,它检查数据包的长度是否够64个字节,如果小于64个字节,那就说明这是个假包,则丢弃该包;如果大于64个字节,则发送该包。这种方式也不提供数据校验。它的数据处理速度比存储转发方式快,但是比直通式慢。 7、交换机分类 从广义上来看,交换机分为两种:广域网交换机和局域网交换机。广域网交换机主要应用与电信领域,提供通信信用的基础平台。而局域网交换机则是应用于局域网络,用于连接终端设备,如PC机及网络打印机等。 从传输介质和传输速度上可以分为以太网交换机、快速以太网交换机、前兆以太网交换机、FDDI交换机、ATM交换机和令牌环交换机等。 从规模应用上又可以分为企业级交换机、部门级交换机和工作组交换机等。 2、 路由器(Windows下叫默认网关,网关就是路由,路由就是网关) 1、路由器的概述 路由:router:跨越从源主机到目标主机的一个互联网络来转发数据包的过程。路由器是连接两个或多个网络的硬件设备,在网络间起着网关的作用,是读取每一个数据包中的地址然后决定如何传送的专用智能性的网络设备。它能够理解不同的协议,例如某个局域网使用的以太网协议,因特网使用的TCP/IP协议,这样的路由器可以分析各种不同类型网络传来的数据包的目的地址,把非TCP/IP网络的地址转换成TCP/IP地址,或者就相反的,再根据选定的路由算法把各个数据包按照最佳的路线传送到指定位置。所以路由器可以把非TCP/IP网络连接到因特网上。

Maven pom.xml <packaging>pom</packaging> 引发的问题

文章目录 Maven pom.xml pom 引发的问题 Maven pom.xml pom 引发的问题 有一个项目在别人那运行的非常好;有一天, 我开开心心的把这个项目作为一个新 module 导入到了当前的工程中;然后启动项目, 发现启动端口和我指定的没有任何关联;我以为出了啥奇怪问题, 于是我重启了一下; 然而, 并没有任何改变;难道是默认的 profile 没生效, 我在idea Program arguments 里指定了 --spring.profiles.actove=dev;日志输出显示当前激活的profile 是dev了, 但是端口依然是默认的8080, 和我指定的没有任何关联;再次我在 VM options 指定 -Dspring.profiles.actove=dev, 然而端口依然是默认的8080, 和我指定的没有任何关联;我注意到 target 下没有我的配置文件: 下意识里我想到了pom.xml 里的一些配置: <build> ... <resources> <resource> <directory>src/main/resources</directory> <includes> <include>*.yml</include> <include>**/*.yml</include> </includes> <!-- <excludes> <exclude>**/*.properties</exclude> <exclude>**/*.yml</exclude> <exclude>*.properties</exclude> <exclude>*.conf</exclude> <exclude>*.yml</exclude> <exclude>generator/*.*</exclude> </excludes> --> </resource> </resources> ... </build> 这些配置加上后, maven 刷新, 重启项目, 问题依旧存在;我注意到右侧, Maven Project -> Plugins 里边少了 resources 这个插件正是往编译目录下复制配置文件的, 没有它, 上边的配置加了=没加; 所以我以为是项目导入的问题;于是我把 idea 中的这个Module 删了, .

Spring Boot 中通过 TaskExecutor 来实现异步任务

简介 Spring 通过任务执行器(TaskExecutor)来实现多线程和并发编程。使用 ThreadPoolTaskExecutor 可实现一个基于线程池的 TaskExecutor。而实际开发中任务一般是非阻碍的,即异步的,所以我们要在配置类中通过 @EnableAsync 开启对异步任务的支持,并通过在实际执行的 Bean 的方法中使用 @Async 注解来声明其是一个异步任务。 代码示例 配置类 在配置类中,利用 @EnableAsync 注解,开启对异步任务支持。配置类实现 AsyncConfigurer 接口,并重写 getAsyncExecutor() 方法,返回一个 ThreadPoolTaskExecutor,这样子我们就获得了一个基于线程池的 TaskExecutor 。 import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; @Configuration // 声明是一个配置类 @EnableAsync //开启异步的支持 public class TaskExecutorConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { //配置类实现 AsyncConfigurer 接口,重写 getAsyncExecutor, 通过配置返回一个 taskExecutor 线程池 ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.initialize(); return taskExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; } } 注意:上面的例子中,ThreadPoolTaskExecutor 并没有被 Spring 容器管理,可以在getAsyncExecutor()上添加 @Bean 注解让它变成 Spring 管理的 Bean。如果加入到 Spring容器,那么就不需要手动调用 executor.

Redis 实现分布式缓存

缓存 1. 什么是缓存? 缓存就是数据交换的缓冲区,用于临时存储数据(使用频繁的数据)。当用户请求数据时,首先在缓存中寻找,如果找到了则直接返回。如果找不到,则去数据库中查找 缓存的本质就是用空间换时间,牺牲数据的实时性,从而减轻数据库压力,尽可能提高吞吐量,有效提升响应速度 2. 缓存的分类 缓存的应用范围十分广泛,常见的有文件缓存、浏览器缓存、数据库缓存等等,但我们今天着重关注的是 WEB 应用服务领域,根据缓存与应用的耦合度,可以分为本地缓存和分布式缓存: 本地缓存 指在应用中的缓存组件,最大的优点是应用和缓存是在同一个进程内部,请求缓存速度快;同时,它的缺点也是因为缓存跟应用程序耦合,多个应用程序无法直接共享缓存,各应用或集群的各节点都需要维护自己的单独缓存 分布式缓存 指的是与应用分离的缓存组件或服务,最大的优点是自身就是一个独立的应用,与本地应用隔离,多个应用可直接共享缓存 3. 缓存的特点 缓存也是一个数据模型对象,那么必然有它的一些特征: 命中率 命中率 = 返回正确结果数 / 请求缓存次数,命中率是衡量缓存有效性的重要指标,命中率越高,表明缓存的使用率越高 最大元素 缓存中可以存放的最大元素的数量,一旦缓存中元素数量超过这个值,将会触发缓存清空策略。根据不同的场景合理设置最大元素值,可以在一定程度上提高缓存的命中率,从而更有效的利用缓存 4. 缓存清空策略 缓存的存储空间有限制,当缓存空间被用满时,就需要缓存清空策略来处理,常见的一般策略有: 先进先出策略:先进入缓存的数据,在缓存空间不足时会被优先被清理掉,在数据实效性要求较高的场景下,可选择该策略 最少使用策略:无论是否过期,根据元素被使用的次数判断,清除使用次数较少的元素。最少使用策略主要比较元素的命中次数,在保证高频数据有效性场景下,可选择该策略 最近最少使用策略:无论是否过期,根据元素最后一次被使用的时间戳,清除最远使用时间戳的元素。策略算法主要比较元素最近一次被使用的时间,适用于热点数据场景 此外,还有一些简单策略,比如: 根据过期时间判断,清理过期时间最长的元素根据过期时间判断,清理最近要过期的元素随机清理根据关键字(或元素内容)清理等等 Redis 实现分布式缓存 可以利用 Mybatis 自带的本地缓存,结合 Redis 实现分布式缓存,主要思路是将 Mybatis 二级缓存的存放地点从本地改为配置了 Redis 的远程服务器 1. 开启 mybatis 二级缓存 创建一个 SpringBoot 工程,整合 MyBatis 和 Redis,在 Mapper 文件中加入 <cache/> 标签开启二级缓存 <cache/> 标签默认采用 PrepetualCache,该类是 Cache 接口的实现类,维护一个 Map 来保存数据 2. 自定义 cache 实现 我们要作改造,就要自定义一个实现类并替换 <cache type="

Python下unittest框架的核心组件使用

前言:在接口/UI自动化中,unittest框架或多或少也听到过,流行的框架我们需要重点去学习及掌握,接下来就一起来学习下吧 一、unittest核心组件 1、TestCase:测试用例类,用来定义测试用例函数的 2、TestSuite:测试套件,用来收集测试用例的 3、TestRunner:测试用例运行类,用来执行测试用例的,以测试套件维度去执行 4、TestFixture:测试脚手架,前置条件,后置处理 二、测试流程--unittest你是如何做自动化测试的 1、TestCase:先定义测试用例类,在测试用例类中写测试方法 2、TestSuite:收集你要执行的测试用例类或者文件里面的测试方法,放到测试套件 3、TestRunner:将收集好的测试条件放到测试用例运行器去执行,并收集测试结果 4、TestFixture:做好前置条件和后置处理 三、如何写测试用例(TestCase) 1、导入模块:import unittest,继承TestCase类 2、定义一个测试用例类:类名称必须Test开头 3、定义测试方法:测试方法也必须是test开头,必须写在测试用例类里面 4、框架执行入口:unittest.main(),自动收集当前py文件的测试用例,然后执行 四、测试用例包含哪些东西 1、前置条件(如果没有可以不写):sql语句执行、数据库连接创建、工具类的实例化 2、测试步骤(业务逻辑):数据替换、数据驱动 3、测试结果断言:响应结果断言、数据库数据断言 4、后置处理(如果没有可以不写):数据清理、数据库连接关闭 五、前置后置(TestFixture) 自动化中什么是前置后置? 答:前置:sql语句执行、数据库连接创建、工具类的实例化 后置:数据清理、数据库连接关闭 a) 类级别(以类级别的运行) 一、类级别(以类级别的运行) 前置:测试用例执行之前执行一次(当前测试用例类) —— @classmethod def setUpClass(cls) -> None:(固定写法,必须加@classmethod,源码就是加了) 后置:测试用例执行之后执行一次(当前测试用例类)—— @classmethod def tearDownClass(cls) -> None: (固定写法,必须加@classmethod,源码就是加了) 解释: 类级别的前后置就是,比如你的测试用例有3条,那就每一条用例都会去执行前后置, 执行顺序:前置,第一条用例,第二条用例,后置 a) 示例:类级别 #例子: class Test_class_setup(unittest.TestCase): #前置后置都需要类继承unittest.TestCase @classmethod #类级别的前置 必须加@classmethod def setUpClass(cls) -> None: print("我是类级别的前置") @classmethod def tearDownClass(cls) -> None: #类级别的后置 必须加@classmethod 这里后置放哪里都可以 你也可以放到最后一条用例后面去。 print("

【win11】shell…{52205fd8-5dfb-447d-801a-d0b52f2e83e1}

文件资源管理器无法打开 快捷方式无效弹出: 修改注册表都不行: shell…{52205fd8-5dfb-447d-801a-d0b52f2e83e1} 修改注册表 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Folder\shell\explore\command] @="%SystemRoot%\\Explorer.exe" "DelegateExecute"="{11dbb47c-a525-400b-9e80-a54615a090c0}" 还是不行 ** ** 这个也不行 Windows Registry Editor Version 5.00 ; HKCR\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1} [HKEY_CLASSES_ROOT\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}] @=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,\ 00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,\ 68,00,65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,32,\ 00,32,00,30,00,36,00,37,00,00,00 [HKEY_CLASSES_ROOT\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\InProcServer32] @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ 00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,68,00,\ 65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,00,00 "ThreadingModel"="Apartment" [HKEY_CLASSES_ROOT\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\open\command] "DelegateExecute"="{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" [HKEY_CLASSES_ROOT\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\OpenNewWindow\command] "DelegateExecute"="{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" ; HKCR\Wow6432Node\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1} [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}] @=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,\ 00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,\ 68,00,65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,32,\ 00,32,00,30,00,36,00,37,00,00,00 [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\InProcServer32] @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ 00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,68,00,\ 65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,00,00 "ThreadingModel"="Apartment" [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\open\command] "DelegateExecute"="{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\OpenNewWindow\command] "DelegateExecute"="{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" ; HKLM\SOFTWARE\Classes\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1} [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}] @=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,\ 00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,\ 68,00,65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,32,\ 00,32,00,30,00,36,00,37,00,00,00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\InProcServer32] @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\ 00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,00,68,00,\ 65,00,6c,00,6c,00,33,00,32,00,2e,00,64,00,6c,00,6c,00,00,00 "ThreadingModel"="Apartment" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\open\command] "DelegateExecute"="{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{52205fd8-5dfb-447d-801a-d0b52f2e83e1}\shell\OpenNewWindow\command] "

Web自动化成长之路:selenium中的PO模式

前言:在UI自动化中,设计的核心思路就是PO模式,PO模式是什么是什么呢?接下来就一起 来认识下吧 一、自动化测试优化流程 a)启动浏览器后,条件反射加一个隐性等待 b)最大化窗口 c)怎么提高代码可维护性 PO模式是什么? 页面url优化成类属性 尽量让方法的返回值返回衣蛾PageObject对象,可以是self,也可以是其他的页面对象 为什么返回po对象?方便链式调用 PO模式的好处? 在 ui 测试当中,必须要使用 PO 模式吗? 答:不一定,为了可读性、可扩展性、可复用、可维护 什么是 PO 模式? 答:就是把浏览器当中的某个页面(特征、操作)转成代码(对象)(属性和方法) PO 模式的本质是什么? 就是对编写的代码的一种封装形式

Docker镜像制作

Docker镜像制作 1 Docker中的镜像分层1.1 Docker 镜像为什么分层1.2 可写的容器层1.3 容器层的细节说明 2 制作镜像2.1 镜像的生成途径2.2 基于容器制作2.2.1 使用 commit2.2.1.2 示例一2.2.1.2 示例二 2.2.2 使用 export 和 import2.2.2.1 导出(容器转变为镜像文件)2.2.2.2 导入(镜像文件转变为镜像) 2.2.3 使用 save 和 load2.2.3.1 保存(镜像转变为镜像文件)2.2.3.1.1 演示一(保存单镜像)2.2.3.1.1 演示一(保存多镜像) 2.2.3.2 加载(镜像文件转变为镜像) 2.2.4 两种方案的差别 1 Docker中的镜像分层 Docker 支持通过扩展现有镜像创建新的镜像。DockerHub 中 99% 的镜像都是通过在base镜像的基础上安装和配置需要的软件所构建出来的。 1.1 Docker 镜像为什么分层 镜像分层最大的一个好处就是共享资源。 多个镜像均以同一个 base 镜像为基础构建而来,而Docker Host 只需在磁盘上保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了,且镜像的每一层都可以被共享。 如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内,这就是容器 Copy-on-Write 特性。 1.2 可写的容器层 当容器启动时,一个新的可写层被加载到镜像的顶部,这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。 所有对容器的改动,无论添加、删除还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。 1.3 容器层的细节说明 镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如/a,上层的/a会覆盖下层的/a,也就是说用户只能访问到上层中的文件/a。在容器层中,用户看到的是一个叠加之后的文件系统。 只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。

Jenkins+Docker 一键自动化部署 SpringBoot 项目

点击关注公众号,实用技术文章及时了解 本文章实现最简单全面的Jenkins+docker+springboot 一键自动部署项目,步骤齐全,少走坑路。 环境:centos7+git(gitee) 简述实现步骤:在docker安装jenkins,配置jenkins基本信息,利用Dockerfile和shell脚本实现项目自动拉取打包并运行。 一、安装docker docker安装社区版本CE 1.确保 yum 包更新到最新。 yum update 2.卸载旧版本(如果安装过旧版本的话) yum remove docker docker-common docker-selinux docker-engine 3.安装需要的软件包 yum install -y yum-utils device-mapper-persistent-data lvm2 4.设置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 5.安装docker yum install docker-ce #由于repo中默认只开启stable仓库,故这里安装的是最新稳定版17.12.0 yum install <自己的版本> # 例如:sudo yum install docker-ce-17.12.0.ce 6.启动和开机启动 systemctl start docker systemctl enable docker 7.验证安装是否成功 docker version 二、安装Jenkins Jenkins中文官网: https://www.jenkins.io/zh/ 1.安装Jenkins docker 安装一切都是那么简单,注意检查8080是否已经占用!如果占用修改端口 docker run --name jenkins -u root --rm -d -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.

android开发之UI

这是一篇关于android开发的UI部分的笔记,其中包括布局,布局中常用的单位以及一个计算器UI的小例子。这里所用到的开发工具是Android4.1。 目录 一、线性布局 1.1.通过大标签LinearLayout来实现线性布局。 1.2.线性布局的摆放方向 1.3.线性布局中的权重 二、相对布局 2.1.相对布局相对于父控件对齐: 2.2.相对布局相对于同级控件: 三、其他布局 3.1绝对布局AbsoluteLayout 3.2表格布局 3.3帧布局 四、布局中常用的单位 4.1像素单位px 4.2适配的单位dp 4.3字体单位sp 4.4wrap_content和match_parent 五、编写计算机UI例子 5.1思路 5.2设置边框和背景颜色 一、线性布局 1.1.通过大标签LinearLayout来实现线性布局。 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> ​ <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> ​ </androidx.constraintlayout.widget.ConstraintLayout> 1.2.线性布局的摆放方向 我们可以通过orientation这个属性来修改LinearLayout.布局的孩子摆放方向,它的值有两个:一个是vertical(水平线性布局),另一个是horizontal(垂直线性布局). 1.3.线性布局中的权重 当有些时候我们需要平均的给孩子高度或宽度,这个时候我们就可以用权重。有时候不平均,但点的宽/高成比例,我们也可以用权重解决。 这个是平均分配宽度的方法,每个占宽度为0,权重占的都是1,也就是占1/N代码如下: <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:layout_editor_absoluteX="61dp" tools:layout_editor_absoluteY="0dp"> ​ <Button android:id="@+id/button14" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button" /> ​ <Button android:id="@+id/button15" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button" /> ​ <Button android:id="

Android解决设备ID获取异常 java.lang.SecurityException: getDeviceId: The user 10612 does not meet the require

问题还原 今天搭建一个新的项目采用了compileSdkVersion 为29的开发版本,同时也targetSdkVersion调整为29,在调用设备ID时发生闪退的异常,查看日志如下: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.smart.artifact.sdk/com.smart.artifact.sdk.MainActivity}: java.lang.SecurityException: getDeviceId: The user 10612 does not meet the requirements to access device identifiers. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3457) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7562) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) Caused by: java.lang.SecurityException: getDeviceId: The user 10612 does not meet the requirements to access device identifiers. at android.os.Parcel.createException(Parcel.java:2074) at android.os.Parcel.readException(Parcel.java:2042) at android.

关于python爬虫的ua设置

无论使用requests还是httpx其实不设置ua也是可以跑的,只不过跑的时候是默认的ua,但是对于一些设置了防火墙或者有防御性质的cdn来说,默认的ua是肯定进不去的。所以我们今天来聊聊关于爬虫的ua的设置问题。 ua全名是user-agent,其实就是我们常说的协议头。 比如百度spider的ua就是:Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) 常见的浏览器ua是:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 常规来说如果我们爬虫不是很频繁,那我们可以将ua设置成固定的常见浏览器ua就可以避过站长的巡查,但是如果频繁,站长可能为了保证服务器正常运行,还是有可能将我们的ip和ua禁掉的。 ip被禁我们就不聊了,可以直接用代理解决,但是ua怎么办? 推荐个库faker,这个库其实就是个协议头合集,我们通过设置可以每次变换一个ua,这样配合代理就不可能将我们所有的爬虫都封掉了。 代码如下: from faker import Faker uas = Faker() ua=uas.user_agent() ua=uas.user_agent()为获取随机ua的代码,将这行放到get请求前,然后替换headers中的ua就好。 演示代码: import requests from faker import Faker uas = Faker() links = ['','',''] for url in links: ua=uas.user_agent() headers = {'user-agent': ua} res=requests.get(url,headers=headers,proxies=proxies) r=res.text 这样就可以实现每次请求ip和ua都不同,从而避免被封的问题

stm32如何用串口发送一个字符串

一、配置时钟,GPIO的时钟,串口的时钟,还有复位时钟 二、结构体配置GPIOA_9,GPIOA_10,TX和RX 三、结构体配置串口 四、串口的发送 PS:整段程序

Keil提高效率的插件之Astyle

一、Artistic Style(Astyle) 下载地址:Astyle 使用方法 将下载好的Astyle.exe文件添加到keil -> Tools -> customize Tools Menu命名,可以取中文名 然后在command中添加下载好的Aatyle.exe文件路径 最后在Argument中添加插件想要用到的配置参数, !E 是必须要有的,其他符号可按需在后面依次添加(,其他符号在第二部分着重介绍,且符号之间没有先后顺序之分)。 完成上述步骤后,就可在Tools工具栏下,看到已添加好的Astyle插件,需要时,点一下即可 二、常用符号 注意:每个助记符前后都必须有空格,严格区分大小写。例如:上图中的 !E -p -s4 -P(-是连接符,不是下划线) -p : 在运算操作符两边插入空格(使用效果见下图) -s4:一个Tab缩进4个空格(默认),数字代表空格个数 -P :在括号两边插入空格。 -d只在括号外面插入空格 -D只在里面插入 -S: 表示switch中case语句的缩进。 -N: 表示命名空间namespace内的缩进; -U: 表示括号内的两头的參数和括号之间不留空格; -H: 表示”if”、”for”、”while”等keyword右边添加一个空格。 -k1: *和&在表示指针和引用类型时,和类型名称并紧。和变量名之间留空格; -p: 在运算符号(操作符)左右加上空格; -P: 在括号两边插入空格;-d仅仅在括号外面插入空格。-D仅仅在里面插入; -j: 给每一个”if”、”for”、“while”添加大括号; -D: 在小括号边上添加一个空格; -c: 将TAB替换成空格; -M: 对定义的參数和变量进行对齐; -w: 对宏进行对齐处理; 更多符号,以后再添加吧 此外还有其他一些插件,文件注释插件:FileComments、函数注释插件FunctionComments、时间显示插件DateTime,有兴趣的小伙伴需要可以评论区留言私发哦

git 相关操作整理

1. 强制本地分支推送覆盖远程分支 慎用 本地分支:dev_1.27.10 远程分支:master 命令:git push origin dev_1.27.10:master --force 2. 将B分支合并到A分支 git checkout A git merge B

vue3使用element-plus控件显示英文,如何改为中文

问题描识:今天使用element-plus的DateTimePicker控件时,发现显示的都是英文,如下图所示,接下来我教大家修改所有控件显示默认为中文 解决方案:在main.js,引入 import locale from 'element-plus/lib/locale/lang/zh-cn'; 然后注册element全局的时候用 .use(ElementPlus,{locale}) 问题解决:

QGraphicsItem图元旋转缩放和自定义图元(三)

系列文章目录 QGraphicsItem图元的简单使用(一) QGraphicsItem图元拖动绘制(二) 文章目录 系列文章目录前言一、缩放和旋转二、自定义图元总结 前言 接上一章,图元绘制出来了,但有时候需要对图元进行缩放或旋转处理,这章先讲解如何调用图元自带函数来对图元进行缩放、旋转等操作; 一、缩放和旋转 先讲解下如何使用图元自带的缩放和旋转函数,后面自己派生QGraphicsItem时就可以通过鼠标拖动选中图元来实现缩放和旋转了; 简单处理,通过重写场景类的鼠标滑轮事件来实现,具体代码如下: void GraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *event) { // 获取当前选中的图元 QList<QGraphicsItem *> listItem = this->selectedItems(); foreach (QGraphicsItem *item, listItem) { // 返回转轮旋转的距离,以八分之一度(1/8秒)为单位。正值表示滚轮向前旋转,远离用户;负值表示滚轮向用户方向向后旋转 int iDelta = event->delta(); if (item->type() == QGraphicsEllipseItem::Type) // 椭圆进行缩放处理 { QGraphicsEllipseItem* pEllipse = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); if(pEllipse != nullptr) { // 获取图元绘图区域的矩阵,也就是图元被选中时那个虚线框 QRectF rect = pEllipse->boundingRect(); // 因为图元默认的缩放原点为(0,0),放大时图元朝着右下脚偏移,缩小时图元朝着左上角偏移 // 所以设置图元中心点为缩放原点 pEllipse->setTransformOriginPoint(rect.center()); if(iDelta > 0) // 放大 { qreal dRate = 1.1; // 每次放大10% pEllipse->setScale(pEllipse->scale() * dRate); } else if(iDelta < 0) // 缩小 { qreal dRate = 0.

Dubbo入门实战最全攻略(基于 Spring Boot 实现)

Dubbo应用 RPC通信 Apache Dubbo 3构建在 HTTP/2 协议之上,具有更好的穿透性与通用性 , 支持基于 IDL 的服务定义 集成了业界主流的大部分协议,使得用户可以在 Dubbo 框架范围内使用这些通信协议 , 这些协议包括 rest、hessian2、jsonrpc、thrift 等 服务发现 即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信 Dubbo 提供的是一种 Client-Based 的服务发现机制,通常还需要部署额外的第三方注册中心组件来协调服务发现过程,如常用的 Nacos、Consul、Zookeeper 等,Dubbo 自身也提供了对多种注册中心组件的对接,用户可以灵活选择 Dubbo服务注册与发现过程如下图(图片来自官网): 流量治理 Dubbo 提供了丰富服务治理规则,包括路由规则、动态配置等 部署架构 Dubbo 作为一个微服务框架,为在分布式环境下实现各个微服务组件间的协作,定义了一系列中心化组件,包括 注册中心:协调服务提供者(Provider)和服务消费者(Consumer)之间的地址注册与发现 配置中心: 存储 Dubbo 启动阶段的全局配置,保证配置的跨环境共享与全局一致性 负责服务治理规则(路由规则、动态配置等)的存储与推送 元数据中心: 接收 Provider 上报的服务接口元数据,为 Admin 等控制台提供运维能力(如服务测试、接口文档等) 作为服务发现机制的补充,提供额外的接口/方法级别配置信息的同步能力,相当于注册中心的额外扩展 下图描述了Dubbo各服务组件间协调的交互图(图片来自官网): 其他内容 可以参考官网的”什么是Dubbo?”内容, https://dubbo.incubator.apache.org/zh/overview/what/ Dubbo示例 需求 构建一个基于用户的CRUD服务 服务提供者(Provider)根据契约提供服务 服务消费者(Consumer)根据契约消费服务 服务消费者(Consumer)以泛化方式消费服务 实现逻辑 分别开发如下项目,实现需求(如上图) 服务接口项目:定义的服务规范IUserService、公共实体类UserEntity 服务提供者(Provider)项目: 引入Nacos注册依赖 添加注册到指定Nacos服务注册中心的配置 引入契约接口依赖 定义UserService服务实现,定义实际的业务逻辑,继承于IUserService,并使用公共实体类UserEntity 服务消费者(Consumer)项目: 引入Nacos注册依赖

Comparison method violates its general contract解决办法

最近有客户自行升级了系统的JDK版本,原本是1.6的,升到了1.8。导致出现了一个偶发的bug Comparison method violates its general contract 查询JDK的资料得知,在JDK1.7开始对Comparator类进行了优化,必须包含3个特性。比如在1.6的时候可以只返回-1和1,但是在1.7之后某些情况必须返回0。 借用查询的资料,Comparator必须包含: 自反性:当两个相同的元素相比,compare方法必须返回0,也就是compare(o1, o1) = 0; 反对称性:如果compare(o1,o2) = 1,则compare(o2, o1)必须返回符号相反的值也就是 -1; 传递性:如果 a>b, b>c, 则 a必然大于c。也就是compare(a,b)>0, compare(b,c)>0, 则compare(a,c)>0 系统原来的代码是这样: public int compare(Object o1, Object o2) { return o1.getScore() > o2.getScore() ? -1 : 1; } 这样当两个分数score相等时,就没有返回0,违反了自反性,导致Comparison method violates its general contract的报错 优化后改成compareTo方法,是这样的: public int compare(Object o1, Object o2) { return -o1.getScore().compareTo(o2.getScore()); } 问题解决。 后面了解到有另外一种可以暂时不修改代码的解决方法,就是在java启动时加上参数 -Djava.util.Arrays.useLegacyMergeSort=true 有用户反馈也能解决,没有出现报错。