进入正题 元素拖拽是一个比较典型的前端学习案例,需要对 JavaScript 的事件有一定的了解,我也是在最近的工作中才重新拾起了这块内容,通过在 Vue3 这种声明式编程风格的框架中把元素拖拽一次讲清楚。
元素的位置和移动 在实现元素拖拽我们使用 mouse 事件,在 mouse 事件的回调函数中可以得到当前事件发生时元素的位置,对应的属性是 MouseEvent 中的 clientX 和 clientY,我们后续将通过读取这两个属性来实时更新元素的位置。
元素的移动推荐优先使用 transform 中的 translate 实现,相比于修改元素的 top、left 属性来说不会造成元素布局的改变,避免了回流和重绘造成的性能影响。
PS:在 MDN 有一份关于translate的使用和体验,可以感受一下。
定义三组坐标 分别定义用来记录元素初始位置的一组坐标(originalPosition)、元素被按下时指针在元素上的坐标(mousedownOffset)和元素在移动时实时更新的一组坐标(elementPosition)。
记录元素初始位置的坐标,原点位于页面左上角,用来在初始化和被拖拽结束后还原被拖拽元素的位置,固定值不发生变化:
typescript复制代码const originalPosition = reactive({ x: 10, y: 10, }) 元素被按下时指针在元素上的坐标,原点位于被拖拽元素的左上角,通过按下时指针的坐标 - 元素初始的偏移位置得到:
typescript复制代码const mousedownOffset = reactive({ x: 0, y: 0, }) 元素在移动时实时更新的坐标,原点位于页面左上角,初始值应该同 originalPosition ,在 mousemove 事件发生时,通过指针的实时坐标 - mousedownOffset 得到:
typescript复制代码const elementPosition = reactive({ x: 0, y: 0, }) PS:当原点是页面左上角时在图中的1号点表示 originalPosition 或 elementPosition,2号点表示指针按下时的坐标,当原点是1号点时在图中的2号点表示 mousedownOffset;
1.定义游标 cursor cursor_name is select_statement;
2.打开游标 执行对应的SELECT语句并将SELECT语句的结果暂时存放到结果集中.
open cursor_name;
3.提取数据 打开游标后,SELECT语句的结果被临时存放到游标结果集中,使用FETCH语句只能提取一行数据
通过使用FETCH..BULK COLLECT INTO语句每次可以提取多行数据
例子:
游标的使用步骤:
1.声明一个游标
2.打开游标 open 游标名(参数1,参数2..);
3.使用循环遍历游标,从游标中取值。fetch 游标名 into 变量名,循环的退出条件是 游标名%notfound;
4.关闭游标 close 游标名;
cursor 游标名(游标输入参数) is select语句 -- 游标参数可以有多个 -------------------------------------- 游标中使用fetch..into语句:只能处理一行数据,除非用循环语句 -------------------------------------- --匿名块 declare --游标的定义 CURSOR emp_cur IS select empno,ename,job from scott.emp; emp_row emp_cur%rowtype;--定一个和游标一样类型的集合 BEGIN --打开游标 OPEN emp_cur; LOOP --提取游标中的数据到emp_row FETCH emp_cur into emp_row; EXIT WHEN emp_cur%notfound; dbms_output.put_line(emp_row.empno||','||emp_row.ename); END LOOP; --关闭游标 CLOSE emp_cur; END; ---- 或者 --- --匿名块 方法2 declare --游标的定义 CURSOR emp_cur IS select empno,ename,job from scott.
MMPretrain是全新升级的开源预训练框架。它已着手提供多个强大的预训练骨干网并支持不同的预训练策略。MMPretrain 源自著名的开源项目 MMClassification 和MMSelfSup,并开发了许多令人兴奋的新功能。目前,预训练阶段对于视觉识别至关重要。凭借丰富而强大的预训练模型,我们目前有能力改进各种下游视觉任务。
我们代码库的主要目标是成为一个易于访问且用户友好的库,并简化研究和工程。我们详细介绍了 MMPretrain 不同部分的属性和设计。
1、MMPretrain 实践路线图 为了帮助用户快速使用 MMPretrain,我们建议遵循我们为库创建的实践路线图:
(1)对于想要尝试 MMPretrain 的用户,我们建议阅读入门 部分以了解环境设置。 (2)对于基本使用,我们建议用户参考用户指南,以利用各种算法来获取预训练模型并评估其在下游任务中的性能。 (3)对于那些希望自定义自己的算法的人,我们提供了 高级指南,其中包括修改代码的提示和规则。 (4)要找到您想要的预训练模型,用户可以查看ModelZoo,它总结了各种主干和预训练方法以及不同算法的介绍。 (5)此外,我们还提供分析和可视化工具来帮助诊断算法。 2、环境配置安装 1、 先决条件 在本节中,我们将演示如何使用 PyTorch 准备环境。
MMPretrain 适用于 Linux、Windows 和 macOS。它需要 Python 3.7+、CUDA 10.2+ 和 PyTorch 1.8+。
2、安装 创建conda环境并激活。 conda create --name mmpretrain python=3.8 -y #创建环境 conda activate mmpretrain #激活环境 conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch #安装 PyTorch and torchvision (官方) #如果网不好,可以这样安装 pip3 install torch==1.8.2+cu102 torchvision==0.9.2+cu102 torchaudio===0.8.2 -f https://download.
夏日炎炎,给大家分享20个涨姿势的小众网站,打开你的新世界大门!
1、电台公园 http://radio.garden/
可以收听到世界各地的电台,在世界地图上选一个绿点,就可以收听当地的电台了。
2、下载 4K 画质 Bing 壁纸 https://bing.lylares.com/
收集了Bing所有的壁纸,支持下载高清原图。
3、免费思维导图 https://gitmind.cn/
全平台免费思维导图,可以画思维导图、流程图、鱼骨图,日常办公学习必备。
4、DeepL 翻译 DeepL Translate: The world's most accurate translator
很有潜力的翻译工具!这是款结合了时下流行的 Ai、大数据等概念的翻译工具,支持中文。
5、天际网络摄像头 ▶️ Live HD Cams from the World! - SkylineWebcams
观看世界各地景区的实时摄像头画面。
6、HiFiNi - 音乐磁场 HiFiNi - 音乐磁场
HiFiNi 是一个由音乐爱好者维护的分享平台, 旨在解决问题互帮互助。关键词:无损音乐下载,高品质音乐下载。
7、myNoise® Background Noises • Ambient Sounds • Relaxing Music | myNoise ®
我个人很喜欢!设计很独特的一个白噪音网站,创造美妙的噪音来掩盖您不想听到的噪音。由于其独特的音频工程,myNoise 在背景声音中树立了标准。
8、在线红白机游戏网站 小霸王,其乐无穷 。红白机,FC在线游戏,街机游戏,街机在线,NES games,NES games online,Super Mario
小时候常玩的超级玛丽、魂斗罗、冒险岛应有尽有。界面简洁,windows、IOS、Android都可以玩,无需下载
9、俄罗斯方块游戏 俄罗斯方块
过滤数组, 返回一个新数组,包含符合条件的所有元素,
如果没有符合条件的元素,则返回空数组。
注意 filter 方法会遍历数组的每一项,并对每一项应用回调函数进行判断。当回调函数返回 true 时,当前项会被包含在新数组中;当回调函数返回 false 时,当前项会被过滤掉,不包含在新数组中。
无论回调函数返回 true 还是 false,filter 方法会遍历完整个数组。它会对数组中的每一项都应用回调函数,并根据回调函数的返回值决定是否将当前项包含在新数组中。
当回调函数返回 true 时,filter 方法会将当前项加入到新数组中,并继续遍历下一项。当回调函数返回 false 时,filter 方法会直接跳过当前项,不将其加入到新数组中,并继续遍历下一项。
只有当遍历完整个数组后,filter 方法才会返回新数组,其中包含满足条件的项。
所以,无论遇到 true 还是 false,filter 方法都会遍历完整个数组,并返回满足条件的项组成的新数组。
filter过滤器,返回的是一个boolean,如下, a、返回true时, 函数内部,会自动将这次回调的n,加入到新的数组中 b、返回false时,函数内部,会过滤掉这次的n 示例: const nums = [ { id: 20, age:18, name: 'Captain Piett' }, { id: 24, age:30, name: 'General Veers' }, { id: 56, age:58, name: 'Admiral Ozzel' }, { id: 88, age:68, name: 'Commander Jerjerrod' } ]; // 对数组进行过滤,筛选出,年龄大于18岁的数据 let newArr = nums.
文章目录 1、概述2、Spring Security、Apache Shiro 选择问题2.1、Shiro2.1.1、shiro的优点2.1.2、shiro的缺点 2.2、Spring Security2.2.1、spring-security的优点 3、快速入门3.1、装备工作 4、认证4.1、登录流程校验4.2、入门案例的原理4.3、正式开始4.3.1 准备工作4.3.2、实现4.3.3、核心代码实现4.3.3.1、密码加密存储4.3.3.2、登陆接口4.3.3.3、认证过滤器4.3.3.4、退出登陆 5、授权5.1、权限的作用5.2、授权基本流程5.3、授权实现5.3.1、限制访问资源所需权限5.3.2、封装权限信息5.3.3 从数据库查询权限信息5.3.3.1 RBAC权限模型5.3.3.2 准备工作5.3.3.3、代码实现 6、自定义失败处理6.1、自定义实现类6.2、配置给SpringSecurity 7、 跨域8、自定义权限校验方法9、CSRF10、认证处理器10.1、认证成功处理器10.2、认证失败处理器10.3、注销成功处理器 原文链接: SpringSecurity框架【详解】 1、概述 Spring Security是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富;
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准;
Spring Security是一个框架,致力于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求。
在 Java 生态中,目前有 Spring Security 和 Apache Shiro 两个安全框架,可以完成认证和授权的功能。
我们先来学习下 Spring Security 。其官方对自己介绍如下:
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。
C语言中的数组(详解) 一、一维数组1.一维数组的创建2.数组的初始化3.一维数组的使用4.一维数组在内存中的存储二、二维数组1.二维数组的创建2.二维数组的初始化3.二维数组的使用4.二维数组在内存中的存储三、数组越界四、数组作为函数参数1.冒泡排序2.数组名是什么?3.代码修正 🎈个人主页:库库的里昂🎐CSDN新晋作者🎉欢迎 👍点赞✍评论⭐收藏✨系列专栏C语言初阶、代码小游戏🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 【前言】
数组可以说是目前为止讲到的第一个真正意义上存储数据的结构。
虽然前面学习的变量也能存储数据,但变量所能存储的数据很有限。不仅如此,数组和指针(后续会讲)是相辅相成的,学习数组可以为学习指针打下基础。
注!!!
由于本文讲解的数组需要用到自定义函数的概念,没有学习的小伙伴可以查看函数的讲解:C语言中的函数
一、一维数组 1.一维数组的创建 一维数组的定义方式如下:
类型说明符 数组名[常量表达式]; 例:int arr[5]; 它表示定义了一个整型数组,数组名为 arr,定义的数组称为数组 arr。
注:数组创建,在C99标准之前, [] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念。(作者用的编译器是VS2019不支持C99标准)
2.数组的初始化 所谓数组初始化是指在创建数组的同时给数组的内容一些合理初始值。
下面举出数组初始化的情况:
//整形数组 int arr1[5] = { 1, 2, 3, 4, 5 };//完全初始化 int arr2[5] = { 1, 2 };//不完全初始化 int arr3[5] = { 1, 2, 3, 4, 5 }; int arr4[] = { 1, 2, 3, 4, 5 }; //字符型数组 char arr5[] = {'a','b','c'}; char arr6[] = "
文章目录 一、前言二、创意名三、效果展示四、烟花代码五、总结 一、前言 2022年圣诞节到来啦,圣诞节是基督教纪念耶稣诞生的重要节日。亦称耶稣圣诞节、主降生节,天主教亦称耶稣圣诞瞻礼。耶稣诞生的日期,《圣经》并无记载。公元336年罗马教会开始在12月25日过此节。12月25日原是罗马帝国规定的太阳神诞辰。有人认为选择这天庆祝圣诞,是因为基督教徒认为耶稣就是正义、永恒的太阳。5世纪中叶以后,圣诞节作为重要节日,成了教会的传统,并在东西派教会中逐渐传开。因所用历法不同等原因,各教派会举行庆祝的具体日期和活动形式也有差别。圣诞节习俗传播到亚洲主要是在十九世纪中叶,日本、韩国等都受到了圣诞文化的影响。现在西方在圣诞节常互赠礼物,举行欢宴,并以圣诞老人、圣诞树等增添节日气氛,已成为普遍习俗。圣诞节也成为西方世界以及其他很多地区的公共假日。
二、创意名 圣诞节就要到了,本篇我们将用html+js写一个动态的烟花代码,程序员的浪漫这不就来了吗,感兴趣的小伙伴可下载学习,安静的在家中读懂它的那一刻,在这疫情肆虐的日子里也是一件很不错的事,将有趣的东西分享给你,希望你度过一个愉快的圣诞节!
三、效果展示 基础版动画效果,有声音
进阶版动画效果,可点击绽放烟花
四、烟花代码 动画主要由焰火类,背景图和随机函数等组成。进阶版可点击屏幕直接开始绽放烟花。
以下是HTML部分,完整代码及效果点击下载👉烟花代码
进阶版👉烟花代码2
<!doctype html> <html> <head> <meta charset="utf-8"> <title>动态烟花代码</title> <style> html, * { margin: 0; padding: 0 } body { background-image: url(bg.png); background-size: 100% 100%; background-size: 100%; background-repeat:no-repeat; } .demo { margin: 0 auto; width: 100%; height: 100%; } h1 { margin: 150px auto 30px auto; text-align: center; font-family: 'Roboto'; } </style> </head> <body> <div class="demo"> </div> <script src="
先试了强制替换,无法替换掉,强制删除,也删除不掉namespace
[root@master k8s-study]# vi ns-demo.yaml [root@master k8s-study]# kubectl create -f ns-demo.yaml namespace/demo created [root@master k8s-study]# kubectl get -f ns-demo.yaml NAME STATUS AGE demo Active 17s [root@master k8s-study]# cp ns-demo.yaml ns-demo-v2.yaml [root@master k8s-study]# vi ns-demo-v2.yaml [root@master k8s-study]# kubectl replace -f ns-demo-v2.yaml namespace/demo replaced [root@master k8s-study]# kubectl get -f ns-demo.yaml NAME STATUS AGE demo Active 102s [root@master k8s-study]# kubectl get -f ns-demo.yaml -o yaml apiVersion: v1 kind: Namespace metadata: creationTimestamp: "2023-07-26T13:22:49Z" labels: kubernetes.
Mysql索引分类及其使用实例详解 Mysql的索引分类 MySQL 索引
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。
拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
单列索引 单列索引又可以叫普通索引,一个索引只包含一个列,一个表中可以有多个单列索引.
创建单列索引的几种方式: 外部创建
CREATE INDEX indexName ON table_name (column_name) 修改表结构(添加索引)
ALTER table tableName ADD INDEX indexName(columnName) 创建表的时候直接指定
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX [indexName] (username(length)) ); 唯一索引 它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
创建唯一索引的几种方式: 外部创建
CREATE UNIQUE INDEX indexName ON mytable(username(length)) 修改表结构(添加索引)
ALTER table mytable ADD UNIQUE [indexName] (username(length)) 创建表的时候直接指定
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, UNIQUE [indexName] (username(length)) ); 联合索引(复合索引) 复合索引是索引中功能最强大的一个,索引能够同时覆盖多个数据列,
前言:文章最后将给出完整代码,前边的代码会因为便于讲解而不全面,仅供参考。
目录
一.三子棋游戏规则
二.分析如何布局
三.代码展示与讲解
1.游戏菜单
2.展示棋盘
3.玩家下棋
4.电脑下棋
5.判断输赢/平局
四.全代码展示
1.game.h
2.game.c
3.test.c
五.总结
一.三子棋游戏规则 朋友们小时候肯定都玩过三子棋,无非就是一个三乘三的棋盘,两个人轮流落子,谁的棋子率先连成一排,一列或一个对角线就会胜出,但是这个游戏也会出现无子可落,也就是九个格子被占满了,造成平局。
二.分析如何布局 我们知道,写代码讲究一个整洁有序,即使是设计三子棋这样一个极为简单的游戏,也不是短短几十行代码就能搞定的。
如下图,我们通过创建一个自己的头文件"game.h"来集中存放我们需要使用到的头文件,以及声明我们需要用到的函数,只需要在源文件中都要声明我们自己的头文件#include"game.h"即可。
此外,我们又创建一个新的源文件game.c来集中创建我们需要的函数。
最后,我们游戏的主体代码则写在源文件test.c中。
三.代码展示与讲解 1.游戏菜单 任何游戏都需要一个菜单来选择游戏如何进行。
void menu()//打印菜单函数 { printf("******************************\n"); printf("******* 1.play *******\n"); printf("******* 0.exit *******\n"); printf("******************************\n"); } char board[ROW][COL] = {'0'};//游戏数组 int main() { int input = 0; do { menu(); printf("请选择->:"); scanf("%d", &input);//选择 switch (input) { case 1: printf("三子棋\n"); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while (input); return 0; } 我们创建一个menu(菜单)函数来专门输出我们的菜单,并通过do-while循环,switch-case语句来实现游戏的循环游玩。
创建和管理volumes 创建卷docker volume create my-vol 列出卷docker volume ls 查看卷详情docker volume inspect my-vol 删除卷docker volume rm my-vol 启动容器时使用卷 启动容器时,使用的卷没有创建,docker会自动创建卷
启动容器时,–mount或-v docker run -d \ --name devtest \ --mount source=myvol2,target=/app \ nginx:latest 使用-v的方式(需要先删除刚才的devtest容器和myvol2卷)docker run -d \ --name devtest \ -v myvol2:/app \ nginx:latest 只读的方式挂载卷docker run -d \ --name=nginxtest \ --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \ nginx:latest 使用-v,只读的方式挂载卷(需要先删除刚才的nginxtest容器和nginx-vol卷)docker run -d \ --name=nginxtest \ -v nginx-vol:/usr/share/nginx/html:ro \ nginx:latest 清除刚才创建的卷和容器docker container stop devtest docker container rm devtest docker volume rm myvol2 启动Service的时候使用卷 创建service
cron 是一个Linux定时执行工具,可以让系统在指定的时间,去执行某个指定的工作。在Ubuntu中,cron是被默认安装并启动的。
cron可以让系统在指定的时间,去执行某个指定的工作,我们可以使用 crontab 指令来管理cron机制。
crontab的参数:
-u:编辑其他人的crontab,如果没有加上这个参数的话就会开启自己的crontab crontab -u 使用者名称 -l:可以列出crontab的内容 -r:可以移除crontab -e:可以使用系统预设的编辑器,开启crontab -i:可以移除crontab,会跳出系统信息让你再次确定是否移除crontab crontab -e 默认用的是当前用户
sudo crontab -e 用的是root用户
语法:
minute(分):可以设置0-59分 hour(小时):可以设置0-23小时 day of month(日期):可以设置1-31号 month(月份):可以设置1-12月 day of week(星期):可以设置0-7星期几,其中0和7都代表星期天,也可以使用名称来表示星期天到星期一,例如sun表示星期天,mon表示星期一 "*" 代表取值范围内的数字 "/" 代表"每" "-" 代表从某个数字到某个数字 "," 分开几个离散的数字 # 顺序:分 时 日 月 周 用户 命令 minute hour day month week user command 举例子:
*/5 * * * * sh /root/hello.sh 每五分 钟执行hello.sh文件 0 * * * * sh /root/hello.
哈喽,哈喽,大家好~ 我是你们的老朋友:保护小周ღ 今天给大家带来的是 SpringBoot 的简介,SpringBoot 项目的创建,相较于 Spring 框架的优点: 1. 快速的集成框架 2.内置运行容器, 快速的部署项目 3. 摒弃繁琐的 xml,使用注解和配置的方式进行开发。4. 支持更多的监控的指标,本文将为大家讲解,一起来看看叭~
本期收录于博主的专栏:JavaEE_保护小周ღ的博客-CSDN博客
适用于编程初学者,感兴趣的朋友们可以订阅,查看其它 “JavaEE基础知识”。
更多精彩敬请期待:保护小周ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* ‘
一、SpringBoot 简介 SpringBoot 的由来可以追溯到 Spring 框架。Spring 是一个非常流行的开源 Java 框架,用于构建企业级应用程序。然而,使用 Spring 框架开发传统的 Java 应用程序需要进行繁琐的配置,并且部署也需要额外的手动操作。
为了简化 Spring 应用程序的开发和部署过程,SpringBoot 在2013年由 Pivotal 团队推出(与Spring 并不是同一团队)。它的目标是通过提供一系列的自动配置、快速启动、内嵌服务器和起步依赖项等功能,使得开发者可以更轻松地创建和部署 Spring 应用程序。
SpringBoot 的设计理念是 “约定大于配置” 的方式来提高开发效率。它采用了一套预定义的规则和约定,根据项目的依赖和类路径进行自动配置,大部分情况下无需手动配置。开发者只需要关注业务逻辑的实现而不必浪费时间在繁琐的配置上。
Spring 的诞生是为了简化 Java 应用程序的开发,而 SpringBoot 的诞生是为了简化 Spring 程序的开发,SpringBoot 是为了快速的开发 Spring 框架而诞生的。
例如:Spring 割稻谷
SpringBoot 割稻谷
也是很鲜明的对比,技术的更新迭代嘛,新的技术相较于之前的技术在效率方面肯定有一些提升。
二、SpringBoot 的优点 优点建立在Spring 框架的基础之上~
2.1 快速的集成框架: 我们想要创建 Spring 项目,最常用的一个做法是先创建一个Maven 项目,然后从 Maven 中央仓库中获取 Spring 的依赖(Spring 属于第三方开源框架),注入到 pom.
什么是SEO图片搜索
图片搜索是通过搜索程序,向用户提供互联网上相关的图片资料的服务。图片搜索的目的是查找出自己所需要的特定图片。
网站的图片内容出现在整合搜索中,应该注意下面几点:
一、ALT文字
这是图片优化最重要的部分,因为ALT文字本身就是为了说明图片内容。ALT文字应该出现目标关键词,准确描述图片内容。
二、页面标题
图片所在页面的标题也很重要。标题写法参考前面页面优化部分。
三、图片周围文字
图片出现的周围文字内容也在一定程度上表明图片内容。当然,这里所说的图片周围文字指的是HTML代码中图片文件的前后,而不一定是用户所看到的页面上图片周围的文字。有时候由于排版原因,视觉上看来处于图片周围的文字,在代码中可能相距很远。
四、图片质量
图片的解像度和像素,也就是图片质量也影响图片优化。质量越高,被排到前面的可能性越大。搜索引擎并不想返回低质量的图片。
五、导入链接锚文字
导入到图片出现页面的链接所使用的锚文字,既表明页面本身的内容主题,对图片内容也是个说明,会被搜索引擎考虑在内。
code and paper: https://arxiv.org/abs/2206.12411
SMILES的benchmark:
【13】GuacaMol: Benchmarking Models for De Novo Molecular Design:GuacaMol: Benchmarking Models for De Novo Molecular Design | Papers With Code
【25】BOSS: Bayesian Optimization over String Spaces:BOSS: Bayesian Optimization over String Spaces | Papers With Code
【6】Automatic chemical design using a data-driven continuous representation of molecules:Automatic chemical design using a data-driven continuous representation of molecules | Papers With Code
【5】Molecular De Novo Design through Deep Reinforcement Learning:Molecular De Novo Design through Deep Reinforcement Learning | Papers With Code
Cilium ConfigMap cilium configmap 是配置cilium的地方:
root@node1:~# kubectl get cm -n kube-system | grep cilium cilium-config 34 7d21h root@node1:~# kubectl edit cm -n kube-system cilium-config # Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 data: agent-health-port: "9879" auto-direct-node-routes: "
实现效果如下:
功能点:
1. 当表格内容超出时,自动滚动,滚动到最后一条之后在从头滚动。
2. 表格中的数据会定时刷新,刷新后数据更新。
3. 鼠标移入表格中,停止滚动;移出后,继续滚动。
4. 点击表格中的排序功能,拉取后端数据,从头滚动。
先说一说实现过程中遇到的大坑吧 坑1: vue-seamless-scroll依赖的使用 1. 安装并对应引入
yarn add vue-seamless-scroll 局部引入:
import vueSeamlessScroll from "vue-seamless-scroll"; components: { vueSeamlessScroll }, 2. 使用
用该组件包住要滚动的表格,并将表格数据传进去
参数:tableData是我的表格数据数组,defineScroll是滚动的参数,参考如下:
代码:
classOption() { return { step: 0.5, // 数值越大速度滚动越快 limitMoveNum: 5, // 开始无缝滚动的数据量 hoverStop: true, // 是否开启鼠标悬停stop direction: 1, // 0向下 1向上 2向左 3向右 openWatch: true, // 开启数据实时监控刷新dom singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1 singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3 waitTime: 500, // 单步运动停止的时间(默认值1000ms) }; }, 3.
文章目录 1. 参考连接2. 使用说明2.1 导出加速模型2.1 使用加速模型2.2 加速参数对比 3. 问题说明3.1 在 Tensorrt 8.4.1.5 版本上使用 export.py 导出失败的问题3.2 把模型文件由 best.pt 更换成加速后的 best.engine 后,执行推理时标注的类别名不正确的问题3.3 导出加速模型和使用加速模型推理时 batch_size 不一致的问题3.3.1 为啥使用 PyTorch 的 pt 模型不需要匹配 batch_size,而使用 Tensorrt 的 engine 模型需要呢(代码层面)?3.3.2 为什么 pt 模型不需要检测,而 engine 模型需要检测张量形状匹配呢?(原理层面) 3.4 导出过程中出现了 Some tactics do not have sufficient workspace memory to run. Increasing workspace size will enable more tactics, please check verbose output for requested sizes 提示信息的问题3.5 高版本 tensorrt 导出的模型文件移植到低版本上报出属性错误 'NoneType' object has no attribute 'num_bindings' 的问题3.
文章目录 前言一、Jupter Notebook是什么1.1 简介1.2 组成部分1.3 Jupyter Notebook的主要特点 二、为什么使用Jupyter Notebook?三、安装四、Jupyter Notebok配置4.1 基本配置4.2 配置开机自启与后台运行4.3 开启代码自动补全 五、两种键盘输入模式5.1 编辑模式5.2 命令模式5.3 其他常用快捷键 六、魔法命令6.1 查看帮助文档6.2 其他魔法命令 七、结语参考 前言 在上一篇中我们已经安装好了Anaconda,Anaconda本身自带Jupter Notebook。本期我们来学习使用 Jupyter Notebook。
一、Jupter Notebook是什么 1.1 简介 Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍
Jupyter Notebook是一个开源 Web 应用程序,允许您创建和共享包含实时代码、方程式、可视化和叙述文本的文档。用途包括:数据清理和转换,数值模拟,统计建模,数据可视化,机器学习等等。支持python、C、java、Go等多种编程语言。同时支持markdown编辑器。
简而言之,Jupyter Notebook是以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也会直接在代码块下显示的程序。如在编程过程中需要编写说明文档,可在同一个页面中直接编写,便于作及时的说明和解释。
Jupyter Notebook 已迅速成为数据分析,机器学习的必备工具。因为它可以让数据分析师集中精力向用户解释整个分析过程。
1.2 组成部分 ① 网页应用
网页应用即基于网页形式的、结合了编写说明文档、数学公式、交互计算和其他富媒体形式的工具。简言之,网页应用是可以实现各种功能的工具。
② 文档
即Jupyter Notebook中所有交互计算、编写说明文档、数学公式、图片以及其他富媒体形式的输入和输出,都是以文档的形式体现的。
这些文档是保存为后缀名为.ipynb的JSON格式文件,不仅便于版本控制,也方便与他人共享。
此外,文档还可以导出为:HTML、LaTeX、PDF等格式。
1.3 Jupyter Notebook的主要特点 ① 编程时具有语法高亮、缩进、tab补全的功能。
② 可直接通过浏览器运行代码,同时在代码块下方展示运行结果。
③ 以富媒体格式展示计算结果。富媒体格式包括:HTML,LaTeX,PNG,SVG等。
④ 对代码编写说明文档或语句时,支持Markdown语法。
⑤ 支持使用LaTeX编写数学性说明。
二、为什么使用Jupyter Notebook? 传统软件开发:工程/目标明确
最近想写写C++,装了VisualStudio 2022,折腾半天。对于一个用惯VSCode的人来说,总感觉IDE太笨重。于是自己网上各种查资料,自己琢磨,搭建了一套Windows下基于VSCode和CMake的C++轻量级开发环境。
具体搭建步骤 1. 下载并安装VSCode VSCode下载地址(AzureCDN加速地址)
首先同意安装协议:
下一步,方便起见全部都勾上:
之后点击安装即可:
2. 安装必要的VSCode插件 这里推荐安装Microsoft官方提供的Chinese简体中文汉化包、C/C++、C/C++ Extension Pack三个插件,C/C++ Extension Pack扩展会自动为我们安装CMake、CMake Tools等插件。
3. 下载并解压MinGW64、CMake MinGW全称是Minimalist GNU on Windows,也就是将Linux/Unix环境下赫赫有名的GCC编译器以及其相关的编译调试组件移植到了Windows上。通过这个工具集我们就可以编译、调试、运行和打包C/C++项目了。
MinGW64下载地址(github最新版 gcc 13.1.0)
github下载慢的话可以考虑GitHub文件加速:https://ghproxy.com
下载完成后解压到某个指定的目录即可 (记住这个目录,后面会用到)
之后下载CMake,CMake是一款现代化的C++编译打包工具,很多开源的C/C++都在用。个人感觉有点像Java的Maven构建工具,但功能没有Maven那么齐全。CMake下载地址(CMake官网最新版3.27.0)
下载完成后一样,解压到某个指定的目录下即可 (同样也要记住这个目录)
最后的重头戏就是用以上两个解压目录配置环境变量啦,打开设置->系统->系统信息:
点击系统信息->高级系统设置:
点击环境变量:
选择上下两个Path都可
将 安装目录\bin 配置在Path变量中,之后一路点击确定就大功告成了!
4. 添加.vscode目录下的配置 使用VSCode打开一个空文件夹,创建一个叫做 .vscode 的文件夹 (注意前面有个英文句号.不要漏掉了),分别创建c_cpp_properties.json、settings.json、launch.json和tasks.json四个文件,文件内容如下:
c_cpp_properties.json
{ "configurations": [ { "name": "Win32", "includePath": [ "${workspaceFolder}/**" ], "defines": [ "_DEBUG", "UNICODE", "_UNICODE" ], "windowsSdkVersion": "10.0.17763.0", "compilerPath": "C:\\Users\\22820\\apps\\mingw64\\bin\\g++.exe", // 此处指定自己安装的g++.exe地址 "cStandard": "
题目:编写一个递归函数,将输入的字符串逆序输出。
要求:使用递归方式实现。
提示:逆序字符串即将字符串中的字符顺序颠倒过来。
例如,将字符串"Hello, World!“逆序输出为”!dlroW ,olleH"。
第一种:交换数组位置
#include <stdio.h> #include <string.h> void reverseString(char str[100], int left, int right) { if (left < right) { char temp = str[left]; str[left] = str[right]; str[right] = temp; reverseString(str, left+1, right-1); } } int main() { char str[100]; printf("请输入一个字符串:"); scanf("%s", str); int left = 0; int right = strlen(str) - 1; reverseString(str, left, right); printf("逆序后的字符串为:%s\n",str); return 0; } 第二种:指针变量接收地址
#include <stdio.h> void reverseString(const char* str) { // 当遍历到字符串的末尾(即遇到空字符'\0')时停止递归 if (*str == '\0') { return; } // 传入下一个字符的地址,实现逆序输出 reverseString(str + 1); // 输出当前字符 printf("
1.Stream API 介绍 Java8 版本引入的重要特性之一, 对于集合(例如 List、Map、Set 等)进行处理和操作的高级抽象.Stream API 提供了一种更为简洁高效的的方式来处理集合数据, 可读性较高, 特别在数据的过滤、转换、聚合时的操作很简单方便快捷.
1.1 特点与优势 函数式风格: Stream API使用函数式接口和Lambda表达式, 让代码更具表达力和简洁性.惰性求值: Stream操作通常是惰性求值的, 这意味着在终端操作之前, 中间操作不会立即执行, 从而提高了效率.并行处理: 通过Stream API可以方便地实现并行处理, 从而充分利用多核处理器的优势, 加速处理大量数据的过程. 下面根据一些实际应用场景来分析
1.2 两大类型 中间操作(Intermediate Operations):中间操作是指在Stream上执行的操作, 它们返回一个新的Stream, 允许你链式地进行多个中间操作.终端操作(Terminal Operations):对Stream进行最终处理的操作, 当调用终端操作时, Stream会开始执行中间操作, 并生成最终的结果或副作用.终端操作是Stream的"触发器", 一旦调用终端操作, Stream就不能再被使用, 也不能再进行中间操作. 2.Stream API 中间操作 2.1 filter(条件) 用于根据指定条件过滤元素.它接收一个条件作为参数, 只保留满足条件的元素, 并生成一个新的Stream.
示例:
存在一个姓名的集合,现在要过滤出来名字中带【大】的人员.
public static void main(String[] args) { List<String> tempList = Arrays.asList("刘一手", "杜子腾", "林大蛋", "Ekko"); List<String> resList = tempList.stream() .filter(s -> s.
报错原因:J-Link固件与J-Link驱动版本不兼容。
常见方法:更换J-Link驱动版本 /或/ 更换J-Link固件版本,意在通过改变这两版本达到最佳兼容性。但问题也很明显,你很难找到匹配的版本,J-Link驱动版本太高依旧用不了,版本太低部分芯片都不再支持,所以可以参考下面的方法操作。
①更新J-Link软件版本 下载地址:SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace
32位系统:把安装文件夹下的“JLink.exe”、“JLinkARM.dll”、“JLinkRDI.dll”拷贝覆盖keil安装目录的“keil”-“ARM”-“Segger”里面对应的文件
64位系统:把安装文件夹下的“JLink.exe”、“JLinkARM.dll”、“JLink_x64.dll”拷贝覆盖keil安装目录的“keil”-“ARM”-“Segger”里面对应的文件,将“JLinkRDI.dll”删除。
这里笔者下载了64位最新版本。
②更新J-Link固件版本 打开J-Link软件包中的“JLinkConfig.exe(不同版本名称不一,大致相同)”,勾选扫描到的产品,点击更新即可。
笔者这里好像并没有更新成功,因为固件版本好像比主机固件新,也没太明白啥意思。
③打开MDK魔术棒,修改Debug的下载速率 速率太大依旧是无法烧写程序,将速率改小即可。
到这里我的问题已经解决了,不知是否能解决你们的问题。
1,先在配置文件中配置Socket监听的端口,由于JDK1.8中已经整合了Socket服务到java.net包中,因此不需要引入其他依赖了 在application.yml中配置下
#Socket配置 socket: port: 8503 2,配置Socket连接类,这一步类似配置一个控制器(Controller),主要用于接收客户端的连接请求,我这里将它写在了控制器类中 package com.linzhuo.app.controller; import com.linzhuo.app.service.IBusinessSocketService; import org.springframework.beans.factory.annotation.Value; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author: jss * Date: 2023/7/25 上午10:58 */ @Slf4j @Component public class SocketServers { //注入被开放的端口 @Value("${socket.port}") private Integer port; //这个是业务处理的接口 @Resource private IBusinessSocketService socketService; @PostConstruct public void socketStart(){ //直接另起一个线程挂起Socket服务 new Thread(this::socketServer).start(); } private void socketServer() { ExecutorService executorService = Executors.
from pycocotools.coco import COCO from pathlib import Path import matplotlib.pyplot as plt import cv2 import os import numpy as np # ============================================================================================ # The following API functions are defined: # COCO - COCO api class that loads COCO annotation file and prepare data structures. # getAnnIds - Get ann ids that satisfy given filter conditions. 用 category id / image id 获取 annotation id # getCatIds - Get cat ids that satisfy given filter conditions.
上一篇:Python tkinter(GUI编程)模块全解(上)_Python zzy的博客-CSDN博客
2 tkinter主模块 2.10 Checkbutton Checkbutton即多选框,用户可以勾选或取消勾选。Checkbutton可以绑定一个variable,一般是BooleanVar。Checkbutton拥有Button的参数之外,还可以有一些别的参数。
参考资料:Python ---(三)Tkinter窗口组件:Checkbutton_近视的脚踏实地的博客-CSDN博客
Checkbutton(master=None, **kw)
参数作用variable与Checkbutton选择相关的Variableonvalue多选框选中时variable的值,默认为1offvalue多选框未选中时variable的值,默认为0selectcolor选择方框的颜色selectimage选中时的图片(须指定image参数)indicatoron是否显示为勾选框样式,默认为True 常用方法: 方法作用select()选中多选框deselect()取消选中选框toogle()切换选框的选中状态(反选选框)invoke()调用Checkbutton的command(disabled无效)flash()使Checkbutton闪烁几次(在normal和active几次切换) 创建Checkbutton from tkinter import * root = Tk() root.geometry("200x200") def tg(): print("选中/取消选中") cb = Checkbutton(root, text="toogle", command=tg) cb.pack() mainloop() 可以尝试点击Checkbutton,左边的方框就会打上勾或取消打勾。每次选择后都会打印"选中/取消选中"。
variable参数 from tkinter import * root = Tk() root.geometry("200x200") def tg(): print("当前状态为:", cb_var.get()) cb_var = BooleanVar() cb = Checkbutton(root, text="toogle", command=tg, variable=cb_var) cb.pack() mainloop() 把多选按钮绑定到一个Var上,这样就可以获取Checkbutton的值。
indicatoron参数 Checkbutton有两种样式,一种是上面的勾选框样式,还可以设置为一个按钮盒的样式。默认是显示为勾选框的样式,如果把indicatoron设置为False也可以设置为按钮的样式。
from tkinter import * root = Tk() root.
系列文章 Cilium 系列文章 前言 在前文中我们提到, cilium install 默认安装后, Cilium 功能启用和禁用情况如下:
datapath mode: tunnel: 因为兼容性原因,Cilium 会默认启用 tunnel(基于 vxlan) 的 datapatch 模式,也就是 overlay 网络结构。KubeProxyReplacement: Disabled Cilium 是没有完全替换掉 kube-proxy 的,后面我们会出文章介绍如何实现替换。IPv6 BIG TCP: Disabled 该功能要求 Linux Kernel >= 5.19, 所以在 Kernel 4.19.232 状态为禁用。BandwidthManager: Disabled 该功能要求 Linux Kernel >= 5.1, 所以目前是禁用的Host Routing: Legacy Legacy Host Routing 还是会用到 iptables, 性能较弱;但是 BPF-based host routing 需要 Linux Kernel >= 5.10Masquerading: IPtables IP 伪装有几种方式:基于 eBPF 的,和基于 iptables 的。默认使用基于 iptables, 推荐使用 基于 eBPF 的。Hubble Relay: disabled 默认 Hubble 也是禁用的。 今天我们尝试关闭 tunnel 功能, 启用本地路由(Native-Routing)功能以提升网络性能.
查看命令 命令解释docker ps查看正在运行的容器docker ps -a查看所有已经创建的容器docker images列出镜像列表docker container ls效果同ps命令(加-a效果同) docker ps 详细参数 -a :显示所有的容器,包括未运行的。 -f :根据条件过滤显示的内容。 --format :指定返回值的模板文件。 -l :显示最近创建的容器。 -n :列出最近创建的n个容器。 --no-trunc :不截断输出。 -q :静默模式,只显示容器编号。 -s :显示总的文件大小。 docker images 详细参数 -a :列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层); --digests :显示镜像的摘要信息; -f :显示满足条件的镜像; --format :指定返回值的模板文件; --no-trunc :显示完整的镜像信息; -q :只显示镜像ID。 删除命令 命令解释docker rm删除容器docker rmi删除镜像 docker rm 详细参数 -f :强制删除一个运行中的容器 -l :移除容器间的网络连接,而非容器本身 -v :-v 删除与容器关联的卷 docker rmi 详细参数 -f :强制删除; --no-prune :不移除该镜像的过程镜像,默认移除 宿-主操作 命令解释docker cp容器与主机之间的数据拷贝 docker cp 实例 docker cp nginx:/www /tmp/ #将nginx容器的/www 拷贝到本地/tmp下 生命周期 命令解释docker start启动容器docker stop停止容器docker restart重启容器docker exec在运行的容器中执行命令docker run创建一个新的容器并运行一个命令 docker exec 详细参数 -d :分离模式: 在后台运行 -i :即使没有附加也保持STDIN 打开 -t :分配一个伪终端 #实例 docker exec -it nginx /bin/bash docker run 详细参数 -i, --interactive=false 打开STDIN,用于控制台交互 -t, --tty=false 分配tty设备,该可以支持终端登录,默认为false -d, --detach=false 指定容器运行于前台还是后台,默认为false -u, --user="
一、引言 什么是OCR?OCR(Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。简单地说,OCR是一种技术,该项技术采用光学的方式将纸质文档中的文字转换为黑白点阵图像,然后通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工。
什么是Tesseract?Tesseract was originally developed at Hewlett-Packard Laboratories Bristol UK and at Hewlett-Packard Co, Greeley Colorado USA between 1985 and 1994, with some more changes made in 1996 to port to Windows, and some C++izing in 1998. In 2005 Tesseract was open sourced by HP. From 2006 until November 2018 it was developed by Google.Tesseract最初是在英国布里斯托尔的惠普实验室和美国科罗拉多州格里利的惠普公司于1985年至1994年间开发的,1996年做了一些更改以移植到Windows,并在1998年进行了一些c++化。2005年,Tesseract被惠普开源。从2006年到2018年11月,它由谷歌开发。简单地说,Tesseract 就是上面OCR所说的“识别软件”的具体实现。
OCR的识别对象(输入)是一张图片,而识别结果(输出)是计算机文字。在Android手机端主要存在两种图片的获取方式,一种是从相册中选择一个,另一个是直接拍照获得。因此,本文将实现最简单的OCR思路:首先从手机中获得一张图片,然后将其输入到Tesseract库,最后通过该库输出识别结果。由于只是学习该库的使用方式,所以博主忽略了其它辅助性的功能,比如拍照识别。
二、Android通过Tesseract实现OCR 1、在Module的build.gradle文件中添加以下依赖 implementation 'com.rmtheis:tess-two:9.1.0' 2、在AndroidManifest.xml文件中添加以下权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="
背景 近十几年来,随着以Android系统为代表的智能手机普及与发展,互联网行业早已进入“移动”的时代。但是现如今的“风口”已经从移动转向,整个移动互联网行业正处于增量下降、存量厮杀的阶段。
面对技术变革、前景不明、竞争激烈的现状,很多开发者们都感到了焦虑与迷茫。在这个大环境下,行业和企业对中高级开发工程师的要求越来越高,而用户对产品质量和体验的要求也越来越高。在这种情况下,我们不能仅仅想着怎么通过面试,更要有一定的技术壁垒,让自己难以替代。
大厂offer是每个技术人的追求 每一个程序员的梦想大概就是能够找一份大厂的 Offer,我觉得这很正常,这并不是我们的饭后谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司/小公司,如果说能够在这样的公司锻炼几年,相信对自己能力的提升还是非常大的。但不是每个人都能够进入大厂的,这往往取决于我们的能力、学历、面试表现等因素。
现在面试大公司你说你没有大型项目开发经验估计都拿不出手,jetpack、NDK、插件化、热修复理论等等已然大厂面试所必须的知识。但是,你真进入大厂了,可能几年都用不上这些知识,还是老老实实去写CRUD。想要一直待在大厂就需要一定的技术竞争力。
为何需要较长时间竞争力的技能 像现在中年技术大咖,你让他们继续跟年轻人一起比敲代码,真敲不过,当然个别有还能敲得很利索的,大部分可能已经无法熟练的使用具体的编程工具和具体的特定算法,跟优秀的年轻人比拼了,但他们知道如何有效的在复杂的系统中发现问题,定位问题,并针对性的给出解决问题的方向,这就是竞争力,这个竞争力,依然可以持续很多年。这样才能一直保持优先级。
长时间竞争力——>>技术壁垒 很多人都会觉得都学一些新的技术,甚至成为全栈程序员。这样的确可以提升一些自身的价值,但是也只是让你在中低端市场受到欢迎。
我们是要解决一些系统底层的逻辑的问题,诸如内存分配的机制,数据结构的原理和设计理念,这才是命脉。
我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。最终形成一定的
技术壁垒
聊到Anroid谈到技术壁垒,就不得不聊聊Framework开发的那些事。
系统应用开发,现在来说,已经开始脱离系统,单独拿出来开发,系统定制接口,已提供给应用调用,用来增强功能。
原生的桌面,拨号,设置,已经没法做出差异化优势,因此都费尽心机,来进行应用深度开发。
对于之前维护系统应用模块的人来讲,修修补补,真的没有什么成长。每天的工作来说,没有很深的技术壁垒,很容易被别人攻陷。
比如设置,比如联系人,在小的改动,修改故障的时候,没有非常高的要求,做过应用开发的,都可以过来参合一脚,改改问题。而让一个应用开发得去修改系统接口,估计改的心累,并且犹豫不决。
技术壁垒,也便是自己的竞争优势。只有顽强的技术能力,并持之以恒的学习,扩充自己的深度,广度,那么你的位置则牢不可破,不会轻易被替代。
技术壁垒形成的就业优势 如应用开发的市场已经饱和,
公司需要开发者能够更深入地理解Android系统,从而能够开发出更加稳定、高效的应用。因此,Android Framework的开发经验在求职过程中变得越来越重要。
垂直领域的智能设备: Android Framework 开发可以针对特定的行业和领域进行定制,以实现更加精准的功能和交互体验。例如,智能家居、智能医疗、智能制造等领域均需要定制化的 Android Framework。
企业级定制化: 一些企业需要为自己的员工和客户定制专属的 Android Framework 应用,以满足其特定的业务需求和安全性要求。这种需求在企业级移动应用中较为普遍。系统优化和升级: Android Framework 开发也可以用于优化和升级系统性能,例如增加系统稳定性、升级系统功能、加强系统安全等。
就目前的就业情况来看,学习Android Framework的市场发展空间还是非常可观,毕竟国内的很多手机大厂,比如华为、oppo、vivo、小米等厂商都需要AF开发,更有其他APP大厂在招聘。
而且直接在招聘网站上看薪资情况,和招聘条件。从中可以看到不管是Android开发还是车载或者视频算法的岗位需要用到framework这项技术。而薪资在同行开发岗位中还处于较上水平14k-30k的区间。
并且,因为大量需要framework方面的人才。所以在大厂面试的时候,我们经常会被问到这些问题:
对Activity的启动流程了解吗?AMS在Android起到什么作用,简单分析下Android的源码system_server为什么要在Zygote中启动,而不是由init直接启动呢?为什么要专门使用Zygote进程去孵化应用进程,而不是让system_server去孵化呢? 能说说具体是怎么导致死锁的吗?Zygote为什么不采用Binder机制进行IPC通信? 大部分Android开发者一遇到这种面试题就直接懵逼了,不少人不是没有看过相关的解答,但也都只是浅尝辄止,没有深入掌握其中原理,面试的时候自然会被问个措手不及。而会framework这方面的人就已经不战而屈人之兵了。
大龄程序员最后的依仗 前面也提到了跟优秀的年轻人比拼,知道如何有效的在复杂的系统中发现问题,定位问题,并针对性的给出解决问题的方向,这是我们最大的依仗
而随着移动互联网的快速发展,Android framework开发成为了一个热门的领域,许多大公司都在招聘这方面的人才。
而framework开发需要的人才基本上都是大龄程序员,因为framework开发需要对系统有深入的理解,而大龄程序员在这方面通常具有优势。
你不要说入行这么多年了,对系统还没有深入的理解。
更重要的是转Android framework开发对于我这些Android人来说是再容易不过了,说是转行但是这个难度要小的多。
关于学习 学习是一直贯穿我们整个程序员职业生涯的,但是很多人总感觉学习没有什么提升,不知道是不是学错了。
学习永远没有错,错的是选择了低效耗时耗精力的前进方向
迷茫的来源有二个,一是看不到自己对公司的价值,二是看不到自己未来发展的路。
先说迷茫的来源一,看不到自身的价值。很多人每天在公司写业务,俗称“搬砖”,每天都搬,感觉一点长进都没有。久而久之你的价值就固定了,公司随时可以让人取代你。
再谈谈迷茫的来源二,看不到未来的路在何方。这个迷茫我觉得来自于对自身的定位不明确。一位老师和我说过,毕业后的头5年,你可以去选择各种开发,前端后端或者移动端,可以随便选。
这是为了什么呢?就是为了找到自己感兴趣的和自己的长处并且打算一辈子一直做下去的方向。
就目前Android 开发而言还有不少人没有找到一个学习方向,或者很多人想了解就是没有这方面的渠道。
为了帮助到大家对framework有一个新的认知,在此分享一份Android Framework源码开发揭秘
由于文档内容过多,因此为了避免影响到大家的阅读体验,在此只以截图展示部分内容,详细完整版的看文末有免费的获取方式!(文末还有使用ChatGPT机器人小福利哦!!大家不要错过)
《Android Framework源码开发揭秘》 本学习手册深入剖析了Android系统源代码,详细讲解了Android框架初始化过程及主要组件的工作原理,旨在通过实例和案例介绍 Android Framework 的核心概念和技术,从而帮助开发者更好地理解 Android 应用程序的设计和开发。 该手册适合具有一定 Android 应用开发经验的程序员,希望能通过深入学习 Android Framework 来帮助开发者更好地理解和掌握这一技术。
2023-3-15: mysql中索引的数据结构,主键索引和普通索引的区别 主键索引和普通索引有什么区别?_主键索引和普通索引的区别_fly_zhaohy的博客-CSDN博客
jvm的内存区域,那些线程共享,那些线程不共享; 说一说jvm的类加载器,双亲委派机制。 造成内存溢出的原因,以及如何解决 以上三个问题请看此篇博客:【JVM】JVM内存模型(详细)_爱穿背带裤的馫的博客-CSDN博客
jvm的垃圾回收机制: JVM之垃圾回收机制(GC)_jvm gc_马小屑的博客-CSDN博客
说一说java中的阻塞队列。 Java 中的阻塞队列_java 阻塞队列_完了学不下的博客-CSDN博客
说一说java中的CopyOnWriteArrayList 线程安全的ArrayList——CopyOnWriteArrayList_copyonwritearraylist线程安全吗_秋枫-沐浠的博客-CSDN博客
说一说平衡二叉树: 平衡二叉树详解 通俗易懂_邓嘉文Jarvan的博客-CSDN博客
TCP/IP的三次握手,四次挥手 TCP 三次握手(Three-way Handshake)是建立 TCP 连接的过程,由客户端和服务器之间交换三个包(Segment)来确认彼此的能力、同步初始序列号(Sequence Number)等信息。具体过程如下:
第一次握手(SYN):客户端发送一个 SYN 包,其中设置 SYN 标志位为 1,同时随机选择一个初始序列号 seq=x。
第二次握手(SYN+ACK):服务器收到客户端的 SYN 包后,如果同意连接,则向客户端发送一个 SYN+ACK 包,其中设置 SYN 和 ACK 标志位均为 1,确认序列号 ack=x+1,并随机选择一个自己的初始序列号 seq=y。
第三次握手(ACK):客户端收到服务器返回的 SYN+ACK 包后,确认序列号 ack=y+1,然后发送一个 ACK 包给服务器,其中设置 ACK 标志位为 1,确认序列号 ack=y+1。
当服务器收到该 ACK 包后,也确认序列号 ack=x+1,并将连接状态设为已连接,至此,TCP 连接建立完成。
TCP 四次挥手(Four-way Handshake)是关闭 TCP 连接的过程,由客户端和服务器之间交换四个包来确认双方已经没有数据需要传输。具体过程如下:
第一次挥手(FIN):客户端发送一个 FIN 数据包,其中设置 FIN 标志位为 1,表示客户端已经没有数据需要发送了,并请求服务器关闭连接。客户端进入 FIN_WAIT_1 状态。
方法1,修改typora文件配置:https://blog.csdn.net/Mao_Jonah/article/details/120533879
方法2,在NVIDIA控制面板中配置typora:https://blog.csdn.net/weixin_54232686/article/details/129770691
一、问题 STM32 I2C 用作从机时,开启如下中断并启用 callback 回调函数。
每一次复位后,从机都可以正常触发地址匹配中断ADDR,之后在该中断的回调函数中启用接收中断去收取数据时,却无法进入RXNE中断,而是触发了 OVR 错误中断。
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) 二、原因 通过简化代码,弃用库函数,改用寄存器操作发现可以正常进入接收中断,发现原来是系统主频太低导致。默认情况下,系统时钟为内部 HSI,仅 8MHz。使用 HSI48 后,便可正常使用库函数方式。
文章目录 👉 前言👉 一、核心代码 : 防抖函数👉 二、Axios封装中的配置👉 三、实现原理👉 结论👉 补充优化: 解决多个接口请求,拦截掉了需要的请求> 防抖函数> 引用位置 往期内容 💨 👉 前言 防抖节流概念: < 性能优化:认识防抖与节流,如何实现呢?它们又有何区别? >
今天这篇文章,主要是讲述对axios封装的请求,由于部分请求可能存在延时的情况。使得接口可能存在会被持续点击(即:接口未响应的时间内,被持续请求),导致重复请求的问题,容易降低前后端服务的性能!
故提出给axios封装的配置里面,新增一个防抖函数,用来限制全局请求的防抖。不过介于部分接口可能存在需要持续请求的情况,所以增加一个参数来判断是否启用防抖函数!
👉 一、核心代码 : 防抖函数 const debounce = (fn, delay, immediate = true) => { // 1.定义一个定时器, 保存上一次的定时器 let timeout = JSON.parse(localStorage.getItem('timeout')) || null // window.console.log(fn, delay, timeout) // 2.真正执行的函数 const _debounce = function() { let context = this; let args = arguments; if (timeout) clearTimeout(timeout); // timeout 不为null if (immediate) { // 第一次会立即执行,以后只有事件执行后才会再次触发 let callNow = !
简介 默认情况下,容器中创建的所有文件都存储在可写容器层中。产生的问题是:
当容器停止后,数据不会持久化,并且如果另一个进程需要该数据,很难从容器中读取。容器的可写层与运行容器的主机紧密耦合,无法简单地将数据移动到其他地方。向容器内写入文件,需要一个存储驱动程序来管理文件系统。与直接写入主机文件系统的数据卷相比,这样会降低性能。 Docker提供了两种方式,让容器将文件存储在主机上,即使容器停止后文件也能持久化:
数据卷绑定挂载点 Docker 还支持容器在主机内存中存储文件。
在 Linux 上运行 Docker,使用tmpfs挂载;在 Windows 上运行 Docker,使用命名管道; 这几种方式,在容器内部看来,是完全一样的。从外部来看如下图所示:
卷 卷是在 Docker 容器和服务中持久化数据的首选方式。
卷存储在由Docker管理的主机文件系统中(在Linux上为 /var/lib/docker/volumes/)。非Docker进程不应修改此文件系统的此部分。
卷由Docker创建和管理。可以使用docker volume create命令显式创建卷,也可以在容器创建时创建卷。
给定的卷可以同时挂载到多个容器中。当没有运行容器使用卷时,该卷仍然可用,并且不会自动删除。可以使用docker volume prune删除未使用的卷。
推荐使用场景
在多个运行的容器之间共享数据。
不能保证 Docker 主机有给定的目录或文件结构时。可以通过卷来与主机的配置解耦。
需要将容器的数据存储在远程主机或云提供商上。
需要从一个 Docker 主机备份、恢复或迁移数据时,卷是更好的选择。直接备份该卷的目录(/var/lib/docker/volumes/)。
需要高性能 I/O 时。卷存储在 Linux VM 中而不是主机中,这意味着读写具有更低的延迟和更高的吞吐量。
需要完全本地文件系统行为时。
例如,数据库引擎需要精确控制磁盘刷新,以保证事务的耐久性。卷存储在 Linux VM 中并可以提供这些保证,而绑定挂载则被转移到 macOS 或 Windows,其中文件系统行为略有不同。
挂载点 绑定挂载可以存储在主机系统的任何位置。包括系统文件。在Docker主机或Docker容器上的非Docker进程可以随时修改它们。
与卷相比,绑定挂载的功能有限。
绑定挂载,是将主机机器上的文件或目录挂载到容器中。需要主机上的文件(目录)的完整引用路径。
绑定挂载非常高效,缺点是要依赖于主机的文件系统是否有这样的目录结构,并且,无法使用Docker CLI命令直接管理绑定挂载。
使用绑定挂载的一个副作用,是可以通过在容器中运行的进程,直接更改主机文件系统,包括创建、修改或删除重要的系统文件或目录。这是一个强大的能力,可能会产生安全影响,包括影响主机系统上的非Docker进程。
一般来说,应该尽可能使用卷。
绑定挂载适用场景
从主机共享配置文件到容器。这是Docker默认提供DNS解析到容器的方式,即将主机机器的/etc/resolv.conf挂载到每个容器中。
在主机上的开发环境和容器之间共享源代码或构建产物。例如,将Maven target/目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问重建的产物。
当主机的文件或目录结构保证与容器所需的绑定挂载一致时。
tmpfs tmpfs挂载在主机或容器内部都不会保留在磁盘上。它可以在容器的生命周期内被容器使用,用于存储非持久状态或敏感信息。例如,Swarm服务使用tmpfs挂载将Secret信息挂载到服务的容器中。
适用场景
不希望数据在主机或容器内持久化的情况。例如:安全原因;当应用程序为了容器性能,需要写入大量非持久状态数据时。 命名管道 npipe挂载可用于Docker主机和容器之间的通信。
一、关于Dockerfile
1.Dockerfile介绍
官网中的介绍: Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image。
Dockerfile 是一个文本文件,里面包含组装新镜像时用到的基础镜像和各种指令。
使用dockerfile 文件来定义镜像,然后运行镜像,启动容器。
2.Dockerfile文件的组成部分
一个dockerfile文件包含以下部分:
基础镜像信息: 使用FROM关键字指定基础镜像信息,FROM是dockerfile文件的第一条指令。维护者信息: 使用MAINTAINER关键字指定,通常可以使用dockerfile文件创建者的名字或者邮件作为维护者的信息。镜像操作指令: 没执行一条镜像操作指令,都会在镜像中添加新的一层。容器启动执行命令: 用户指定在启动容器时需要执行的命令,通过:CMD ENTRYPOINT指定 常见的镜像操作指令:
指令描述FROM# 基础镜像,一切从这里开始构建MAINTAINER镜像是谁写的,姓名+邮箱RUN镜像构建的时候需要运行的命令ADD添加内容: 比如加一个tomcat压缩包WORKDIR镜像的工作目录VOLUME镜像挂载的目录EXPOSE保留暴露的端口CMD指定这个容器启动的时候要运行的命令,只有最后一个会生效,可以被代替ENTRYPOINT指定这个容器启动的时候需要运行的命令,可以追加命令ONBUILD当构建一个被继承DockerFile 的时候就会运行 ONBUILD 的指令。触发指令COPY类似ADD ,将我们的文件拷贝到镜像中ENV构建的时候设置环境变量 3.Dockerfile的执行
在完成dockerfile文件的编写后,执行docker build命令,则会根据dockerfile文件中上下文的内容构建新的docker镜像。
整个构建过程会被递归处理,如果在dockerfile中包含了路径或者URL,都会被递归构建。
二、Docker bulid命令介绍
docker build 命令用于使用 Dockerfile 创建镜像
在MySQL数据库中删除数据后,如果没有备份数据库或开启数据恢复功能,恢复数据可能会比较困难。以下是一些可能的方法来尝试恢复删除的数据:
备份恢复: 如果你有数据库的备份文件,在删除数据之前的备份中可以找回被删除的数据。将备份文件导入到数据库中即可恢复数据。
二进制日志: MySQL数据库会记录所有的数据更改操作到二进制日志中,如果你开启了二进制日志功能,可以查找删除操作的记录并通过恢复这些操作来还原数据。
事务回滚: 如果删除数据的操作在一个事务中进行,并且未提交事务,可以使用回滚操作将数据恢复到删除前的状态。
数据库恢复工具: 有一些第三方数据库恢复工具可以帮助恢复误删除的数据。这些工具通常会扫描数据库的物理文件并找回被删除的数据。
值得注意的是,对于大部分情况,删除的数据是无法100%恢复的,尤其是在数据已经提交、事务已经关闭并且没有备份的情况下。因此,为了防止数据丢失,建议在执行删除操作前做好数据备份,确保有可靠的数据恢复手段。
另外,为了防止误删数据,可以在生产环境中限制删除操作的权限,并在开发和测试环境中执行删除操作时谨慎确认,以避免误操作导致数据丢失。
题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个
整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
答案 static int[] twoSum(int[] nums, int target) { int[] result = {0,0}; HashMap<Integer,Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int re = target - nums[i]; if (map.containsKey(re)){ return new int[]{map.get(re),i}; } map.put(nums[i],i); } return result; }
题目描述 给你一个字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
字母区分大小写,因此 “a” 和 “A” 是不同类型的石头。
示例 1:
输入:jewels = “aA”, stones = “aAAbbbb”
输出:3
示例 2:
输入:jewels = “z”, stones = “ZZ”
输出:0
提示:
1 <= jewels.length, stones.length <= 50
jewels 和 stones 仅由英文字母组成
jewels 中的所有字符都是 唯一的
答案 int numJewelsInStones(String jewels, String stones) { int mun = 0; List<String> list = new ArrayList<>(); for (char j : jewels.toCharArray()) { list.add(String.valueOf(j)); } for (char s : stones.
一、游戏规则 游戏玩家将会看到屏幕上显现一个 3*3 的网格棋盘,系统默认玩家先下棋,电脑后下棋。
规定:先连成一条直线(3 个棋子)的玩家获胜,直线是行,列,对角线均可。若在棋盘下满时仍未分出胜负,则结果为平局。
二、文件的创建 test.c(实现游戏的整体思路,用于测试三子棋游戏的逻辑)game.c(游戏的实现)game.h(声明 .c 文件的函数,包含所有需要用到的头文件以及 define 定义的常量) 注:如果原文件和头文件名字一样,则表示代表同一个模块。
三、初始页面的实现 1、实现主菜单页面 // test.c
(1)menu() void menu() { printf("*****************************\n"); printf("***** 1.Play 0.Exit *****\n"); printf("*****************************\n"); } 运行效果图: (2)test(): void test() { int input = 0; srand((unsigned int)time(NULL)); do { menu();// 主菜单 printf("请选择:>"); scanf("%d", &input);// 玩家选择 switch (input)// 判断玩家是否进行游戏以及是否输入合法选项 { case 1: game();// 游戏 break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择!\n"); break; } } while (input); } 注:这里使用 do while() 循环可以保证至少会进行一次选择。如果选择 0,会被判定为假,则跳出循环,退出游戏;如果输入选择则不会退出游戏,可以1保证游戏能够重复游玩。
与Windows相比,Mac上的软件,不仅不稀缺,并且大多数都更加精致,还没有乱七八糟烦人的弹窗骚扰!所以,本期就为大家盘点一下2023年Mac上超好用的10款软件神器!
1、Downie 4 https://www.downie.cn/
支持平台:Mac
主要功能:下载视频
非常好用的视频下载软件,支持多达1000多个网站,包括bilibili、抖音、youtube、西瓜视频、快手、instagram、Facebook等国内外主流互联网。软件自带的搜索功能,可以直接搜索到视频网站的视频,然后一键将视频下载到本地。并且下载的时候可以选择视频清晰度,下载速度非常快,让工作效率大大提高。
2、GitMind https://gitmind.cn/
支持平台:Mac/Win/iOS/Android
主要功能:思维导图制作、各类流程图制作
非常好用的一款全平台思维导图软件,支持流程图、思维导图、鱼骨图、UML、网络拓扑图、组织架构图等图形的快速绘制。对于整理思路、记笔记、做框架等有逻辑的事物都非常有帮助,并且可以在手机、ipad和电脑等设备上随时随地同步数据,支持团队成员实时协作编辑思维导图,有演说模式,而且做出的思维导图可以导出为图片、pdf、Word文件等多种格式,日常办公必备~
3、Final Cut Pro X Final Cut Pro for Mac - Apple (SG)
支持平台:Mac
主要功能:剪辑视频
Final Cut Pro X是苹果公司开发的一款高效的视频剪辑软件,不管是电影制作,还是视频编辑都非常适用。软件提供了先进的剪辑工具、多轨道编辑、色彩校正,以及各种特效和过渡效果,让你分分钟能够制作出专业水准的视频作品。
4、AlDente Pro AlDente - AppHouseKitchen
支持平台:Mac
主要功能:电池管理
AlDente Pro 是一款专为 MacBook 打造的充电管理工具,它可以读写 MacBook 内置 SMC 芯片,即使你的 MacBook 一直连接电源线,AlDente也会根据设定在电脑内部自动接通和切断电源,这样就可以在必要的时候接通或者断开电源,从而避免电池彻底耗尽,或者长期处于过充状态。
AlDente 最主要的功能就是调整电池充电阈值。在电池电量在达到指定值后,电脑会停止充电,转向电池供电,全过程无需手动插拔 MacBook 充电器。通过软件控制充电量的上限和电池状态,即使在接通电源的情况下,也能让电池电量保持在 80% 左右,有益于电池健康。
5、CleanMyMac X CleanMyMac X: 让您的 Mac 迅捷如新
支持平台:Mac
主要功能:系统清理
CleanMyMac X 是一款专业的 macOS清理软件,它可以帮你清理、加速、优化和保护系统。主要包括清理系统垃圾、恶意软件、卸载不再使用的软件,管理启动项、大型文件查找等 30 多种工具来帮助解决最常见的 Mac 问题。
◼️ webpack.config.js文件没有的原因 Vue 项目中 vue.config.js 文件就等同于 webpack 的 webpack.config.js。
vue-cli3 之后创建的时候并不会自动创建 vue.config.js,因为这个是个可选项,所以一般都是需要修改 webpack 的时候才会自己创建一个 vue.config.js。
vue-cil3之后创建项目后的目录结构如下:
├── README.md # 说明 |-- dist # 打包后文件夹 ├── babel.config.js # babel语法编译 ├── package-lock.json ├── public # 静态文件夹,这类资源将会直接被拷贝,而不会经过 webpack 的处理。 │ ├── favicon.ico │ └── index.html #入口页面 └── src # 源码目录 ├── App.vue - 页面 ├── assets - 静态目录,这类引用会被 webpack 处理。 │ └── logo.png ├── components 组件 │ └── HelloWorld.vue └── main.js # 入口文件,加载公共组件 │—— vue.
之前因为使用的springboot版本比较低,另一个工具版本比较高,两者共同的依赖jakarta版本就一直报错:
报错ClassNotFoundException:jakarta.xml.bind not found
解决办法:
重新单独引入jakarta包: <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> 这时候我jakarta的版本就是2.3.0了,如果有其他地方引入了不同版本的,记得exclusions排除一下但是我又报错ClassNotFoundException:javax.xml.bind not found,于是又引入了包: <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>com.sun.activation</groupId> <artifactId>jakarta.activation</artifactId> <version>2.0.1</version> </dependency> 我这里遇到这个问题的原因在于,我引入的工具版本比较高,需要jakarta开头的包,但是springboot版本又是需要javax开头的包,所以把这俩都自己手动引入即可。
进入环境后有三个路径链接 访问/flag提示会说flag在/fllllllllllag里
值得注意的是访问后网页url发生的变化,这里居然有两个参数
替换掉filename的值后页面url再次发生变化,网页只有一个msg传参的数据
访问welcome.txt,只是回显了一个render,百度了一下,出来了几段模版注入的文章,就想到了之前学习flask模版注入里的,render_template渲染函数
最后查看了一下wp,果然是模版注入。不过不是Python flask,而是Tornado,是另外一种Python模版,没学
最后访问一下hints.txt,出现了一个MD5算法,filename我们知道,只不过这个cookie_secret,需要了解一下
那说明URLfilehash参数就是上面算法MD5加密后的字符串,那我们只要得到cookie_secret,就可以经过算法得到flag
cookie_secret简介 普通的cookie并不安全,可以通过客户端修改
在Tornado框架中,cookie_secret是一个密钥,一般使用随机生成的字符串,被用于对生成的cookie进行加密。它的作用是确保cookie的安全性,防止被修改或伪造。
具体来说,当Tornado应用程序使用set_secure_cookie()函数设置cookie时,会使用cookie_secret对cookie进行加密。而在获取cookie时,Tornado则会使用同样的密钥进行解密,并验证cookie是否被篡改。如果cookie_secret不匹配,Tornado将不会对其进行解密,并抛出异常,以防止未经授权的访问。
handler.settings 以下是gpt的答案,因为还没有学过这个模版相关的知识,所以直接复制来的
`handler.settings`在Tornado框架中是一个字典,用于存储应用程序的各种配置选项。其中包括一些默认的配置选项,也可以自定义添加其他配置选项。
在Tornado框架中,`cookie_secret`是`handler.settings`字典中用于配置cookie密钥的一个选项。Cookie密钥是用于加密和验证cookie的字符串,它应该是一个随机且足够长的字符串,用于保证cookie的安全性和完整性。
解题步骤 说明我们可以利用handler.settings,去访问一些配置,就能得到cookie_sercret的键值对,这样我们就可以通过hints文件提供的算法,求得filehash的值 需要注意的是一定要按照顺序进行字符串拼接,否则出来的MD5值会有所差别
import hashlib filename = '/fllllllllllllag' cookie_secret = '139f115c-818e-4821-9f5a-c88ae4f19a06' filename = hashlib.md5(filename.encode()).hexdigest() a = cookie_secret + filename filehash = hashlib.md5(a.encode()).hexdigest() print(filehash) 至此也就做出来了,这个cookie_sercret的值是动态的,后面还要补充模版知识
文章目录 前言一、SSH免密登录配置1.安装GIt2.生成SSH3.配置 SSH key4.验证SSH key是否配置成功 二、创建远程仓库1.登录自己的Gitee账号2.创建远程仓库 前言 我这里使用的是vuecli创建的项目进行代码管理,使用的平台是Gitee。
平台的话其实最推荐使用的平台还是GitHub(但是因为国内连接不稳定的原因放弃使用),因为GitHub有个功能可以直接将你的项目在仓库中跑起来,这个是别的平台都没有的,希望以后我们的平台也可以做到这种程度。
一、SSH免密登录配置 SSH key 的作用:实现本地仓库和 Github 之间免登录的加密数据传输。 SSH key 的好处: 免登录身份认证、数据加密传输。
SSH key 由两部分组成,分别是:
id rsa(私钥文件,存放于客户端的电脑中即可)id rsa.pub (公钥文件,需要配置到 Gitee 中) 1.安装GIt https://git-scm.com/
直接Install就可以了
2.生成SSH 进入直接项目的根目录,在空白的地方右键,打开Git Bash
我用的是Vscode中内置的终端,直接ctrl+~就可以打开了,但是注意目录需要在项目根目录下
cd (文件名) 根目录下ls就可以看到
此时需要注意一个文件.gitignore
这个文件是git的配置文件,如果没有可以使用touch .gitignore生成,我是使用vuecli创建的,所以有自带并且配置好了,我这边给个默认配置
.DS_Store node_modules /dist # local env files .env.local .env.*.local # Log files npm-debug.log* yarn-debug.log* yarn-error.log* pnpm-debug.log* # Editor directories and files .idea .vscode *.suo *.ntvs* *.njsproj *.sln *.sw? 这当中的文件代表,在git add 时不会去跟踪这些文件尤其是依赖文件node_modules这个文件是项目中占用最大的,这个文件是不需要去跟踪的,所以需要屏蔽,*.
1.运行创建项目命令 # 使用 npm npm create vite@latest # 使用 yarn yarn create vite # 使用 pnpm pnpm create vite 注:Vite 需要 Node.js 版本 >= 12.0.0
2.填写项目名称 3.选择框架,我选择了vue 4.选择使用的类型,在这里我选择我了js 5.项目创建完成,依次执行以下命令 6.运行成功
cell为mtalab提供的一种数据类型。
语法:x=cell(m,n) 表示创建m*n的cell类型数据。每个单元都是独立的,可以存储任何数据。
x=cell(2,3) x{1,1}=[1,3,4,5,6] x{1,2}=['J','e','r','r','y'] x{1,3}=50 x{2,1}=[4 5;6 7] x = 2×3 cell 数组 [1×5 double] 'Jerry' [50] [2×2 double] [] [] 访问:x{1,1}表示x的1行1列单元中的数据
>> x{1,1} ans = 1 3 4 5 6 >> x{1,2} ans = 'Jerry' 引用cell单元时要用{},再引用矩阵的某个数据就要用()了。
如果用第四个单元中矩阵中的某个元素,x{2,1}(1,2)表示矩阵的元素5
需求背景 想在Ubuntu22.04上搭建一下Lua的开发环境,其实步骤比较简单的,此文章也适用于Ubuntu主机环境搭建Lua,如果想在在Ubuntu内部署一个容器,然后在容器内搭建Lua的环境,可以先参考容器的创建过程 ubuntu22.04上如何创建有privilege权限,有固定自定义IP的空容器,然后再根据此文章的部署步骤搭建
创建Lua解释器源码存放目录 mkir -p /root/dev_env
创建Lua的安装目录 mkdir -/ /usr/cloudland/lua
安装下载工具及编译工具 apt-get install wget make gcc
下载解压Lua解释器源码包 cd /root/dev_env
wget www.lua.org/ftp/lua-5.4.6.tar.gz
tar -zxvf lua-5.4.6.tar.gz
修改Makefile,重新设置安装目录
将INSTALL_TOP=/usr/local更改为INSTALL_TOP=/usr/cloudland/lua,退出保存
编译安装 make linux
make install
设置Lua环境变量 vi /root/.bashrc
在最后添加
export LUA_HOME=/usr/cloudland/lua
PATH=$PATH/bin:$LUA_HOME/bin
export PATH
source 一下Lua环境变量
source /root/.bashrc
验证 lua -v
1 一个文件引用另一个文件全局变量2 在定义点之前的函数想引用该全局变量3 c语言中extern关键字3.1 Example 1:3.2 Example 2:3.3 Example 3:3.4 Example 4:3. 5 Example 5:3.6 总结 4 C++导入C函数 extern "C"5 其他相关文章 我们知道,程序的编译单位是源程序文件,一个源文件可以包含一个或若干个函数。在函数内定义的变量是局部变量,而在函数之外定义的变量则称为外部变量,外部变量也就是我们所讲的全局变量。它的存储方式为静态存储,其生存周期为整个程序的生存周期。全局变量可以为本文件中的其他函数所共用,它的有效范围为从定义变量的位置开始到本源文件结束。
1 一个文件引用另一个文件全局变量 如果整个工程由多个源文件组成,在一个源文件中想引用另外一个源文件中已经定义的外部变量,只需在引用变量的文件中用 extern 关键字加以声明即可
举例
test1.cpp
#include<stdio.h> int kpi = 100; int getmax(int a, int b) { return a > b ? a : b; } test2.cpp
#include<stdio.h> int main() { extern int kpi;//外部变量申明 extern int getmax(int a, int b);//外部函数申明 int i = 0; i = kpi; printf("