个人经历口水话 一直换过来换过去,尝试各种配置,修改,突然它能够正常显示到html页面去了,困扰了我一整天的问题突然不知怎么解决了,让我有点懵,但是我又好奇到底是怎么回事,于是开始找到这个原因,以便后面的人不要走我的老路
有三种问题可以通过这种方式进行改变:
1、它报找不到那个templates下面的文件
2、也是标题所说的那个model传值后,html中无法获取对应的值
3、controller的return 进行跳转对应的html页面 不用写全称,如等会儿下面的controller中
return "test"; 即可访问test.html 的页面 不用再加上后缀写全称。
上面的这三种问题均可以通过改变依赖来解决(或者说你的依赖导错了版本)
问题描述 现象描述:
首先是controller中的内容,注意里面有个System.out.println() 通过打印控制台信息来测试是否执行到了这儿,且多个System.out.println()可查看问题具体出现在哪儿,如下图:
下面是test.html中通过thymeleaf的方式对存储在model中的值进行访问(此时可以看到msg还被标红色下划线了,说明有问题)
然而运行工程,是暂时为发现问题:
然后我通过网页访问,出现了下面的结果(当时的时间已经是凌晨了,我测试了很久,找了很久的问题原因,所谓的控制变量法找原因是真的麻烦):
404找不到页面,且地址栏中的url并没有改变,变为test.html什么的,但是控制台却打印了System.out.println()中的内容(直到return语句为止都是正常运行的),且控制台无报错:
说明能够通过地址栏访问到对应的controller函数,直到return返回前都运行 return原本应该跳转到对应页面,但是未执行(或者说是返回的内容未被程序正常解释)
好了,上面就是整个问题的毛病
解决方法 我找到了我当前的pom.xml 文件中的thymeleaf依赖,如下:
此时是导入的thymeleaf的依赖,通过我写的注释,应该也知道了,我上面出现的问题 就是依赖使用错了,虽然都是thymeleaf的依赖,但他们还是有不同之处,具体怎么个不同,我现在也说不清,上面两个的注释内容也只是我通过控制变量法,总结出来的,所谓实践出真知
然后修改上面的thymeleaf依赖:
记得点击右上角出现的图标,对工程导入的依赖进行更新
细节一:重新查看那个test.html中的使用thymeleaf的msg已经没有了红色的下划线
然后重新运行工程:
控制台无任何问题正常运行:
通过网页访问try(成功将model中的值读取出来):
恭喜自己到这儿成功解决
附录: 这儿把test.html 和那个controller的程序代码给你们,可直接复制用于测试:
test.html:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>网页测试1</title> </head> <body> <p th:text="${msg}"></p> <h1 th:text="测试通过"> 测试测试 </h1> <input type="text" th:value="${msg}"> </body> </html> controller程序 (Package需要根据自己的工程改变):
package com.qc.qc_blog.controller; import org.springframework.stereotype.Controller; import org.
网络模块需要在.pro文件中添加 QT += network QHostInfo 利用操作系统提供的查询机制来查询与特定主机名相关联的主机的 IP 地址
头文件:#include<QHostInfo>
//获取本机的名称 QString loaclHostName = QHostInfo::localHostName(); qDebug()<<"本机名称为:"<<loaclHostName; QHostAddress类提供一个IP地址。 这个类提供一种独立于平台和协议的方式来保存IPv4和IPv6地址。
头文件:#include<QHostAddress>
//通过本机名获取本机对象 QHostInfo info = QHostInfo::fromName(loaclHostName); //获取所有的IP地址 QList<QHostAddress> allAddresslist = info.addresses(); foreach(QHostAddress address, allAddresslist) { //协议为IPv4时 if(address.protocol() == QAbstractSocket::IPv4Protocol) { qDebug()<<"IP地址为:"<<address.toString(); } } QNetworkInterface类提供了程序所运行时的主机的IP地址和网络接口信息的列表。在每一个网络接口信息中都包含了0个或多个IP地址,而每一个IP地址又包含了和它相关的子网掩码和广播地址,它们三者被封装在一个QNetworkAddressEntry对象中。
头文件:#include<QNetworkInterface>
QList<QNetworkInterface> list = QNetworkInterface::allInterfaces(); //遍历每一个网络接口 foreach(QNetworkInterface interface,list) { qDebug() << "设备名: "<<interface.name(); qDebug() << "硬件地址: "<<interface.hardwareAddress(); //获取IP地址条目列表,每个条目中包含一个IP地址,一个子网掩码和一个广播地址 QList<QNetworkAddressEntry> entryList = interface.addressEntries(); //遍历每一个IP地址条目 foreach(QNetworkAddressEntry entry,entryList) { qDebug()<<"IP地址: "<<entry.ip().toString(); qDebug()<<"
#vue# 本地电脑如何配置host文件? (1)host概念 在进行请求接口之前,我们需要先配备好host
Hosts:它是一个没有扩展名的系统文件,
而它的的基本作用,就是将一些我们个人常用的网址和相对应的IP地址建立一个关联“数据库”
所以,当我们(也就是用户)在浏览器输入一个需要我们登录的网址时,
我们的计算机系统会首先自动的从Hosts文件中寻找对应的IP地址
如果一旦找到对应的IP地址,
我们的系统将会立即打开对应的网页,
如果没有找到,这时候系统将会把网址,
交给DNS域名解析服务器进行IP地址的解析
(2)host5大特点 加快域名解析方便局域网用户屏蔽网站顺利连接系统虚拟域名 本机电脑的网址指向是为localhost,port: 8080(端口) ,
但是在实际的开发里面,
我们服务的项目往往不止一个,
如果有其它的项目,就会按照顺序:port: 8081(端口)、port: 8082(端口)、
port: 8083(端口)、port: 8084(端口)…
那这样的话,就会很乱!!
所以针对这种情况,我们最好就是重新配置一下域名以及端口,方便自己查看,
也方便其它协助者一起开发项目的时候,可以拿到你电脑的数据
步骤如下:
在vue目录里面,config----index.js文件里
找到host
然后,自定义域名和端口
在XP 、win7、win10系统中,
在系统盘输入以下路径,
C:\Windows\System32\drivers\etc 找到HOST文件,
(如果进去没有看到Hosts文件,是因为某些系统将Host文件隐藏了)
然后将同事给的域名和地址,
进行粘贴到里面就可以了
格式:
1436.00.10(这个是同事电脑地址) rteryryrutuyyrty.nen.edb.cn(这个是域名)
这样就映射到同事的电脑了
访问rteryr45yrutuyyrty.nen.edb.cn,
即系等同于访问1453455336.00.10
温馨提示:这个域名也是我们后期数据请求时,拼接域名地址时,同样会使用到的
具体可以查看#vue# 超级详细步骤!vue项目封装网络请求接口思路及方法
里面的第三步
【www.gywlwh.com--百科大全】
计算器也能够弹奏出美妙动听的音乐,那么今天给大家分享一下关于计算器弹奏简谱音乐有哪些,本站今天为大家精心准备了计算器弹歌曲谱子,希望对大家有所帮助!
计算器弹歌曲谱子
粉刷匠 5353531 24325 5353531 24321 2244325 24325 5353531 24321
小星星 1155665 4433221 5544332 5544332 1155665 4433221
用计算器弹《夜空中最亮的星》
教程:5+9888865x÷÷ 89+xx89 888865x÷÷ 889+xxx+9 +9888865x÷÷ 889+xxx+9 9+88886÷÷ 89+xx89
计算器弹歌曲谱子
1、体面
89+89+8×× ×+98 8678 6++ +765 8678×÷× ×+8 9+6 ++++98+ 89+89+ 8×× ×+98 8678 5++9+×8 8678 5÷×7 ++86 +678
2、成都
6888 68996 54 4566 68 8689 996 54 1564 124 4 55 86 689 8 98 56 45 4542 565 45555698
1、Intel平台笔记本:
进入BIOS,选择 Configuration 选项,找到 Intel Virtual Technology,改成Enable。
2、AMD平台笔记本:
进入BIOS,选择 Configuration 的选项,找到 SVM Support,改成Enable。
3、商用笔记本(按F1进入bios的VBKEM系列):
按F1进入BIOS选择【Security】-【Virtualization】 ,设置为Enabled。
4、Intel平台的台式机:
按F1进入BIOS选择【Advanced】-【CPU Setup】 ,选择【Intel(R)Virtualization Technology】设置为Enabled。
原文链接:https://mclub.lenovo.com.cn/showarticle/11341?ivk_sa=1024320u
☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░ 一、引言 老猿对图像处理基础知识非常缺乏,所以OpenCV-Python的学习进度很慢,很多基础概念和原理的东西花了大量精力去研究和学习,如前面图像的形态变换、最近的仿射变换和投影变换等。
目前正准备学习图像的滤波处理,但图像怎么能进行滤波了?难道图像是波吗?经过多天查阅资料加上自己的理解,个人觉得自己终于理解了图像滤波的概念,在此将相关知识整理分享出来,供类似老猿这样的图像处理小白参考。
二、滤波器 学过物理等课程的人就对滤波器(filter)有印象,滤波器是用于过滤掉不符合要求的波形,有低通滤波器、高通滤波器、带通滤波器等类型,广泛用于声波、光波、电磁波等处理领域。
低通滤波(Low-pass filter) 是一种过滤方式,规则为低频信号能正常通过,而超过设定临界值的高频信号则被阻隔、减弱。但是阻隔、减弱的幅度则会依据不同的频率以及不同的滤波程序(目的)而改变,它有的时候也被叫做高频去除过滤(high-cut filter)高通滤波器,又称低截止滤波器、低阻滤波器,允许高于某一截频的频率通过,而大大衰减较低频率的一种滤波器。它去掉了信号中不必要的低频成分或者说去掉了低频干扰带通滤波器(band-pass filter)是一个允许特定频段的波通过同时屏蔽其他频段的设备 三、图像与波 图像滤波器借鉴了滤波器的概念,这其中有个背景知识,就是图像也是波。为什么这么说呢?
这是因为如下2个原因:
对于图像的每行像素的每个通道值来说,所有像素点同一通道值构成一条曲线。以灰度图为例,其像素值为单通道的灰度值,灰度值的变化表示图像灰度的变化,这种变化就是一个波形曲线。而对于三通道的彩色图像,每行像素对应三条波形曲线。 一个图像有n行,就代表有n×c条波形曲线,其中的c代表通道数。当图像色彩或灰度和明度变化很平滑时,图像对应的所有波形曲线的起伏很小,但当图像出现色彩或灰度或明度变化大时,就存在某些对应的波形曲线起伏大。除了少数的计算机合成数字图像外,大部分产生图像的能源(具体请见《冈萨雷斯《数字图像处理》学习总结及感悟:第一章 绪论 百闻不如一见》的介绍)都是电磁波、声波或电子束,它们都可用波来表示。 因此图像每行像素通道波动与图像是紧密关联的。图像本质上就是各种色彩波的叠加,可以说图像就是色彩的波动:波动大,就是色彩或灰度突变;波动小,就是色彩或灰度平滑过渡。因此,波的各种指标可以用来描述图像。
另外,波动是否变化频繁可以用频率来表示,频率(frequency)是波动快慢的指标,单位时间内波动次数越多,频率越高,反之越低。所以,色彩/灰度值变化频繁的地方,就是图像的高频区域;色彩/灰度值稳定平滑的地方,就是图像的低频区域。
更具体介绍大家可以参考《转载:图像滤波概念知识解释》的介绍。
四、图像噪声 4.1、概述 噪声在理论上可以定义为“不可预测,只能用概率统计方法来认识的随机误差”。数字图象的噪声主要来源于图象的获取(数字化过程)和传输过程。
一般情况下图像的变化比较平滑,但由于成像系统、传输介质和记录设备等的不完善,数字图像在其形成、传输记录过程中往往会受到多种因素的干扰出现不应该出现的噪点(借鉴声波概念称为噪声)。另外,在图像处理的某些环节当输入的图像对象并不如预想时也会在结果图像中引入噪声。
图像噪声是指存在于图像数据中的不必要的或多余的干扰信息,是妨碍人们对图像信息认知的因素。图像噪声在图像上常表现为引起较强视觉效果的孤立像素点或像素块,对于数字图像信号,图像中的噪点表为或大或小的极值,这些极值通过加减作用于图像像素的真实灰度值上,对图像造成亮、暗点干扰,极大降低了图像质量,影响图像复原、分割、特征提取、图像识别等后继工作的进行。
4.2、图像噪声分类 4.2.1、加性噪声、乘性噪声和量化噪声 根据噪声和信号(图像波)之间的关系,可以将噪声分为加性噪声、乘性噪声和量化噪声。
加性噪声:
加性噪声与信号的关系是相加,不管有没有信号,该类噪声是一直存在的。假定信号为S(t),噪声为n(t),如果混合叠加波形是S(t)+n(t)的形式,则称其为加性噪声。加性嗓声和图像信号强度是不相关的,如图像在传输过程中引进的“信道噪声”电视摄像机扫描图像的噪声等。一般把加性噪声看成是系统的背景噪声。
乘性噪声:
乘性噪声则与信号强度有关,往往随图像信号的变化而变化,如飞点扫描图像中的嗓声、电视扫描光栅、胶片颗粒造成等。
乘性噪声一般由信道不理想引起,它们与信号的关系是相乘,信号在它在,信号不在它就不在。
乘性噪声看成系统的时变性(如衰落或者多普勒)或者非线性所造成的。
量化噪声:
图像中的量化噪声是图像在量化过程中图像从模拟到数字所产生的差异,是图像量化过程中的误差。
在图像处理等技术里取得采样值后,要对数据进行量化。量化后的数值与原来的采样值是有误差的,这个数值就是量化精度。量化精度越高,量化值与采样值之间的误差就越小,所采集的数据更能真实的反应实际情况。量化精度所采集到的数据与原始图像越近似。
在将量化数据还原成图像时,这种量化过程存在的量化误差会作为噪声再生,称为量化噪声。
在老猿查找的资料中,大多只介绍了加性噪声和乘性噪声,有少量介绍量化噪声的,但没有清晰地说明三者之间的关系。从三者的定义来看,老猿理解为三者是并列的,加性噪声与图像采集设备和传输设备相关,乘性噪声与图像的展示过程相关,而量化噪声与从模拟图像到数字图像的量化过程相关。
4.2.2、其他噪声分类 除了按信号和噪声的关系将噪声分类外,还有多种分类方式:
按噪声幅度随时间分布形状来定义,从噪声的概率分布情况来看,可分为高斯噪声、瑞利噪声、伽马噪声、指数噪声、脉冲噪声、均匀噪声
说明:平时提及比较多的椒盐噪声是脉冲噪声(impulsive noise)的一种,脉冲噪声是非连续的、由持续时间短和幅度大的不规则突发性干扰脉冲或噪声尖峰组成,通常将在所有出现的离散型噪声统称脉冲噪声。脉冲噪声的幅值基本上相同,但是噪声出现的位置是随机的。
噪声脉冲可以是正的,也可以是负的。因为脉冲干扰通常大于图像信号的强度,因此,在一幅图像中,脉冲噪声总是数字化为最小值(纯黑)或最大值(纯白)。负脉冲以一个黑点(胡椒点)出现在图像中,正脉冲以白点(盐点)出现在图像中。因此这种双极脉冲噪声又称为椒盐噪声。
按噪声频谱形状来命,如频谱均匀分布的噪声称为白噪声;频谱与频率成反比的称为1/f 噪声(为低频区域噪,也称闪烁噪声,像一道闪烁的烛光,在示波器上使用慢扫描来观察1/f噪声可以看到一条漂移的基线);而与频率平方成正比的称为三角噪声等等
根据经常影响图像质量的噪声源又可分电子噪声和光电子噪声
五、小结 本节介绍了图像处理中图像与波的关系,由于图像灰度值或通道值在各位置的值联合起来看象波,同时数字图像的成像的辐射源也是各种波,因此图像处理和波关系密切,滤波处理其实就是对图像的各像素的灰度值或通道值幅度的处理。
图像采集、传输和量化过程中会产生各种噪声,图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。图像噪声的有多种分类方法,在不同处理中会用到不同分类方法。
更多图像处理请参考专栏《OpenCV-Python图形图像处理》及《图像处理基础知识》的介绍。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《 专栏:Python基础教程目录》从零开始学习Python。
写博不易,敬请支持: 如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
关于老猿的付费专栏 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.
树形dp就是在树上进行的dp。由于树具有递归的性质,因此树形dp一半都是用递归的方式进行的。
问题的大意是,选了父节点,那么它的直接子节点就不能被选择,求总的权值的最大值。
题目:P1352 没有上司的舞会
这题是树形dp的板子题,每个节点都有被选择和不被选择两种情况。
用数组dp[n][0]记录第n个节点不被选择的情况,用数组dp[n][1]记录被选择的情况。
那么就有状态转移方程
dp[n][0] = Σ(max(dp[x][0],dp[x][1]),其中,x是n的所有子节点
dp[n][1] = a[n] + Σ(dp[x][0])
然后总的权值和的最大值就是 max(dp[root][0],dp[root][1])
下面给出代码实现:
#include <bits/stdc++.h> using namespace std; #define MAXN 6006 typedef long long ll; int r[MAXN]; int n; //采用链式前向星的方式存储树 struct edge { int u, v, next; } e[4 * MAXN]; int head[MAXN]; int js_edge = 0; void add_edge(int u, int v) { js_edge++; e[js_edge].u = u; e[js_edge].v = v; e[js_edge].next = head[u]; head[u] = js_edge; } ll dp[MAXN][2]; bool vis[MAXN] = {false}; void dfs(ll u) { vis[u] = true; dp[u][1] = r[u]; for (int i = head[u]; i !
在Linux中有很多方法可以删除目录,在图形化界面可以利用文件管理器,或者通过终端删除。本文将介绍在文本界面使用命令删除目录。 在Linux中有很多方法可以删除目录,在图形化界面可以利用文件管理器,或者通过终端删除。本文将介绍在文本界面使用命令删除目录。
使用rmdir删除目录
Rmdir命令间成“remove directory”,用于删除空目录的命令。
例如,删除一个名为“MyDocuments”的空目录:
[root@localhost test]# rmdir MyDocuments 如果目录不是空的,会提示错误:
rmdir: failed to remove ‘MyDocuments’: Directory not empty 使用rm命令删除目录
rm命令通常用于删除Linux中的文件。可以添加参数用来删除目录。例如,递归地删除目录,使用递归选项-r或-R,如果目录是受写保护的,则会提示是否继续删除目录和目录中的文件作为一个整体。-f 强制删除而不被提示。
[root@localhost test]# rm -rf MyDocuments/ 可以在单个命令中删除多个目录,如下面的命令所示。命令删除所有目录和它们的子目录,而不提示删除。
[root@localhost test]# rm -rf dir1 dir2 dir3 使用find命令
Find命令帮助用户根据特定的表达式搜索文件和目录。此外,该命令可用于搜索目录并根据指定的搜索标准删除它们。
删除当前目录中的名为”MyDocuments”的目录
[root@localhost test]# find . -type d -name "MyDocuments" -exec rm -rf {} + . 表示在当前目录执行-type d 只搜索目录-name 指定目录名称-exec rm -rf 执行rm命令删除所有目录即内容{} + 追加在rm命令末尾 删除一个空目录
如果希望删除所有空目录,请使用以下命令:
[root@localhost test]# find . -type d -empty -delete -empty 只对空目录进行限制-delete 删除包括子目录在内的所有空目录 总结
好吧,写了这么多关于python桌面开发的博文,今天终于开始回过头来,把tkinter的基础知识进行科普一下了。
一路走来,不容易! 贵在持之以恒
OK,这篇大而全的科普文章,经过整理和参考多方的资料,终于完工了。可喜可贺!在此也感谢前辈的努力和分享!
下面正式进入正题:tkinter基础知识科普,也许你想学习的知识这里都有
文章目录 一、什么是GUI二、 PYTHON的GUI库三、 什么是tkinter(一) 容器+组件的设计思维(二) 多重继承的架构模式1. 根父类Misc和Wm2. 子类 Tk3. 组件基类 BaseWidget4. UI组件 四、 一个入门案例五、 配置方法六、 控件的共同属性七、 查看帮助文档八、事件处理(一) command方法(二) bind方法 九、 Variable变量处理 一、什么是GUI GUI,是 Graphics User Interface(图形用户界面)的缩写。在 GUI 中,并不只是输入文本和返回文本,用户可以看到窗口、按钮、文本框等组件,还可以通过鼠标和键盘操作应用。
GUI 是程序交互的一种不同的方式,使用 GUI 开发的程序,和命令行程序一样,都具有输入数据、处理数据和输出数据这3个基本要素,只不过,使用 GUI 开发的程序,它们的输入和输出方式更丰富,更有趣。
二、 PYTHON的GUI库 Python GUI 常用库
库名特点wxPythonwxPython 是一个跨平台的 GUI 工具集,以流行的 wxWidgets(原名 wxWindows)为基础,提供了良好的跨平台外观。简单来说,wxPython 在 Windows上调用 Windows 的本地组件、在 Mac OS 上调用 Mac OS X 的本地组件、在 Linux 上调用 Linux 的本地组件,这样可以让 GUI 程序在不同的平台上显示平台对应的风格。wxPython 是一个非常流行的跨平台的 GUI 库。其官方网址是http://www.
Nginx是一款轻量级的、高性能的Web 服务器/反向代理服务器,其特点是占有内存少,并发能力强。
文章目录 1、Nginx安装2、Nginx启动3、Nginx命令4、本地域名解析5、Nginx配置5.1、root方式配置5.2、alias方式配置5.3、反向代理 1、Nginx安装 解压安装包,不要有中文路径,不要保存C盘
2、Nginx启动 右键nginx.exe,超级管理员身份运行。
nginx默认占用端口号80。
访问http://localhost/
3、Nginx命令 ①、搜索命令提示符,以管理员身份运行,打开cmd窗口
②、输入D:到D盘
③、cd + 文件夹名到达nginx根目录
④、start nginx 启动
⑤、nginx -s reload 重启
⑥、nginx -s stop 关闭
⑦、nginx -t 检测配置是否正确
4、本地域名解析 本机HOSTS文件位置:
在本机环境中测试时,可以人为地修改域名与IP的映射关系,用自定义的域名代替localhost,相当于域名解析器。
5、Nginx配置 http { server { #监听端口号 listen 80; #监听的域名 server_name localhost; #反向代理的配置项 / 是正则表达式写法 location / { #root 关键字 代表文件夹目录 root html; #默认页面跳转 index index.html index.htm; } } } 5.1、root方式配置 root指定的是根目录,会从根目录开始查找,location指定的路径,在root指定的位置后一定要存在。
使用root,实际的路径就是:root值 + location值。
location /test-root { root html/1-JT/; #在1-JT下要存在test-root目录 } 访问:http://www.
文章目录 前言一、为什么使用libbpf?二、环境搭建1.Libbpf相关环境搭建2.GO环境搭建 三、使用libbpfgo编译运行eBPF程序步骤1:生成头文件步骤2:Clang将BPF程序的源代码编译为.o对象文件步骤3:使用GO编译为二进制文件并运行 后记 前言 本文参考:How to Build eBPF Programs with libbpfgo
但实际运行时出现了许多情况,因此记录分享。
写在最前:使用libbpf请将系统更新到最新版本,本文环境为Ubuntu21.04。
Ubuntu最新版本下载
一、为什么使用libbpf? libbpf是可以在用户空间和 bpf 程序中导入的库。它为开发人员提供了一个用于加载 bpf 程序并与之交互的 API。
在使用libbpf前,先使用bcc对eBPF相关知识进行学习运行,学习曲线将更平滑。相对于bcc,libbpf与BPF CO-RE的实际编译部署的难度增大了。
然而性能优化大师 Brendan Gregg 在用 libbpf + BPF CO-RE 转换一个 BCC 工具后给出了性能对比数据:
As my colleague Jason pointed out, the memory footprint of opensnoopas CO-RE is much lower than opensnoop.py. 9 Mbytes for CO-RE vs 80 Mbytes for Python.
我们可以看到在运行时相比 BCC 版本,libbpf + BPF CO-RE 版本节约了近 9 倍的内存开销,这对于物理内存资源已经紧张的服务器来说会更友好。
一、开发社区首页 代码:community-1.6
1.1、建立数据库 init.schema.sql文件
1.2、DAO数据访问层 1、编写实体类(Entity)
User.java 用户信息 DiscussPost.java Page.java 封装分页相关的信息 2、编写对应Mapper文件(注释:@Mapper)
public interface UserMapper {} public interface DiscussPostMapper {} 3、编写xml配置文件(放在 resources.mapper下)
user-mapper.xml DiscussPost-mapper.xml 4、测试 MapperTests.java
1.3、service业务层 1、编写service包下的 DiscussPostService.java和UserService.java(通过userID查询到用户的信息)
1.4、Controller视图层 1.4.1、开发社区首页,显示前10个数据 1、编写HomeController.java
2、index.html
1.4.2、开发分页组件 分页显示
1.5、项目调试技巧 响应状态码的含义
https://developer.mozilla.org/zh-CN/docs/Web/HTTP
常见状态码:
200:请求成功302:重定向:请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的404:客户端响应:请求失败,请求所希望得到的资源未被在服务器上发现。路径有问题。500:服务器响应:服务器遇到了不知道如何处理的情况。 服务端断点调试技巧
客户端断点调试技巧
设置日志级别,并将日志输出到不同的终端
logback配置文件:logback-spring.xml
1.6、版本控制Git 二、SpringBoot实战,开发社区登录模块 2.1、发送邮件 邮箱设置:启用客户端SMTP服务
Spring Email:
在pom.xml文件中导入jar包
邮箱参数配置
使用JavaMailSender发送邮件
在util包下创建MailClient.java工具类,封装发送邮件功能测试MapperTests.java 模板引擎
使用Thymeleaf发送HTML邮件: resource.templates.mail.demo.html 2.2、开发注册功能 共涉及到了三个请求
(1) 点击注册按钮,弹出注册框
(2) 填完表单数据,点击注册,会发送一次请求
(3) 注册成功后,用户接收到激活邮件后,点击激活邮件又会发送一次请求(进行激活服务)
2.2.1、请求一:访问注册页面 controller层,显示注册网站 controller.
大家好,我是程序员吴师兄,一个坚持在 CSDN 日更原创的程序员。
今天想和大家聊一聊为什么有人劝别选计算机专业?
和大家说一句掏心窝的话:直到 2021 年,计算机专业依旧是寒门改变命运的一个最佳选择之一,要不是怕被喷,我都想把之一去掉,因为想了半天,我实在找不到其它与之匹配的选择。。
之所以会出现有人劝退计算机专业,我琢磨了一下,可能有以下几个原因:
1、本身对编程无感,但听说计算机专业高薪,所以人云亦云的进来,后来发现这钱没有想象中那么好挣,996 是常态,于是发出呐喊:别选计算机!
2、家里有矿,背景好,进可玩玩金融,退可当个包租公,瞧不起敲臭代码的程序员,于是居高临下鄙视到:别选计算机。
3、身边有程序员,对程序员存在误解,认为程序员都是穿格子衫黑眼圈秃头的形象,选了计算机专业最终会变成单身狗,出于好心,提醒别人:别选计算机专业。
4、稀里糊涂的参加了培训班,一出来发现找不到工作,浪费了大半年时间和上万元人民币,怒斥道:RNM,退钱,别选计算机专业!
5、对计算机专业持悲观态度,认为计算机现在已经太火了,火过头了,比白酒还火,各行各业都想转计算机,人员早就饱和,现在进就等着失业吧。
看完这些原因,可以得出一个很明显的结论:计算机专业并不是适合每一个人,劝进劝退都可以。
计算机专业不适合那些怕苦的人,不适合那些不缺钱的人,不适合那些不热爱技术的人。
计算机专业最适合的群体是那些热爱计算机技术同时又想高薪的同学,想想一毕业就有可能找到月薪 20k 甚至 30k 的工作,而同龄人在其它非金融行业才五六千起步,寒门逆袭的故事正在书写。
并且,计算机专业毕业去找工作,那些互联网大厂并不像招其他岗位的人一样,十分看重学历或者看重大学成绩,一次表现优异的秋招,足以。
说来说去,对于想改变命运的寒门学子来说,我是相当劝进学计算机的,当然,很有可能你会说:我也想选计算机专业,但我怕自己不热爱技术。
关于这个问题,我建议在一开始的时候可以去看一个视频,叫做《计算机科学速成课》,这套课程是 Crash Course 旗下的计算机科学相关的视频,早期发布在 Youtube 上,整个系列课程高达 12 亿的播放量,现在你可以在 B 站上免费观看,有汉化有弹幕。
之所以建议看这个视频,是因为这个系列视频总时长 10 个小时,一共 40 集,基本上每集控制在 10 分钟左右,只要不到 10 小时就可以粗略了解计算机科学这门学科,如果你是一个门外汉,相信我,通过这个短短的 10 个小时足以帮你打开计算机的大门。
Crash Course 的这套计算机科学视频一共 40 集,基本上每集控制在 10 分钟左右,所以,只要不到 10 小时就可以粗略了解计算机科学这门学科,如果你是一个门外汉,相信我,通过这个短短的 10 个小时足以帮你打开计算机的大门。
你可能会不禁疑惑,十几分钟能学到啥?而事实上,Crash Course 的视频信息量很大,每一秒的时间都是精华,视频里面不仅有图像、视频资料、图表等,更有老师面授,老师的语速也是很快的,如果跟不上,建议 0.75 的速度进行观看。
如果你是小白,想了解一门学科,不妨通过该系列视频作为切入点;如果你是某学科学生,可以用该视频梳理总结课程的框架结构;如果你想拓宽知识,这个系列视频作为下饭菜也是十分合适的。
Crash Course 的 Youtube 官方频道地址如下:
https://www.youtube.com/user/crashcourse
B 站频道地址如下:
多周期路径 利用这一约束可以修改STA时序分析的建立和保持关系。
单周期路径 默认情况下Vivado执行单周期的检查。
setup 一个周期hold零个周期 如下图所示:
建立 建立关系是发送沿和捕获沿的关系。建立要求 = 捕获沿 - 发送沿 STA实际会找到所有的建立要求,在图中仅画出最严苛的情况,因为STA时序只计算最严苛的情况,也就是建立要求的最小值,我们知道正常情况下,setup是正数才对,而正得越多建立的松弛(建立后的余量,越容易达到建立条件)越多,对应数值越大,所以这里要选择小的,即建立松弛小的。
保持 这里有两个保持要求:
hold1 保持关系的发送沿==(默认就是上图的发送沿)发的数据不能被到达沿(默认是上图捕获沿的前一个周期)==捕获。保持要求 = 到达沿 - 保持关系发送沿。保持关系是到达沿与保持关系发送沿的关系。因为保持关系发送沿可以根据约束移动,所以不一定保持关系发送沿的下一个周期就是源时钟的下一个发送沿。 hold2 保持关系的发送沿的下一个发送沿==(默认就是发送沿的下一个周期即上图的下一个发送沿)==发送的数据不能被捕获沿捕获。保持要求 = 捕获沿 - 保持关系的发送沿的下一个发送沿。保持关系是到达沿下一个周期==(默认是捕获沿)与保持关系的发送沿的下一个发送沿(默认就是发送沿的下一个周期即上图的下一个发送沿)==关系。因为到达沿可以根据约束移动,所以不一定到达沿下一个周期就是目的时钟捕获沿。 STA时序只计算最严苛的情况,也就是两个保持要求的最大值,我们知道正常情况下,hold1和hold2都是负数才对,因此而负得越多保持的松弛(保持后的余量,越容易达到保持条件)越多,而对应数值越小,所以这里要选择大的,即保持松弛小的。实际上第二个保持关系与第一个保持关系是同一个意思,发送沿当作下个发送沿,则到达沿就是捕获沿。每个建立条件都有两个保持关系,而建立条件的最严苛不一定对应于保持关系的最严苛,STA是单独计算的。换句话就是STA会找一个公共周期(在0位置对齐的相位开始,还有相同的对齐相位)内的所有建立关系,并选择最小的为关注点,每一个建立关系都有两个保持关系,STA会选择最大的为关注点,最大关注点保持关系不一定对应于最小关注点的建立关系。
建立保持检查 默认的STA将执行以下的建立与保持关系检查。
建立检查
TDatapath(max) < TCLK(t=Period) - TSetup 保持检查
TDatapath(min) > TCLK(t=0) + THold 对于其他情况下,可能需要多个周期或者为了让终端接收到稳定的数据,需要多个时钟周期才能将数据稳定。
用法 set_multicycle_path <path_multiplier> [-setup|-hold] [-start|-end] [-from <startpoints>] [-to <endpoints>] [-through <pins|cells|nets>] 保持关系在大多数情况下跟着建立关系走,且有下面的公式,默认情况下 setup path multiplier = 1,hold path multiplier = 0
h o l d _ c y c l e s = < s e t u p p a t h m u l t i p l i e r > − 1 − < h o l d p a t h m u l t i p l i e r > = 1 − 1 − 0 = 0 \begin{aligned} hold\_cycles &= <setup path multiplier> - 1 - <hold path multiplier>\\ &= 1 - 1 -0\\ &= 0 \end{aligned} hold_cycles=<setuppathmultiplier>−1−<holdpathmultiplier>=1−1−0=0
springboot 集成系列 mybatis-plus 简单配置:一个dependency,一个@MapperScan 在pom.xml文件中引入mybatis-plus-starter的依赖,(注意:不需要再引入mybatis-core等依赖,因为在starter中已全部添加) <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> mybatis-plus 核心依赖关系 2. 在启动类上增加扫描注解@MapperScan
@MapperScan(basePackages = "com.xxx.dao")
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan(basePackages = "com.xxx.dao") public class RcbaApplication { public static void main(String[] args) { SpringApplication.run(RcbaApplication.class, args); } } 3. 在DAO类上继承mybatis-plus的BaseMapper,则DAO类快速拥有了CRUD功能
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xxx.model.AuthUser; public interface AuthUserDao extends BaseMapper<AuthUser> { } 4. 在service层继承mybatis-plus的ServiceImpl类,service类也同样拥有了CRUD功能
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xxx.dao.AuthUserDao; import com.xxx.model.AuthUser; import com.xxx.service.AuthUserService; import org.springframework.stereotype.Service; @Service public class AuthUserServiceImpl extends ServiceImpl<AuthUserDao, AuthUser> implements AuthUserService { }
GitHub代码链接:https://github.com/Tony0726/Keyword-Extraction.git
数据集:https://github.com/yuewang-cuhk/TAKG/tree/master/data/Weibo
写在前面:这是数据挖掘老师布置的一个作业,我本来打算网上找别人现成的改一下,结果发现基本上都基于无监督的方法,例如TF-IDF。而我想用基于有监督的方法,毕竟老师给了数据集不拿来训练实在太可惜了,所以被迫自己写代码,下面都是关于程序的运行说明,有问题的话可以评论区或私信留言,我看到的话会第一时间回复,如果能帮到你的话在GitHub上记得点颗星星。
本实验用了两类共5种方法,分别是基于无监督与基于有监督(即机器学习)的两类方法,无监督用了TF-IDF和LDA,机器学习用的是RNN、LSTM和LR-SGD分类器,目前只在中文上运行成功,因为数据集中存在英文所以理论上英文也行。
运行环境 运行系统为Window10,运行软件为Pycharm,编程语言为python,python版本为3.8.3,numpy版本为1.18.5,jieba版本为0.42.1,gensim版本为3.8.3,scikit-learn版本为0.23.1,joblib版本为0.16.0,torch版本为1.7.0。
文件说明 zh_wiki.py 和 langconv.py 用于繁体字转简体
RNN & LSTM.py RNN和LSTM
SGD.py SGD
TF-IDF & LDA TF-IDF和LDA
data文件夹 用于存储数据集、停用词表和数据集特征提取后的nump矩阵
result文件夹 用于存储结果
saved_model文件夹 用于存储训练模型
stopword.txt 停用词表
train_src.txt、train_trg.txt、valid_src.txt、valid_trg.txt、test_src.txt、test_trg.txt 文本数据集
dataset.npz 数据集特征提取后的numpy矩阵保存文件
lstm_best_0.pkl LSTM候选词个数不限时的最佳模型 lstm_best_0.txt 对应的输出结果
lstm_best.pkl LSTM候选词个数为5时的最佳模型 lstm_best.txt 对应的输出结果
rnn_best_0.pkl RNN候选词个数不限时的最佳模型 rnn_best_0.txt 对应的输出结果
rnn_best.pkl RNN候选词个数为5时的最佳模型 rnn_best.txt 对应的输出结果
sgd.pkl SGD模型(不论候选词个数为5还是不限都用这个模型) sgd_best.txt、 sgd_best_0.txt 为对应输出的结果
lad_best.txt LDA最佳结果
tfidf_best.txt TF-IDF最佳结果
运行说明 RNN RNN是一种特殊的神经网络结构,它之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。具体的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。因此非常适合自然语言处理,于是本文用RNN来实现关键词抽取。
打开RNN & LSTM.py文件,将327行model = torch.load('./saved_model/lstm_best.pkl')改为model = torch.load('./saved_model/rnn_best.pkl')后运行即可。
若要训练,只需将319-324行的注释取消(代码如下),并将326-335行注释(代码如下),然后运行即可。
友链
references:
https://blog.csdn.net/koastal/article/details/52125583https://www.cnblogs.com/jmtang/p/13477193.html 下载源码
cd /usr/local/src wget http://cn2.php.net/get/php-5.6.24.tar.gz/from/this/mirror mv mirror php-5.6.24.tar.gz tar -zxvf php-5.6.24.tar.gz cd php-5.6.24 安装依赖
apt-get install libxml2-dev apt-get install libpng-dev apt-get -y install libfreetype6-dev apt-get install openssl apt-get install libcurl4-openssl-dev apt-get install libssl-dev apt-get install libjpeg-dev 配置
./configure --prefix=/opt/php --with-config-file-path=/opt/php/lib --enable-mbstring --enable-ftp --with-gd --with-jpeg-dir=/usr --with-png-dir=/usr --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-openssl-dir=/usr --with-openssl --with-pdo-mysql=mysqlnd --with-pear --enable-sockets --with-freetype-dir=/usr --enable-gd-native-ttf --with-zlib --with-libxml-dir=/usr --with-xmlrpc --enable-zip --enable-fpm --enable-fpm --enable-xml --enable-sockets --with-gd --with-zlib --with-iconv --enable-zip --with-freetype-dir=/usr/lib/ --with-openssl=/usr/local/ssl --enable-soap --enable-pcntl --enable-cli 安装
大家好,我是程序员吴师兄。
今天和大家聊一聊为什么我喜欢用动画讲解算法。
原因很简单,在文章中加入动画和图片相对于只有文字代码会更加有趣耐读,一方面可以让技术类文章显得不那么枯燥,另外一方面视觉冲击感带来的印象会更加深刻,有利于理解和记忆。
对于学算法的小白来说,如果教程中有动画和图片,往往能帮助他们更好的入门,在这里给大家推荐一个算法可视化的网站 VisuAlgo 。
地址:https://visualgo.net/zh
VisuAlgo 包含了程序员必学的数据结构和算法,比如排序、链表、哈希表、二叉树、图等,它把算法的执行过程以最直观可视化的形式展示出来,很多我一开始无法理解的抽象算法一下子立体化,犹如打通了任督二脉,很多算法知识融会贯通。
基于 VisuAlgo 带来的灵感和帮助,我在写 LeetCode 题解的时候开始加入图片和动画,不得不说,这个举动帮助不少初学者度过了入门阶段。
如果你在学习数据结构的过程中觉得太抽象,那么可以通过 VisuAlgo 辅助理解。
如果你想刷算法题,那么可以访问 AlgoMooc,每道题目都有动画和图片。
AlgoMooc 地址:https://www.algomooc.com
作者简介 作者:大家好,我是程序员吴师兄,在 GitHub 上开源了一个项目 LeetCodeAnimation,目前有 60k star,通过动画的形式讲解算法,已经帮助成千上万的程序员入门算法了,欢迎关注公众号「五分钟学算法」,和我们一起学习算法。
点击了解程序员吴师兄
转载说明:未获得授权,禁止转载
一、软件架构设计 软件或计算机系统的软件架构是该系统的一个(或多个)结构,而结构由软件元素、元素的外部可见属性及它们之间的关系组成。
软件系统架构是关于软件系统的 结构、行为和属性 的高级抽象。指定了软件系统的组织结构和拓扑结构。
软件架构是可传递可复用的模型,架构就是体系结构。架构设计介于需求分析和软件设计之间。架构设计就是需求分配,即满足,需求的职责分配到组件上。
软件架构设计是降低成本、改进质量、按时和按需交付产品的关键因素。架构设计能够满足系统的性能、可维护性等品质;能够使得不同的利益相关人(stakeholders)达成一致的目标;能够支持项目计划和项目管理等活动;能够有效地管理复杂性;等等。然而系统架构的给出必须建立在需求明确的基础上。
软件架构能够在设计变更相对容易的阶段,考虑系统结构的可选方案,便于技术人员与非技术人员就软件设计进行交互,能够展现软件的结构、属性与内部交互关系。但是软件架构与用户对系统的功能性需求没有直接的对应关系。
二、架构的模型 4+1视图 逻辑视图:主要支持系统的功能需求,即系统提供给最终用户的服务。(用户关注)
开发视图:也称为模块(实现)视图,主要侧重于软件模块的组织和管理。(程序员)
进程视图:侧重于系统的运行特性,主要关注一些非功能性的需求,例如系统的性能和可用性。(并发,集成人员)
物理视图:主要考虑如何把软件映射到硬件上,它通常要考虑到解决系统拓扑结构、系统安装、通信等问题。(软件到硬件,系统工程人员)
场景:可以看作是那些重要系统活动的抽象,它使四个视图有机地联系起来,从某种意义上说,场景是最重要的需求抽象。(用例图)
逻辑视图和开发视图描述系统的静态结构,而进程视图和物理视图描述系统的动态结构。
三、软件架构风格 软件架构风格是描述特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件和这些构件的组织方式;惯用模式则反映众多系统共有的结构和语义特性。强调对软件设计的重用。
架构风格定义一个系统家族,即一个架构定义一个词汇表和一组约束。词汇表中包含一些构件和连接件类型,而这组约束指出系统是如何将这些构件和连接件组合起来的。架构风格反映了领域中众多系统所共有的结构和语义特性,并指导如何将各个模块和子系统有效地组织成一个完整的系统。对软件架构风格的研究和实践促进对设计的重用,一些经过实践证实的解决方案也可以可靠地用于解决新的问题。例如,如果某人把系统描述为“客户/服务器”模式,则不必给出设计细节,我们立刻会明白系统是如何组织和工作的。
1. 数据流风格
批处理序列
强调数据作为一个整体(数据必须是完整的,以整体的方式传递)
管道和过滤器
每个构件都有一组输入和输出,构件读输入的数据流,经过内部处理,然后产生输出数据流. (构件–>过滤器;连接件–>管道) (数据流的形式)
2. 调用/返回风格
主程序/子程序
计算构件作为子程序协作工作,由一个主程序顺序地调用这些子程序,构件通过共享存储区交换数据. 曾经作为结构化开发方法的主要选择,具有结构清晰,维护方便的特点,缺点是主子程序划分缺乏标准,较难实现不同设计人员间设计的子程序复用。
面向对象风格
面向对象在类的层次实现高度内聚,整个系统通过不同类的组合调用实现不同功能,便于类的复用,只是面向对象是一个通用风格,类的划分不同设计人员设计结果有很大不同,对实际架构设计指导意义不大。
层次结构风格
分层结构将整个系统按照抽象层次不同分为多层,每个层次的程序只需要负责与相邻的上下两层打交道,简化了系统中调用关系复杂度。允许每层用不同的方法实现,为软件重用提供了强大的支持。(二层C/S、三层C/S、MVC、MVP、MVVP、RIA富互联网应用)
3. 独立构件风格
进程通讯
进程通讯架构将系统建设成一个个独立构件,构件间采用命名的消息传递来实现沟通与协作。
事件系统子风格(隐式调用 )
事件驱动架构风格与进程通讯风格类似,也是将系统分各个为独立的构件,不同的是不同构件间通讯不采用命名的消息,而是采用隐式调用的方式,先将一个个构件的过程注册到某个事件中,当这个事件发生时,所有注册到该事件的过程自动被触发执行。这类风格的好处是独立构件间耦合度进一步降低,方便构件修改及替换,缺点是触发事件放弃了对被触发执行程序组的控制。
4. 虚拟机风格
解释器
具有运行时系统行为 (自)定义与改变能力 。如专家系统。
基于规则的系统
基于规则的系统包括规则集、规则解释器、规则/数据选择器及工作内存。(一般用在人工智能领域和DSS中)
5. 仓库风格
在仓库风格中,有两种不同的构件:中央数据结构说明当前状态,独立构件在中央数据存储上执行。
数据库系统
构件主要有两大类,一个是中央共享数据源,保存当前系统的数据状态,另一个是多个独立处理元素,处理元素对数据元素进行操作。中央数据库管理系统通过自身机制如数据排它锁,共享锁等,实现数据高速访问,数据一致性,数据完整性。同时各独立数据处理单元之间互相不受约束。 (如编译器,传统编译器采用批处理架构,现代编译器采用数据共享架构风格。分析树是共享数据。)
超文本系统
主要应用于静态网页。
黑板风格
由一个作为全局共享数据的黑板,一个控制单元和多个知识源组成,主要应用与专家问题解决系统。通过专家知识和反馈逐步得到正确结果. (如语音识别)
6. 闭环控制架构
过程控制
工业中的过程控制是指以温度、压力、流量、液位和成分等工艺参数作为被控变量的自动控制。过程控制也称实时控制,是计算机及时的采集检测数据,按最佳值迅速地对控制对象进行自动控制和自动调节,如数控机床和生产流水线的控制等。(比如空调制冷,温度大于设定温度制冷,小于等于时停止,一旦大于继续运作)
C2
通过连接件绑定在一起按照一组规则运作的并行构件。
构建和连接件都有一个顶部和一个底部构建的顶部都要连接连接件的底部,构建的底部都要连接连接件的顶部,构建 之间不允许直连。一个连接进行直接连接时,必须有其中一个的底部到另一个的顶部。 四、分层C/S架构风格演化 1.
概念:
VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。
DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。
VO与DTO的区别
大家可能会有个疑问(在笔者参与的项目中,很多程序员也有相同的疑惑):既然DTO是展示层与服务层之间传递数据的对象,为什么还需要一个VO呢?对!对于绝大部分的应用场景来说,DTO和VO的属性值基本是一致的,而且他们通常都是POJO,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在VO和DTO,因为两者有着本质的区别,DTO代表服务层需要接收的数据和返回的数据,而VO代表展示层需要显示的数据。
用一个例子来说明可能会比较容易理解:例如服务层有一个getUser的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,它可能需要用“帅哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。说到这里,可能你还会反驳,在服务层直接就返回“帅哥美女”不就行了吗?对于大部分应用来说,这不是问题,但设想一下,如果需求允许客户可以定制风格,而不同风格对于“性别”的表现方式不一样,又或者这个服务同时供多个客户端使用(不同门户),而不同的客户端对于表现层的要求有所不同,那么,问题就来了。再者,回到设计层面上分析,从职责单一原则来看,服务层只负责业务,与具体的表现形式无关,因此,它返回的DTO,不应该出现与表现形式的耦合。
理论归理论,这到底还是分析设计层面的思维,是否在实现层面必须这样做呢?一刀切的做法往往会得不偿失,下面我马上会分析应用中如何做出正确的选择。
VO与DTO的应用
上面只是用了一个简单的例子来说明VO与DTO在概念上的区别,本节将会告诉你如何在应用中做出正确的选择。
在以下才场景中,我们可以考虑把VO与DTO二合为一(注意:是实现层面):
当需求非常清晰稳定,而且客户端很明确只有一个的时候,没有必要把VO和DTO区分开来,这时候VO可以退隐,用一个DTO即可,为什么是VO退隐而不是DTO?回到设计层面,服务层的职责依然不应该与展示层耦合,所以,对于前面的例子,你很容易理解,DTO对于“性别”来说,依然不能用“帅哥美女”,这个转换应该依赖于页面的脚本(如JavaScript)或其他机制(JSTL、EL、CSS)
即使客户端可以进行定制,或者存在多个不同的客户端,如果客户端能够用某种技术(脚本或其他机制)实现转换,同样可以让VO退隐
以下场景需要优先考虑VO、DTO并存:
上述场景的反面场景
因为某种技术原因,比如某个框架(如Flex)提供自动把POJO转换为UI中某些Field时,可以考虑在实现层面定义出VO,这个权衡完全取决于使用框架的自动转换能力带来的开发和维护效率提升与设计多一个VO所多做的事情带来的开发和维护效率的下降之间的比对。
如果页面出现一个“大视图”,而组成这个大视图的所有数据需要调用多个服务,返回多个DTO来组装(当然,这同样可以通过服务层提供一次性返回一个大视图的DTO来取代,但在服务层提供一个这样的方法是否合适,需要在设计层面进行权衡)。
DTO与DO的区别
首先是概念上的区别,DTO是展示层和服务层之间的数据传输对象(可以认为是两者之间的协议),而DO是对现实世界各种业务角色的抽象,这就引出了两者在数据上的区别,例如UserInfo和User(对于DTO和DO的命名规则,请参见笔者前面的一篇博文),对于一个getUser方法来说,本质上它永远不应该返回用户的密码,因此UserInfo至少比User少一个password的数据。而在领域驱动设计中,正如第一篇系列文章所说,DO不是简单的POJO,它具有领域业务逻辑。
DTO与DO的应用
从上一节的例子中,细心的读者可能会发现问题:既然getUser方法返回的UserInfo不应该包含password,那么就不应该存在password这个属性定义,但如果同时有一个createUser的方法,传入的UserInfo需要包含用户的password,怎么办?在设计层面,展示层向服务层传递的DTO与服务层返回给展示层的DTO在概念上是不同的,但在实现层面,我们通常很少会这样做(定义两个UserInfo,甚至更多),因为这样做并不见得很明智,我们完全可以设计一个完全兼容的DTO,在服务层接收数据的时候,不该由展示层设置的属性(如订单的总价应该由其单价、数量、折扣等决定),无论展示层是否设置,服务层都一概忽略,而在服务层返回数据时,不该返回的数据(如用户密码),就不设置对应的属性。
对于DO来说,还有一点需要说明:为什么不在服务层中直接返回DO呢?这样可以省去DTO的编码和转换工作,原因如下:
两者在本质上的区别可能导致彼此并不一一对应,一个DTO可能对应多个DO,反之亦然,甚至两者存在多对多的关系。
DO具有一些不应该让展示层知道的数据
DO具有业务方法,如果直接把DO传递给展示层,展示层的代码就可以绕过服务层直接调用它不应该访问的操作,对于基于AOP拦截服务层来进行访问控制的机制来说,这问题尤为突出,而在展示层调用DO的业务方法也会因为事务的问题,让事务难以控制。
对于某些ORM框架(如Hibernate)来说,通常会使用“延迟加载”技术,如果直接把DO暴露给展示层,对于大部分情况,展示层不在事务范围之内(Open session in view在大部分情况下不是一种值得推崇的设计),如果其尝试在Session关闭的情况下获取一个未加载的关联对象,会出现运行时异常(对于Hibernate来说,就是LazyInitiliaztionException)。
从设计层面来说,展示层依赖于服务层,服务层依赖于领域层,如果把DO暴露出去,就会导致展示层直接依赖于领域层,这虽然依然是单向依赖,但这种跨层依赖会导致不必要的耦合。
对于DTO来说,也有一点必须进行说明,就是DTO应该是一个“扁平的二维对象”,举个例子来说明:如果User会关联若干个其他实体(例如Address、Account、Region等),那么getUser()返回的UserInfo,是否就需要把其关联的对象的DTO都一并返回呢?如果这样的话,必然导致数据传输量的大增,对于分布式应用来说,由于涉及数据在网络上的传输、序列化和反序列化,这种设计更不可接受。如果getUser除了要返回User的基本信息外,还需要返回一个AccountId、AccountName、RegionId、RegionName,那么,请把这些属性定义到UserInfo中,把一个“立体”的对象树“压扁”成一个“扁平的二维对象”,笔者目前参与的项目是一个分布式系统,该系统不管三七二十一,把一个对象的所有关联对象都转换为相同结构的DTO对象树并返回,导致性能非常的慢。
DO与PO的区别
DO和PO在绝大部分情况下是一一对应的,PO是只含有get/set方法的POJO,但某些场景还是能反映出两者在概念上存在本质的区别:
DO在某些场景下不需要进行显式的持久化,例如利用策略模式设计的商品折扣策略,会衍生出折扣策略的接口和不同折扣策略实现类,这些折扣策略实现类可以算是DO,但它们只驻留在静态内存,不需要持久化到持久层,因此,这类DO是不存在对应的PO的。
同样的道理,某些场景下,PO也没有对应的DO,例如老师Teacher和学生Student存在多对多的关系,在关系数据库中,这种关系需要表现为一个中间表,也就对应有一个TeacherAndStudentPO的PO,但这个PO在业务领域没有任何现实的意义,它完全不能与任何DO对应上。这里要特别声明,并不是所有多对多关系都没有业务含义,这跟具体业务场景有关,例如:两个PO之间的关系会影响具体业务,并且这种关系存在多种类型,那么这种多对多关系也应该表现为一个DO,又如:“角色”与“资源”之间存在多对多关系,而这种关系很明显会表现为一个DO——“权限”。
某些情况下,为了某种持久化策略或者性能的考虑,一个PO可能对应多个DO,反之亦然。例如客户Customer有其联系信息Contacts,这里是两个一对一关系的DO,但可能出于性能的考虑(极端情况,权作举例),为了减少数据库的连接查询操作,把Customer和Contacts两个DO数据合并到一张数据表中。反过来,如果一本图书Book,有一个属性是封面cover,但该属性是一副图片的二进制数据,而某些查询操作不希望把cover一并加载,从而减轻磁盘IO开销,同时假设ORM框架不支持属性级别的延迟加载,那么就需要考虑把cover独立到一张数据表中去,这样就形成一个DO对应对个PO的情况。
PO的某些属性值对于DO没有任何意义,这些属性值可能是为了解决某些持久化策略而存在的数据,例如为了实现“乐观锁”,PO存在一个version的属性,这个version对于DO来说是没有任何业务意义的,它不应该在DO中存在。同理,DO中也可能存在不需要持久化的属性。
DO与PO的应用
由于ORM框架的功能非常强大而大行其道,而且JavaEE也推出了JPA规范,现在的业务应用开发,基本上不需要区分DO与PO,PO完全可以通过JPA,Hibernate Annotations/hbm隐藏在DO之中。虽然如此,但有些问题我们还必须注意:
对于DO中不需要持久化的属性,需要通过ORM显式的声明,如:在JPA中,可以利用@Transient声明。
对于PO中为了某种持久化策略而存在的属性,例如version,由于DO、PO合并了,必须在DO中声明,但由于这个属性对DO是没有任何业务意义的,需要让该属性对外隐藏起来,最常见的做法是把该属性的get/set方法私有化,甚至不提供get/set方法,但对于Hibernate来说,这需要特别注意,由于Hibernate从数据库读取数据转换为DO时,是利用反射机制先调用DO的空参数构造函数构造DO实例,然后再利用JavaBean的规范反射出set方法来为每个属性设值,如果不显式声明set方法,或把set方法设置为private,都会导致Hibernate无法初始化DO,从而出现运行时异常,可行的做法是把属性的set方法设置为protected。
对于一个DO对应多个PO,或者一个PO对应多个DO的场景,以及属性级别的延迟加载,Hibernate都提供了很好的支持,请参考Hibnate的相关资料。
前言 雪花算法生成的Long型ID,传到前台时末尾精度丢失。后台数据1402848130449276928传到前台变为1402848130449277000。为了兼容先前代码。方案为:后台类型保持不变。jackson序列化数据到前台时,将Long转为String。前台使用String类型ID,既不影响前后台数据交互,也不影响前台大部分代码,我的前台系统代码也只是修改了分页插件的Total变量,将其再次转为Number类型。
后台序列化 第一种方案:
此种方案仅在系统中没有使用@EnableWebMvc注解时有效。
因为@EnableWebMvc继承的WebMvcConfigurationSupport,requestMappingHandlerAdapter()中的setMessageConverters会覆盖掉自定义的ObjectMapper。
@Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // 全局配置序列化返回 JSON 处理 SimpleModule simpleModule = new SimpleModule(); //JSON Long ==> String simpleModule.addSerializer(Long.class, ToStringSerializer.instance); objectMapper.registerModule(simpleModule); return objectMapper; } 第二种方案:
在@EnableWebMv注解的类中这样注册
@Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters){ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = converter.getObjectMapper(); // 生成JSON时,将所有Long转换成String SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(Long.class, ToStringSerializer.instance); simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); objectMapper.registerModule(simpleModule); // 设置格式化内容 converter.setObjectMapper(objectMapper); converters.add(0, converter); } 前台转化 几乎前台所有代码无需修改。你也可以用一元+操作符,将string转化为Number类型
一、 Afinal
官方介绍:
Afinal是一个Android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过finalActivity,我们可以通过注解的方式进行绑定ui和事件。通过finalBitmap,我们可以方便的加载bitmap图片,而无需考虑oom等问题。通过finalDB模块,我们一行代码就可以对android的sqlite数据库进行增删改查。通过FinalHttp模块,我们可以以ajax形式请求http数据。详情请通过以下网址查看。
Afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用;
使用finalBitmap,无需考虑bitmap在android中加载的时候oom的问题和快速滑动的时候图片加载位置错位等问题。
Afinal的宗旨是简洁,快速。约定大于配置的方式。尽量一行代码完成所有事情。
项目地址:https://github.com/yangfuhai/afinal
功能:
一个android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过finalActivity,我们可以通过注解的方式进行绑定ui和事件。通过finalBitmap,我们可以方便的加载bitmap图片,而无需考虑oom等问题。通过finalDB模块,我们一行代码就可以对android的sqlite数据库进行增删改查。通过FinalHttp模块,我们可以以ajax形式请求http数据。
优点:功能比较全面,文档完善,代码效率比较高。
缺点:没有项目demo,框架的时间比较久,代码冗余比较多(这也是无可避免的),文档比较老跟不上代码更新进度。
(这个评价是其他高人评的,他自己也有写了框架。我个人觉得以前Afinal算是经典了 用的人多)。
二、 xUtils
Git地址:https://github.com/wyouflf/xUtils
xUtils:可以说是Afinal的升级版。
xUtils 包含了很多实用的android工具。
xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响...
xUitls 最低兼容android 2.2 (api level 8)
三、 ThinkAndroid
项目地址:https://github.com/white-cat/ThinkAndroid
官方介绍:
ThinkAndroid是一个免费的开源的、简易的、遵循Apache2开源协议发布的Android开发框架,其开发宗旨是简单、快速的进行Android应用程序的开发,包含Android mvc、简易sqlite orm、ioc模块、封装Android httpclitent的http模块,具有快速构建文件缓存功能,无需考虑缓存文件的格式,都可以非常轻松的实现缓存,它还基于文件缓存模块实现了图片缓存功能,在android中加载的图片的时候,对oom的问题,和对加载图片错位的问题都轻易解决。他还包括了一个手机开发中经常应用的实用工具类,如日志管理,配置文件管理,android下载器模块,网络切换检测等等工具
优点:功能看起来比较完善。个人觉得名字起的好。
缺点:从2013年就停止维护了,没有项目文档。
四、 LoonAndroid
官方介绍:
如果你想看ui方面的东西,这里没有,想要看牛逼的效果这里也没有。这只是纯实现功能的框架,它的目标是节省代码量,降低耦合,让代码层次看起来更清晰。整个框架一部分是网上的,一部分是我改的,为了适应我的编码习惯,还有一部分像orm完全是网上的组件。在此感谢那些朋友们。 整个框架式的初衷是为了偷懒,之前都是一个功能一个jar,做项目的时候拉进去,这样对于我来说依然还是比较麻烦。最后就导致我把所有的jar做成了一个工具集合包。 有很多框架都含有这个工具集合里的功能,这些不一定都好用,因为这是根据我个人使用喜欢来实现的,如果你们有自己的想法,可以自己把架包解压了以后,源码拉出来改动下。 目前很多框架都用到了注解,除了androidannotations没有入侵我们应用的代码以外,其他的基本上都有,要么是必须继承框架里面的activity,要么是必须在activity的oncreat里面调用某个方法。 整个框架式不同于androidannotations,Roboguice等ioc框架,这是一个类似spring的实现方式。在整应用的生命周期中找到切入点,然后对activity的生命周期进行拦截,然后插入自己的功能。
开源地址:https://github.com/gdpancheng/LoonAndroid
功能:
1自动注入框架(只需要继承框架内的application既可)
2图片加载框架(多重缓存,自动回收,最大限度保证内存的安全性)
3网络请求模块(继承了基本上现在所有的http请求)
4 eventbus(集成一个开源的框架)
5验证框架(集成开源框架)
6 json解析(支持解析成集合或者对象)
7 数据库(不知道是哪位写的 忘记了)
8 多线程断点下载(自动判断是否支持多线程,判断是否是重定向)
9 自动更新模块
10 一系列工具类
第一篇 nginx-- port_in_redirect off配置服务器造成 很大的威胁,后端端口暴露出来 规则描述:
可以从Nginx的核心模块中得知,如果请求发生重定向,Nginx默认的情况下,是会在重定向的URL后自动添加Nginx当前站点监听的端口。这样明显会对服务器造成 很大的威胁,后端端口暴露出来,就可能会被人直接对这个端口进行诸如CC类攻击。
根据:
审计描述:
检查nginx.conf文件,是否存在以下配置:
http { ... #Nginx will not add the port in the url when the request is redirected #port_in_redirect off; ... Server { ... } ... } 修改建议:
1、在配置文件Nginx.conf中的http段、或server段或location端增加禁止指令,建议在http段添加,如下:
http { ... #Nginx will not add the port in the url when the request is redirected port_in_redirect off; ... Server { ... } ... } 检测用例信息:
检测描述
期望结果
检测结果
工厂模式优缺点分析
function createPerson(name, age, sex) { var p = new Object(); p.name = name; p.age = age; p.sex = sex; p.sayName = function() { console.log("我的名字是:" + this.name); } return p; } 优点:能够复用
缺点:1.无法识别对象类型; 2.每个对象都有自己的 sayName 函数,函数不能共享,造成内存浪费
原因:造成无法识别对象类型的原因
p 对象是在 createPerson 中重新定义的 new Object(),因此 createPerson 就不是 p 对象的原型了。
var per1 = createPerson("张三", 30, "男"); var per2 = createPerson("李四", 40, "男"); console.log(per1 instanceof createPerson);//false console.log(per2 instanceof createPerson);//false console.log(per1 instanceof Object);//true console.log(per2 instanceof Object);//true 举例说明缺点1带来的问题:
直接下载完整github库的办法(包括sub模组):
https://www.cnblogs.com/walker-lin/p/11060621.html
无法打开desktop-sharing:
https://blog.csdn.net/qq_38129331/article/details/107859137
闪退:
https://blog.csdn.net/weixin_44967177/article/details/107869100
在jetson上安装cuda、cudnn、opencv
https://www.jianshu.com/p/141c7e48dc6c
官方提供的jetson的很多资源:
https://elinux.org/Jetson_Zoo
在jetson上编译onnxruntime
https://blog.csdn.net/xccccz/article/details/110309432
https://www.onnxruntime.ai/docs/how-to/build.html#execution-provider-shared-libraries
在jetson上编译Qt5.12.9
https://blog.csdn.net/GeForeverr/article/details/109160215
其中qt的编译配置文件最好改成这样,否则有可能会无法启动具有ui界面的程序
(我这边的话,linuxfb用不了,要用xcb才行,所以需要改一下;在远程登陆的桌面中,直接运行不了,需要加上命令 [-platform xcb])
#!/bin/sh #为防止污染qt的源文件文件夹,可以在另外的地方新建文件夹,然后指定好configure的相对路径 ../qt-everywhere-src-5.12.9/configure \ -prefix /opt/qt-5.12.9-arm \ -confirm-license \ -opensource \ -release \ -make libs \ -xplatform linux-aarch64-gnu-g++ \ -pch \ -qt-libjpeg \ -qt-libpng \ -qt-zlib \ -linuxfb \ -xcb \ -opengl es2 \ -no-opengl \ -no-sse2 \ -no-cups \ -no-glib \ -no-dbus \ #-no-xcb \ #-no-separate-debug-info \ 在jetson上面使用onnxruntime
https://blog.csdn.net/XCCCCZ/article/details/110356437
MySQL实例内存占用分类 服务器级别(全局),主要内存占用部分
query_cache_size = 64M
innodb_additional_mem_pool_size = 32M
innodb_buffer_pool_size = 1G
innodb_log_buffer_size = 16M
key_buffer_size = 256M
线程级别
#net_buffer_length = 16K
thread_stack = 256K
#query_prealloc_size = 8K
binlog_cache_size = 2M
binlog_stmt_cache_size = 64K
会话级别(每个线程分配一次)
read_rnd_buffer_size = 16M
sort_buffer_size = 8M
bulk_insert_buffer_size = 64M
#preload_buffer_size = 32K
会话级别(每个线程分配多次)
read_buffer_size = 2M
join_buffer_size = 8M
tmp_table_size = 1024M
MySQL最大可使用内存(M): select (@@key_buffer_size +@@innodb_buffer_pool_size + @@tmp_table_size + @@max_connections*(@@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size + @@join_buffer_size + @@binlog_cache_size + @@thread_stack) )/1024/1024 as “Total_AllMem result”;
首先vue中的store.js中的内容应该大家都熟悉 我还是贴一下代码吧
import Vue from 'vue' import Vuex from 'vuex' import persistedState from 'vuex-persistedstate' Vue.use(Vuex) export default new Vuex.Store({ state: { userInfo: null, token: '' }, mutations: { saveToken(state, token) { state.token = token }, saveUserInfo(state, info) { state.userInfo = info }, clearUserInfo(state) { state.userInfo = null } }, actions: {}, modules: {}, plugins: [persistedState({ key: 'openrationManagement' })] }) 这个应该是最基础的代码 就两个值 一个保存用户信息,一个清理用户信息 还有一个保存toekn 的信息
那我们要如何使用呢?
其实最开始我的写法是这样的
//这是提交保存用户信息;其实就一句话搞定 this.$store.commit('saveUserInfo', this.form) //那我们要使用userInfo 如何使用呢? //也是一句话搞定 this.
<keep-alive :include="cachedViews"> <router-view :key="key" /> </keep-alive> computed: { cachedViews() { return this.$store.state.tagsView.cachedViews }, key() { return this.$route.path } } 使用 vue-devtools 查看,发现 AppMain 里缓存了两个页面组件,此时没有问题,页面组件都被缓存了(此时路由地址在 单位菜单管理 下面)
但是当我切换到“菜单管理”时,发现只有 Menu 页面组件被缓存了,UnitMenu 页面组件的缓存没了
造成的后果是:菜单管理 页面正常缓存,而 单位菜单管理 页面没有被缓存起来,来回切换菜单时,单位菜单管理 总是会刷新。
继续查看 cachedViews 里保存的值,发现名字叫做 Unitmenu ,而我 单位菜单管理 export 里的 name 叫做 UnitMenu
好吧,知道原因了,字符串不相等,页面中 export 里的 name 值必须跟 cachedViews 里的值一模一样,否则不会被缓存
一、没有导入库函数导致的警告 Error:L6216E:Undefined symbol UART3(refered from uart3.0) 错误:L6216E:未定义符号UART3(来自uart3.0)Not enough information to list image symblos 没有足够的信息来列出图像符号Not enough information to list load addresses in the image map 没有足够的信息在图像映射中列出加载地址Not enoughinformation,0 warning and 1 error messages 信息不足,0个警告和1个错误消息 错误原因:没有将相应的库函数包含进去。
解决: 导入相应的库函数
二、编译器优化导致的警告 描述:变量'd'定义但从未使用,或者是,虽然这个变量你使用了,但编译器认为变量d所在的语句没有意义,编译器把它优化了.
解决:仔细衡量所定义的变量d是否有用,若是认定变量d所在语句有意义,那么尝试用volatile关键字修饰变量d,若是真的没有用,那么删除掉以释放可能的内存. warning: #550-D: variable "d" was set but never used
变量已设置但从未使用
三、#101错误 error:#101:"FALSE" has already been declared in the current scope
#ifndef _GPIO_H #define _GPIO_H #include "stm32f10x_gpio.h" #ifdef ROOT #define EXT #define ext #else #define EXT Extern #define ext extern #endif .
1. 加密和认证 在认识公私钥之前,首先我们需要区分加密和认证这两个基本概念:
加密是将数据资料加密,使得非法用户即使取得加密过的资料,也无法获得正确的资料内容,所以数据加密可以保护数据,防止监听攻击,其重点在于数据的安全性。身份认证是用来判断某个身份的真实性,确认身份后,系统才可以依据不同的身份赋予不同的权限,其重点在于用户的真实性。两者的侧重点是不同的。
1.1 对称加密和非对称加密的主要区别 对称加密和非对称加密的区别为:密钥不同、安全性不同、数字签名不同。
密钥不同: 对称加密:对称加密加密和解密使用同一个密钥。非对称加密:非对称加密加密和解密所使用的不是同一个密钥,需要两个密钥来进行加密和解密。 安全性不同: 对称加密:对称加密如果用于通过网络传输加密文件,那么不管使用任何方法将密钥告诉对方,都有可能被窃听。非对称加密:非对称加密因为它包含有两个密钥,且仅有其中的“公钥”是可以被公开的,接收方只需要使用自己已持有的私钥进行解密,这样就可以很好的避免密钥在传输过程中产生的安全问题。 数字签名不同: 对称加密:对称加密不可以用于数字签名和数字鉴别。非对称加密:非对称加密可以用于数字签名和数字鉴别。 2. 公钥和私钥 2.1 公钥和私钥的作用 公钥和私钥的作用主要就是用来加解密和加验签,但是很多人搞不清楚公钥和私钥的区别,不知道用哪个加密、用哪个加签。下面我们先上结论,再详细解释:
公钥加密、私钥解密。私钥加签、公钥验签。 2.2 加解密 加密的目的是保证信息的保密传输,使只有具备资格的一方才能解密。
公钥和私钥是一对密钥,公钥是公开的,私钥是不公开的。假设A有一对公私钥,当B或者其他人用A的公钥对某信息进行加密,那么只有具备私钥的A可以解密该信息。
2.3 加验签 加签的目的是让收到消息的一方确认该消息是由特定方发送的。
因为私钥只存在于A,也只有A才能对消息进行加签,这个过程就叫签名。你可以理解为老干妈的私章只有老干妈才有,腾讯拿到这个章盖过的合同后,需要先确认这个合同是老干妈发过来的,但为什么腾讯还是被骗了,那是因为腾讯没有老干妈的公钥,没有对加签过的合同进行验签。公钥的作用就是验签,验证了就能知道消息的真伪。
文章目录-Shell阶段二十六-端口与服务对照表 前言端口与Web服务对照表简介 前言 端口与Web服务对照表 2端口:管理实用程序 3端口:压缩进程 5端口:远程作业登录 7端口:回显 9端口:丢弃 11端口:在线用户 13端口:时间 17端口:每日引用 18端口:消息发送协议 19端口:字符发生器 20端口:FTP文件传输协议(默认数据口) 21端口:FTP文件传输协议(控制) 22端口:SSH远程登录协议 23端口:telnet(终端仿真协议),木马Tiny Telnet Server开放此端口 24端口:预留给个人用邮件系统 25端口:SMTP服务器所开放的端口,用于发送邮件 27端口:NSW 用户系统 FE 29端口:MSG ICP 31端口:MSG验证,木马Master Paradise、HackersParadise开放此端口 33端口:显示支持协议 35端口:预留给个人打印机服务 37端口:时间 38端口:路由访问协议 39端口:资源定位协议 41端口:图形 42端口:主机名服务 43端口:who is服务 44端口:MPM(消息处理模块)标志协议 45端口:消息处理模块 46端口:消息处理模块(默认发送口) 47端口:NI FTP 48端口:数码音频后台服务 49端口:TACACS登录主机协议 50端口:远程邮件检查协议 51端口:IMP(接口信息处理机)逻辑地址维护 52端口:施乐网络服务系统时间协议 53端口:dns域名服务器 54端口:施乐网络服务系统票据交换 55端口:ISI图形语言 56端口:施乐网络服务系统验证 57端口:预留个人用终端访问 58端口:施乐网络服务系统邮件 59端口:预留个人文件服务 60端口:未定义 61端口:NI邮件 62端口:异步通讯适配器服务 63端口:whois++ 64端口:通讯接口 65端口:TACACS数据库服务 66端口:Oracle SQL*NET 67端口:引导程序协议服务端 68端口:引导程序协议客户端 69端口:小型文件传输协议 70端口:信息检索协议 71端口:远程作业服务 72端口:远程作业服务 73端口:远程作业服务 74端口:远程作业服务 75端口:预留给个人拨出服务 76端口:分布式外部对象存储 77端口:预留给个人远程作业输入服务 78端口:修正TCP 79端口:查询远程主机在线用户等信息 80端口:http,用于网页浏览,木马Executor开放此端口 81端口:HOST2名称服务 82端口:传输实用程序 83端口:模块化智能终端ML设备 84端口:公用追踪设备 85端口:模块化智能终端ML设备 86端口:Micro Focus Cobol编程语言 87端口:预留给个人终端连接 88端口:Kerberros安全认证系统 89端口:SU/MIT telnet(终端仿真网关) 90端口:DNSIX 安全属性标记图 91端口:MIT Dover假脱机 92端口:网络打印协议 93端口:设备控制协议 94端口:Tivoli对象调度 96端口:DIXIE协议规范 97端口:快速远程虚拟文件协议 98端口:TAC新闻协议 99端口:后门程序ncx99开放此端口 100端口:未知用途 101端口:NIC 主机名称服务 102端口:消息传输代理 103端口:Genesis 点对点传输网络 105端口:信箱名称服务 106端口:3COM-TSMUX开放端口 107端口:远程Telnet服务 108端口:SNA 网关访问服务 109端口:POP2服务器开放此端口,用于接收邮件 110端口:POP3服务器开放此端口,用于接收邮件 111端口:SUN公司的RPC服务所有端口 112端口:McIDAS 数据传输协议 113端口:认证服务,用于鉴别TCP连接的用户 114端口:音频新闻多点服务 115端口:简单文件传输服务 116端口:ANSA REX 通知 117端口:UUCP 路径服务 118端口:SQL 服务 119端口:NEWS新闻组传输协议,承载USENET通信 121端口:木马BO jammerkillahV开放端口 122端口:SMAKY网络 123端口:网络时间协议,蠕虫病毒会利用,一般关闭 128端口:GSS X许可认证 129端口:密码生成器协议 130端口:Cisco软件开放端口 131端口:Cisco软件开放端口 132端口:Cisco软件开放端口 133端口:统计服务 134端口:INGRES-网络服务 135端口:DCOM服务,冲击波病毒利用,不能关闭 136端口:命名系统 137端口:NETBIOS协议应用,为共享开放 138端口:NETBIOS协议应用,为共享开放 139端口:NETBIOS协议应用,为共享开放 140端口:EMFIS数据服务 141端口:EMFIS控制服务 143端口:Interim邮件访问协议 144端口:UMA软件开放端口 145端口:UAAC协议 149端口:AED 512仿真服务 150端口:SQL(结构化查询语言)-网络 152端口:后台文件传输协议 156端口:SQL(结构化查询语言)服务 158端口:PC邮件服务器 159端口:NSS-路由 160端口:SGMP-陷阱 161端口:简单网络管理协议 162端口:SNMP陷阱 163端口:CMIP/TCP 管理 164端口:CMIP/TCP 代理 166端口:Sirius系统 169端口:发送 170端口:网络附言 177端口:x显示管理控制协议,入侵者通过它访问X-windows操作台 178端口:NextStep Window 服务 179端口:边界网关协议 180端口:图表 181端口:统一 184端口:OC服务器 185端口:远程-KIS 186端口:KIS 协议 187端口:应用通信接口 189端口:队列文件传输 190端口:网关进入控制协议 191端口:Prospero 目录服务 192端口:OSU 网络监视系统 193端口:Spider 远程控制协议 194端口:多线交谈协议 197端口:目录地址服务 198端口:目录地址服务监视器 200端口:IBM系统资源控制器 201端口:AppleTalk(Mac机所用的网络协议)路由保证 202端口:AppleTalk(Mac机所用的网络协议)Name Binding 203端口:AppleTalk(Mac机所用的网络协议)未用端口 204端口:AppleTalk(Mac机所用的网络协议)回显 205端口:AppleTalk(Mac机所用的网络协议)未用端口 206端口:AppleTalk(Mac机所用的网络协议)区信息 207端口:AppleTalk(Mac机所用的网络协议)未用端口 208端口:AppleTalk(Mac机所用的网络协议)未用端口 209端口:快速邮件传输协议 210端口:ANSI(美国国家标准协会)Z39.
初识C#,对lambda中return一直很疑惑,到底返回了什么?个人理解,return只是一个函数的返回,而且只能返回bool类型,表示是否满足条件,满足条件的会被筛选出来。
activity闪退_关于android studio中Activity切换闪退的问题 原文链接:activity闪退https://blog.csdn.net/weixin_33208391/article/details/112136633
初学Kotlin,按书本学的,学习过程中观前不顾后,看了后面看不到前面。以致走很多弯路。初学者都是这样的。有个老师指点一下一两句话的问题,而自己查找,要找好久才能找得到答案。尽管这些答案在高手看来是很低级的问题,都懒地回答。
从MainActivity(activity_main.xml)切换到MainActivity(activity_main2.xml)这个闪退,
1.检查代码是否有错漏(但是没报错)
2.配置manifests / AndroidManifest.xml这个文件
< application >
<activity android:name=’’.MainActivity’’>
…
< /activity >
<activity android:name=".MainActivity2"> (注释:MainActivity2(activity_main2)为跳转目的页面) </activity > < /application>
文章目录- Shell阶段九-数据库被攻击&&恢复 如果有帮助的话,打赏一下哎,很不容易前言当MySQL数据库遭到攻击篡改后,使用备份和binlog进行数据恢复一、发现问题二、解决方法三、找备份及时间点四、具体的恢复操作1.从备份机拷贝备份:2.恢复测试机 解压:3.恢复测试机导入(测试恢复库中之前没有db_name这个库):4.将主库的Binlog拷贝到恢复测试机:5.使用MySQLBinlog 生成SQL脚本:6.Binlog生成的SQL脚本导入:7.导入完成后检查数据正确性:8、将该库导出,并压缩:9.恢复测试的数据导入到线上主库中: 总结 Shell阶段九-数据库被攻击&&恢复) 如果有帮助的话,打赏一下哎,很不容易 前言 当MySQL数据库遭到攻击篡改后,使用备份和binlog进行数据恢复 主要描述了MySQL遭到攻击篡改数据,利用从库的备份和主库的Binlog进行不完全恢复。
一、发现问题 今天是2014-09-26,开发大清早就说昨晚数据库遭到了攻击。数据库中某文章表的文章内容字段遭到篡改,全部改成了同一篇文章。
通过查看日制 发现 数据是在 2014-09-25 21:53:57 遭到篡改。
所有的内容全部被改成了如下:
我把文章贴出来,先谴责一下,很可能是某旅游社的人为了打广告 雇人干的。
二、解决方法 这个库我们是每天凌晨备份,保留30天的备份。主库的Binlog保留时间为7天。
因此很容易想到的方法是将从库2014-09-25凌晨的备份拿出来恢复,然后通过主库的Binlog通过时间段来筛选出凌晨至2014-09-25 21:53:56的所有更改,之后的数据,经业务确认,可以舍弃掉。或者后面再通过其他方法慢慢将这部分数据找出来。但是当务之急,是立马恢复数据库。
三、找备份及时间点 在备份的从库上检查备份:
crontab -l #0 3 * * * /data/opdir/mysqlbak/backup_mysqldump.sh 6084 >> /data/opdir/mysqlbak/6084/mysql-bakup.log 2>&1 发现备份任务让注释了
查看备份文件:
[root@localhost 6084]# ll total 128 drwxr-xr-x 2 root root 4096 Aug 25 03:13 20140825 drwxr-xr-x 2 root root 4096 Aug 26 03:13 20140826 drwxr-xr-x 2 root root 4096 Aug 27 03:13 20140827 drwxr-xr-x 2 root root 4096 Aug 28 03:13 20140828 drwxr-xr-x 2 root root 4096 Aug 29 03:13 20140829 drwxr-xr-x 2 root root 4096 Aug 30 03:13 20140830 drwxr-xr-x 2 root root 4096 Aug 31 03:13 20140831 drwxr-xr-x 2 root root 4096 Sep 1 03:13 20140901 drwxr-xr-x 2 root root 4096 Sep 2 03:13 20140902 drwxr-xr-x 2 root root 4096 Sep 3 03:13 20140903 drwxr-xr-x 2 root root 4096 Sep 4 03:13 20140904 drwxr-xr-x 2 root root 4096 Sep 5 03:13 20140905 drwxr-xr-x 2 root root 4096 Sep 6 03:13 20140906 drwxr-xr-x 2 root root 4096 Sep 7 03:13 20140907 drwxr-xr-x 2 root root 4096 Sep 8 03:13 20140908 drwxr-xr-x 2 root root 4096 Sep 9 03:13 20140909 drwxr-xr-x 2 root root 4096 Sep 10 03:13 20140910 drwxr-xr-x 2 root root 4096 Sep 11 03:13 20140911 drwxr-xr-x 2 root root 4096 Sep 12 03:13 20140912 drwxr-xr-x 2 root root 4096 Sep 13 03:13 20140913 drwxr-xr-x 2 root root 4096 Sep 14 03:13 20140914 drwxr-xr-x 2 root root 4096 Sep 15 03:13 20140915 drwxr-xr-x 2 root root 4096 Sep 16 03:13 20140916 drwxr-xr-x 2 root root 4096 Sep 17 03:13 20140917 drwxr-xr-x 2 root root 4096 Sep 18 03:14 20140918 drwxr-xr-x 2 root root 4096 Sep 19 03:14 20140919 drwxr-xr-x 2 root root 4096 Sep 20 03:13 20140920 drwxr-xr-x 2 root root 4096 Sep 21 03:13 20140921 drwxr-xr-x 2 root root 4096 Sep 22 03:14 20140922 drwxr-xr-x 2 root root 4096 Sep 23 18:33 20140923 -rw-r--r-- 1 root root 5475 Sep 23 18:33 mysql-bakup.
在Windows中安装虚拟机+Centos
https://www.bilibili.com/video/BV1dW411M7xL
网上教程中, 提到要去BIOS中, 修改设置开启虚拟化设备支持, 否则Centos会安装不上去
1. 安装 https://www.vmware.com/cn.html
Workstation Player
用于在 Windows 或 Linux PC 上运行第二个操作系统的简单工具,可供个人免费使用
Workstation pro15,可以安装在win7上
Workstations pro16,不可以安装在win7上
2. 安装 1、安装 Workstation pro15
2、安装 vmware tools
3. 黑屏处理 3.1 方式1 1、以管理员身份打开命令提示符,输入
netsh winsock reset 2、重启电脑
不解决问题
3.2 方式2 编辑虚拟机设置中
设备-显示器-加速3D图形,取消对勾
解决问题
3.3 方式3 编辑虚拟机设置中
编辑-首选项-设备-虚拟打印机,
选择启动虚拟打印机,重启电脑
黑屏可能原因如下:
虚拟机和主机之间的通信,基本上是以socket的方式进行通信的(这里socket 泛指一切socket,包括本地的、网络的等等)
某个程序通过LSP给系统的TCP/IP stack 注入了自己的DLL,
如果程序退出时,没有把这个DLL收回来,或者回收失败、没有彻底回收等,
那么这DLL残留的东西影响了整个TCP/IP stack,而且是永久性的。
每个socket收发的数据包是要经过TCP/IP stack的,
这个DLL 可能会对这些 socket 的数据包做了些什么操作(比如修改数据、直接丢弃等等),然后所以你的虚拟机就黑屏了
netsh winsock reset这条命令会重置,所以那些被注入的 DLL 就被清理掉了,所以一切都是最初的模样。
这篇技术贴讲怎样在Django的框架下导出Excel, 最开始打算用ajax post data 过去,但是发现不行,所以改用了get的方式。如果只有一个id(pk)那用get的方式很简单就可以访问对应的view section,但是如果是多个ids,我用的是session,大家还有其他好的例子吗?希望一起讨论。
Python3.5 Django 1.10, sqlite3, windows 10
virtualenv export_excel <--- create a virtualenv for django
cd export_excel <--- Go into the export_excel folder
Script\active <--- activate env environment.
once activate the environment, in the windows would be liked as above.
pip install django.
pip install django-bootstrap3. <-- bootstrap3 for django.
pip install xlsxwriter. <-- this uses for excel export.(用xlsxwriter 这个Python 库)
urls.py
"""export_excel URL Configuration The `urlpatterns` list routes URLs to views.
背景:目前在做一个视觉测试系统,需要做一个界面,将相机获取的图像,以及测试过程中的数据呈现在界面上,在我印象里,做界面就用qt吧,直到这个月真要开始做界面了,我的领导给我建议用imgui做界面,这个东西我没有听说过还,他说realsense的SDK中的界面部分就是用imgui做的,让我参考一下,之前吧,我对于新的事物总是有恐惧感,但是慢慢的面对新的事物,我内心的这种恐惧感没有那么强了,我感觉我之所以有恐惧感是因为害怕自己搞不定他,但是呢,困难远没有你想象中的那么强大,只要你有一颗强大的内心,绝大多数困难都是可以被解决的。
一、认识imgui
1. 首先是在github上下载代码,https://github.com/ocornut/imgui,这里还有realsense的sdk:https://github.com/IntelRealSense/librealsense 可以参考。
二、VS2017上运行imgui的例程
对于代码这东西,我一般都是先把相关的环境配置好,把程序跑起来,看了效果,才能安心的去深入了解这个东西本身,对于imgui,我也是这么做的。我的工作环境是:win10+VS2017。也就是说我需要在这样的环境下配置imgui需要的环境,然后把他的例程跑起来。
图1. imgui-master目录下的文件
图1中是下载下来的imgui-master目录下的文件展示,使用初期我们只需要关注图像标记的这三个部分就可以了,现在先不介绍没一部分都是做什么的。
图2. examples中的例子
图2是imgui-master中的examples中的例子展示,可见这个目录下有一个.sln文件,我们可以双击这个文件使用电脑上安装的VS直接打开工程。打开后如图3所示。
图3. 使用VS打开imgui-master中的examples中的工程
经过查看这个工程的属性中已经将需要的路径,库都配置好了,如果不出其他问题,按理说可以直接编译运行了。
图4. include directories
图5. Lib Directories
图6. Aditional Dependences
这个工程运行的结果如下:
图7. Directx9例程运行效果
下一篇文章中将介绍:如何自己配置imgui环境。
首先你想自己搭建hadoop平台,可以按照我的上篇博客一步一步来,搭建好之后就可以安装Hive环境. 手把手教你搭建你自己电脑的Hadoop平台
安装Hive相对来说比安装hadoop轻松多了,但是有可能也会遇到以下这几种问题: 1. java.sql.SQLException: Access denied for user ‘root’@‘localhost’ (using password: YES) 这种情况的出现可能是因为你的mater上没有访问mysql的权限,这种比较好解决.
进入你的mysql,然后赋权限
grant all privileges on *.* to 'mysql账户' @"你的主机名" identified by "mysql密码"; 举例: grant all privileges on *.* to 'root' @"master" identified by "xxx"; 你有几台虚拟机 就需要赋几天机器的权限!
2. Terminal initialization failed; falling back to unsupported java.lang.Incomp 如果报这种错误,需要删除hadoop目录下的一个文件,重启hadoop和hive即可
删除文件: $HADOOP_HOME/share/hadoop/yarn/lib/jline-0.9.94.jar
别问我为什么? 问就是白问!!!
转载于:https://www.cnblogs.com/wys-373/p/11459343.html
3.如果你安装完MySQL设置root密码报错如下 error: 'Access denied for user ‘root’@‘localhost’ (using password: NO)' 你可以启动安全模式 去修改你的mysql登陆密码
# 停止mysql服务 systemctl stop mysqld.
一、什么是鸿蒙 鸿蒙即 HarmonyOS ,是华为公司推出的支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备的分布式操作系统,并且它提供了多语言开发的 API,支持 Java、XML、C/C++、JS、CSS、HML(类 html 的鸿蒙自己的标记语言)等开发语言,而且它提供多种响应式布局方案,支持栅格化布局,可以使用同一套代码部署在手机手表平板等多种不同尺寸屏幕的设备上。
二、开发准备 2.1 环境安装 开发鸿蒙软件需要用到 HUAWEI DevEco Studio,它提供了模板创建、开发、编译、调试、发布等服务。
1、登录 HarmonysOS 应用开发门户,点击右上角注册按钮,注册开发者帐号。
2、进入 HUAWEI DevEco Studio 产品页,登录华为开发者账号后下载 DevEco Studio 安装包并进行安装。
3、启动 DevEco Studio,根据工具引导下载 HarmonyOS SDK。 4、下载 HarmonyOS SDK 成功后会进入欢迎页,点击欢迎页中的 Configure > Settings 打开设置窗口,点击 Apparance&behavior > System settings > HarmonyOS SDK,选中 JS SDK 进行下载。 至此开发环境安装完成。
2.2 新建项目 点击菜单栏中的 File > New > New Project 选择需要开发的项目设备,然后选择 Empty Featrue Ability(JS) 后,点击 Next,此时会出现项目的信息配置 点击 Finish,一个新的项目就被创建出来了。
2.3 项目目录 使用 JS SDK 进行开发的话,需要关注的是 entry > src > main > js 文件夹,其中:
同步FIFO的实现 首先是同步的实现,只需要一个时钟用来控制读写。
同步 FIFO 实现较为直接,如下图所示,一个 FIFO 内部实现了 RAM 和一个控制读写的控制端,和普通的随机存储器不一样的是,FIFO 内部需要自动产生读写地址。
控制端产生空、满信号。因此如何实现控制端去产生空满信号是主要需要考虑的地方。通常空满的判断是通过读、写地址进行的。
第一种思路,利用读写地址的大小来判断空、满 方法很简单,设置一个信号量 factor 来表识空满,每次读一个数据则令 factor - 1,写一个数据则令其+1。实现代码如下:
module fifo #( parameter DATA_WIDTH=16, parameter ADDR_WIDTH=8 )( input clk , input rst_n , input write_en , input [DATA_WIDTH-1:0] write_data , input read_en , output reg [DATA_WIDTH-1:0] read_data , output reg empty , output reg full , output [ADDR_WIDTH-1:0] counter ); reg [ADDR_WIDTH-1:0] read_addr; reg [ADDR_WIDTH-1:0] write_addr; reg [ADDR_WIDTH-1:0] factor; assign counter = factor; wire write_allow = (write_en && !
镂空剪纸效果 你的浏览器居然不支持Canvas?!赶快换一个吧!!
window.onload = function(){ var canvas = document.getElementById("canvas");
canvas.width = 800; canvas.height = 600;
var context = canvas.getContext("2d"); context.fillStyle = "#FFF";
context.fillRect(0,0,800,600);
context.beginPath(); context.rect(200,100,400,400);
drawPathRect(context, 250, 150, 300, 150); drawPathTriangle(context, 345, 350, 420, 450, 270, 450);
context.arc(500, 400, 50, 0, Math.PI * 2, true); context.closePath();
context.fillStyle = "#058";
context.shadowColor = "gray"; context.shadowOffsetX = 10;
context.shadowOffsetY = 10; context.shadowBlur = 10;
context.fill();
};
//逆时针绘制矩形 function drawPathRect(cxt, x, y, w, h){
许多面试过开发岗位的小伙伴都知道,“缓存和数据库的双写一致性”是面试的重灾区,我们经常会面对面试官的redis连环提问。本期小树懒来给大家总结一下缓存和数据库一致性相关的面试题,让大家在面试时不再“无话可说”。
一、什么是缓存? 存储速度不同。缓存是将低速存储的结果暂时存储在高速存储中的技术。
如图所示,金字塔上的存储可以作为下面存储的缓存。
二、为什么需要缓存? 在高并发性的业务场景中,数据库大多是用户并发访问的最弱环节。因此,有必要使用redis进行缓冲操作,以便首先访问redis,而不是直接访问MySQL等数据库。
该商业场景,主要是解决从Redis缓存中读取数据的问题,一般是按照下图的流程进行商业操作。
由于其高并发性和高性能的特点,缓存在项目中得到了广泛的应用。在使用缓存时,通常会面临更新问题。当数据源发生变化时,如何更新到数据库和缓存中,并尽可能保证安全性和性能。
三、如何更新缓存? 方法一:CacheAsidePattern。
CacheAsidePattern是最经典的缓存+数据库读写模式。
标准Pattern,facebook就是这样使用的,具体流程图如下:
故障:应用程序首先从cache获取数据,如果没有获取,则从数据库中获取数据,成功后,放入缓存。
命中:应用从cache中获取数据,获取后返回。
更新:先将数据存储在数据库中,成功后缓存无效。
阅读部分大家都很熟悉,先阅读cache,如果cache没有命中,去阅读存储介质,如底层数据库,返回数据,并设置缓存。
下面我们讨论三种更新策略:
先更新缓存,再写数据库。
首先更新数据库,然后更新缓存。
首先删除缓存,然后更新数据库。
(1) 先更新缓存,再写数据库。
同时,如果要求A和要求B更新,就会出现。
线程A更新了数据库。
线程B更新了数据库。
线程B更新缓存。
线程A更新缓存。
因此,请求A更新缓存应该比请求B更新缓存更早,但由于网络等原因,B更新缓存比A更早。这样会导致脏数据,所以没有考虑。
(2)在缓存之前更新数据库。
这个方案,大家都很反对。为什么呢?原因如下。
有两点:
如果你写数据库的场景较多,而读数据场景较少的业务需求,采用这个方案就会导致,数据压根还没有读到,缓存就会频繁更新,浪费性能。
写入数据库的值不是直接写入缓存,而是通过一系列复杂的计算写入缓存。那么,每次写入数据库,再次计算写入缓存的值无疑是浪费性能的。显然,删除缓存更合适。
(3)在更新数据库之前删除缓存。
这个计划会导致不一致的原因是。与此同时,一个要求A进行更新操作,另一个要求B进行查询操作。然后会出现以下情况:
要求A写作,删除缓存。请求B查询,发现没有缓存。请B到数据库查询以获得旧值。请求B将旧值写入缓存。请求A将新值写入数据库。 这种情况会导致不一致。此外,如果不使用为缓存设置过期时间策略,数据将永远是脏数据。
那怎样解决呢?采用延迟双删策略。
伪代码如下
public void write(String key,Object data){ redis.delKey(key); db.updateData(data); Thread.sleep(1000); redis.delKey(key); }} 方法二:Read/WriteThroughPattern。
ReadThrough是在查询操作中更新缓存,也就是说,当缓存失效时(过期或更换LRU),CacheAside由调用者负责将数据加载到缓存中,而ReadThrough则由缓存服务自己加载,从而使应用者更加透明。WriteThrough是双写的。
方法三:WriteBehindCachingPattern。
WriteBehind又称WriteBack,可能是先更新cache,然后批量更新数据库。
了解更多数据库知识,点击全文链接:https://www.shulanxt.com/doc/mysqldoc/sjcjms
一、微信小程序引入echarts过大最佳解决方案 微信上传时代码包大小限制为2MB,但是当我们引入echarts以后,单echarts代码包已经973KB,因此再结合额外的业务代码以及其他资源很有可能超过2MB的限制,那么我们如何解决这个问题呢,方案有两种:
1、压缩echarts的大小 从echarts官网下载微信小程序集成DEMO以后,官方包内容如下:(ECharts官方文档链接)
通过各个文件大小判断,我们最佳方式就是压缩echarts.js这个文件的大小,其他文件原始大小也不大,压缩后效果有限。
我们通过官网文档的下载中官方自定义构建可以下载经过UglifyJS压缩后的echarts,也可以选择只含有实际项目使用到图表的echarts.js(因为默认通过官方DEMO下载的ec-canvas文件夹中含有微信小程序引入echarts的全部内容,但实际项目中可能用到了柱状图、折线图很多用不到的图表/工具没必要放在项目中占用代码大小)
大家可以根据实际项目情况选择用到的echarts组件进行构建,下图时我项目中使用到的组件自定义构建内容:
选择完成以后,点击【下载】就可以下载我们自定义构建的echart文件了
注:勾选代码压缩以后下载的文件名称为:echarts.min.js
未勾选代码压缩以后下载的文件名称为:echarts.js
然后我们将自定义构建下载的echarts.min.js重命名为echarts.js再替换项目ec-canvas目录下的echarts.js就可以了,访问项目发现echarts相关图表渲染正常,控制台无任何异常输出,这样我们就将原本大小将近1000KB的echarts压缩了一半。
注:自定义构建下载的echarts.min.js重命名后放入项目后可能会出现无法渲染图表、控制台报undefined、找不到echart部分函数错误,说明我们在项目中所使用到的echarts的功能在自定义构建中没有选择到,这个时候需要我们认真核对自定义构建是否漏选了项目中使用到的功能。
2、使用分包 分包功能各位可以直接参考微信小程序官方文档就可以解决这个问题了:官方链接
二、echarts在微信开发者工具中不跟随滑动 在通过微信开发者工具的模拟器查看echarts时,我们会发现图表没有随着滚动条而滑动,但是在进行真机模拟的时候却又一切正常,这个时候我们可以在wxml的canvas中添加一个属性解决这个问题:
force-use-old-canvas="true" 示例:
<ec-canvas force-use-old-canvas="true" id="{{echartData.recentTrendBar.id}}" canvas-id="mychart-multi-bar" ec="{{ echartData.recentTrendBar }}"></ec-canvas> 添加该属性后,控制台会提示如下信息,但是在模拟器中图表可以正常滑动了。
开发者强制使用旧canvas,建议关闭 注:该属性会强制使用旧的canvas渲染,建议在开发环境中使用,在生产环境不要使用,(期待未来echarts官方能够解决这个问题);
三、使用echarts控制台提示使用canvas 2d 查看ec-canvas/ec-canvas.wxml内容如下:
<!-- 新的:接口对其了H5 --> <canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas> <!-- 旧的 --> <canvas wx:else class="ec-canvas" canvas-id="
js 逻辑层处理 data: { list: [{ id: 20, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' }, { id: 21, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' }, { id: 22, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' }, { id: 23, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' }, { id: 24, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' }, { id: 25, info: '你稍等会覅四idfh斯蒂芬和i速发货i收到回复i收到回复isdfhi是否hi收到发hi收到覅但是' } ], position: 'center', duration: 300, show: false, overlay: false, contact:{}, }, showNext(e) { const index = e.currentTarget.dataset.index this.setData({ show: true, contact: this.data.list[index] }) }, showPrev() { this.setData({ show: false }) }, onBeforeEnter(res) { console.
报错信息: gyp ERR! stack Error: Command failed: C:\Users\liufei\AppData\Local\Programs\Python\Python37\python.EXE -c import sys; print “%s.%s.%s” %
完整报错:
F:\webstorm\cloud-desktop> npm install npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. > xxhash-addon@1.4.0 install F:\webstorm\cloud-desktop\node_modules\xxhash-addon > node-gyp rebuild --ensure F:\webstorm\cloud-desktop\node_modules\xxhash-addon>if not defined npm_config_node_gyp (node "E:\node\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild --ensure ) else (node "E:\node\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" rebuild --ensure ) gyp ERR! configure error gyp ERR! stack Error: Command failed: C:\Users\liufei\AppData\Local\Programs\Python\Python37\python.
局域网 局域网的缩写是LAN,local area network,顾名思义,是个本地的网络,只能实现小范围短距离的网络通信。
(如下图)我们的家庭网络是典型的局域网。电脑、手机、电视、智能音箱、智能插座都连在无线路由器上,可以互相通信。
我们的熟悉的教室网络,也是典型的局域网 局域网的通信设备主要是交换机。交换机可以把多个本地的终端连接在一起,帮他们进行数据转发。局域网部署的时候,自己买几台交换机就可以,不需要运营商(电信联通等)提供服务。
因特网 因特网本质上就是把世界各地的局域网连通,咱们刷知乎的时候,知乎那边有个局域网,我们家有个局域网,这两个局域网就是通过因特网连起来的。想要接入因特网,需要向运营商购买1条宽带,电信联通都可以,然后通过这条宽带接入运营商,运营商再接入因特网。
广域网(Wan) 广域网是相对局域网来讲的,局域网的传输距离比较近,只能是一个小范围的。 特殊需求
如果需要长距离的传输,比如某大型企业,总部在北京,分公司在长沙,局域网是无法架设的。这时需要通信有三个解决方案。第一,通过因特网,只需要办一根宽带,就实现了通信,非常方便,现在的宽带价格也比较便宜。但是会存在数据泄露的风险,前面讲到了,因特网是一个全球人民都连进来的网,虽说大部分都是好人,但总会有些坏人,特别是商业竞争的情况下,会有黑客坏人连在因特网里盗取各种数据卖钱。所以大型企业、金融单位、各级政府单位,是不放心使用因特网来传输数据的。第二,通过广域网专线。所以为了数据安全,不能连接因特网,需要用一条自己的专用线路来传输数据,这条线路上只有自己人,不会有其他人接入,且距离很远,这个网络就叫 “广域网”广域网的缩写是WAN,Wide Area Network,支持很长距离的传输。这条专线当然不是企业自己搭电线杆架设,而是租用电信联通等运营商架设好的线路,使用费用会比因特网贵很多,带宽也比较小,但是为了安全,就要承担一些必要的成本。第三,通过VPN,VPN是虚拟专用网,是在普通的便宜的因特网上,通过数据加密,完整性验证,身份验证等多种技术手段构建的安全传输网络,实现类似专线的安全功能。 其他详细资料
传送门
传送门
摘要
广域网接入方式主要有:专线、电路交换(实现在电话交换网传输数字信号)、分组交换、VPN、无线等。WAN常见的封装协议
专用线路:PPP、HDLC
电路交换:ISDN、ADSL
分组交换:FrameRelay
广域网技术主要位于底层的3个层次,分别是物理层,数据链路层和网络层。 神奇比喻 想象你住在一个小区里,这个小区有很多栋楼,每栋楼有很多单元,每个单元有很多层,你和你的邻居之间谁也不认识谁,不知道该怎么找到对方,你们想要互相联系,只能靠写信的方式,你把信写好后交给小区的门房大爷,并且告诉他,这封信要送到1号楼1单元101,然后门房大爷负责把信送到,这个时候,整个小区可以看成一个局域网,因为大家在这个小区里使用的都是私有地址(私有IP),这个地址只有你们小区的门房大爷知道该怎么走,换个人就找不到了。如果你想要给另外一个小区的某个住户写信,因为每个小区的私有地址命名方式都不一样,假设他们小区的地址是A号楼东座302,这个时候你把信交给门房大爷,他就傻眼了,因为他不认识,所以拒绝为你送信。当然还是有解决方式的,那就是把附近小区的门房大爷全都叫到一块大家开个会,给所有门房大爷统一按照一种方式来命名,比如叫天通苑张大爷、回龙观王大爷等等,这个名字就是公有地址(公有IP),这个名字在所有门房大爷中是唯一的,一人一个不能重名,这个时候门房大爷之间就互相认识了,以后你再想给另外一个小区的住户写信,就需要告诉你们小区的门房大爷,“麻烦您把这封信交给天通苑的张大爷,再让他转交给A号楼东座302”。这个时候,附近这些小区就形成了一个广域网,广域网内包含很多个小区(局域网),小区(局域网)和小区(局域网)之间想要互相通信,就必须靠各自的门房大爷。过了段时间大家觉得这样还是很不爽,干脆把全世界的门房大爷都交到一块开个会吧,以后全世界的门房大爷们都统一起一个唯一的名字,这样全世界的人就可以自由通信了,这就叫Internet/互联网。可以说Internet/互联网是最大的广域网,但并不是每个广域网都叫Internet/互联网。一些特殊需求:你就是想要和天通苑那个A号楼东座302直接通信,不想通过门房大爷,所以你在你家和他家之间拉了条钢丝(专线),你把信写好以后吊在篮子里直接给他送了过去,这种方式效率很快,也很安全,但是成本也很高。或者你可以雇一个专职通信员(VPN),他只负责给你送信,信一直放在他身上不需要倒手,由他去向门房大爷问路,并且亲自送过去,这样安全了很多,当然成本同样很高。再来说一下“广域网由交换机连接”和“广域网需要路由交换和分组转发”这两句话。交换机的功能可以看成是小区和小区之间的路,有些小区之间只有一条路通着,有些小区之间可能有好几条路,这些路有的远有的近。而门房大爷的功能其实就是路由器(严谨的说其实不一定,因为现在具备路由功能的设备很多,不一定是路由器),也就是负责找路,只有他知道小区和小区之间的路怎么走,哪条路最近。所以说广域网(附近多个小区)有交换机(路)连接,并且广域网(附近多个小区)需要路由(门房大爷)选择(走哪条路)和分组转发(把不同的信交个不同的人) 综合起来 小型家庭局域网
总结
如果局域网是小溪,很多条小溪就汇聚成大的干流,比如长江、黄河,干流就是广域网,然后再流入大海,大海就是互联网。互联网就是由无数个局域网,通过WAN线路汇聚到运营商,然后运营商之间互联起来,就形成了互联网。如果一个公司、机构的局域网没有连接到互联网,那这个局域网就不属于互联网。公司的局域网比家庭的局域网增加了一些交换机、AP(无线访问接入点)、防火墙,除此之外,和家庭局域网没有任何实质差别。 转自 局域网,广域网,因特网之间的区别和联系? - 百哥的回答 - 知乎
https://www.zhihu.com/question/51295773/answer/1315288417
局域网,广域网,因特网之间的区别和联系? - 石岩的回答 - 知乎
https://www.zhihu.com/question/51295773/answer/127644619
局域网,广域网,因特网之间的区别和联系? - 车小胖的回答 - 知乎
https://www.zhihu.com/question/51295773/answer/127512085
minio重复修改密码 # 修改密码 export MINIO_ACCESS_KEY=minioadmin export MINIO_SECRET_KEY=*** # 查看进程 netstat -nlp|grep 9000 kill -9 进程号 第一次修改密码没问题,第二次修改就会报错:
原因:
minio的配置文件保存在隐藏文件夹。minio.sys下
删除**.minio.sys**,然后重启就可以了~
Stack Overflow也写得很清楚:
页面在加载未完成前会出现瞬间错乱的现象,虽然时间不算长,但是肉眼可见,必须解决
我们知道页面加载顺序通常是”从上往下”加载的,所以在内容区域,也就是body以及body包含的DOM还未被浏览器遍历之前,我们就应该将html的font-size计算好。
所以我们应当把计算字体的js放在body之前
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>web_app</title> </head> <body> <div id="app"> <router-view/> </div> </body> </html> <script> (function(win) { var tid; function refreshRem() { let designSize = 750; // 设计图尺寸 let html = document.documentElement; let wW = html.clientWidth;// 窗口宽度 let rem = wW * 100 / designSize; document.documentElement.style.fontSize = rem + 'px'; } win.addEventListener('resize', function() { clearTimeout(tid); tid = setTimeout(refreshRem); }, false); win.addEventListener('pageshow', function(e) { if (e.
文章目录 JS动画实现概述匀速动画缓速动画无缝连续滚动特效轮播图轮播图淡入淡出效果 JS动画实现 概述 在CSS3中可以通过transition过渡属性可以实现动画JS可以利用CSS3中的transition属性实现元素动画 匀速动画 JS封装匀速动画
<button id="btn">开始动画</button> <div id="box"></div> var btn = document.querySelector("#btn"); var box = document.querySelector("#box"); var timer = null; var left = 0; function animation(target, distance, time) { var each = parseInt(distance / time * 30); clearInterval(timer); timer = setInterval(function() { if (left >= distance) { clearInterval(timer); } else { left += each; target.style.left = left + "px"; } }, 30); }; btn.onclick = function() { animation(box, 800, 2000); }; 利用CSS transition属性实现平滑动画效果
01
先选择要合并的单元格,按CTRL+1键,再用“←”及“→”方向键移动到第二个选项卡,再按ALT+M键,再按确定,完成。Excel是Microsoft为使用Windows和AppleMacintosh操作系统的电脑编写的一款电子表格软件。
Word文档中合并单元格的快捷键是鼠标右击+M,鼠标左键选中单元格,然后按下鼠标右键加M键就可以快速合并单元格了。合并的按钮变成“合并及居中(M)”,这个(M)就是你想要的快捷方式了,现在点关闭,然后选几个单元格,再按组合键:ALT+M,就可以合并居中了。现在就已设置完成了。excel合并单元格的快捷键是alt+M。
选中需要合并的所有单元格,点击上方“合并居中”或者点击“合并单元格”下方的倒三角,就可以根据需要合并单元格了。在合并单元格上面右键,选择添加到快速访问工具栏;选择合并居中的按钮;然后按alt+2键,即可合并单元格。也可按CTRL+1键,再用“←”及“→”方向键移动到第二个选项卡,再按ALT+M键,再按确定,完成。
Excel直观的界面,出色的计算功能和图表工具,再加上成功的市场营销,使Excel成为最流行的个人计算机数据处理软件。在1993年,作为MicrosoftOffice的组件发布了5.0版之后,Excel就开始成为所适用操作平台上的电子制表软件的霸主。
本文章主要内容为C++对于C语言基础语法方面,有哪些改进与提升。
目录 1. 命名空间 namespace1.1 概念1.2 命名空间的定义1.3 命名空间的使用 2. C++中强大的输入与输出2.1 标准输入输出的使用 3. 方便的缺省参数3.1 概念3.2 分类 4. 函数重载4.1 概念4.2 举例4.3 函数重载的调用原理4.4 缺省函数有函数重载吗? 5. 引用(重点)5.1 概念5.2 如何使用5.3 特性5.4 常引用5.5 使用场景5.5.1 变量别名5.5.2 做函数参数5.5.3 做函数的返回值使用5.5.4 C/C++几种传值的效率对比5.5.5 指针和引用的区别 6. 内联函数6.1 概念6.2 特性6.3 宏函数和内联函数的区别 7. auto关键字7.1 概念7.2 使用方法7.2.1 auto和指针/引用 联合使用7.2.2 在同一行声明多个变量 7.3 auto关键字不能使用的场景 8. 范围for循环8.1 概念8.2 使用 总结 1. 命名空间 namespace 1.1 概念 在程序编写时存在着大量的变量、函数、类等等,如果将这些内容放在全局作用域,难免会出现很多冲突。所以在C++中引入了命名空间这个概念。
在命名空间中对标识符进行名称本地化,避免标识符名称冲突。
1.2 命名空间的定义 在命名空间中,可以定义函数,变量等等。
1.定义普通的命名空间
namespace A { int a = 10; int b = 20; int sum(int a, int b) { return a + b; } } 2.
1 .用户第一次访问网址,浏览器向服务器发出请求,服务器返回html文件
2 .浏览器开始载入html代码,发现head标签内有一个link标签引用外部css或者js文件。注意这里的icon,地址是一张图片,以及main.json是没有发现在请求列表的,可能之前就有了缓存
3 .浏览器又发出css以及js文件请求,服务器返回这个css,js文件
4 .浏览器继续载入html中body部分的代码,并且css,js文件已经拿到手了,可以开始渲染页面了
5 .浏览器在代码中发现一个img标签引用了一张图片,向服务器发出请求,此时浏览器不会等图片下载完,而是继续渲染后面的代码
6 .服务器返回图片文件,由于图片占用了一定面积,影响了页面布局,因此浏览器需要回过头来重新渲染这部分代码。
7 .浏览器发现了一个包含一行js代码的script标签,赶快执行他。
8 .js脚本执行了这条语句,他命令浏览器影藏掉代码中的某个div,此时浏览器不得不重新渲染这部分代码
9 .直到发现闭合的html标签
浏览器加载和渲染html的顺序
1 .ie浏览器下载的顺序是从上到下的,渲染的顺序也是从上到下,下载和渲染是同时进行的
2 .在渲染到页面的某一部分的时候,其上面所有部分都已经下载完成,但并不是说相关联的元素都以下载完毕
3 .如果遇到语义解释性的标签嵌入文件,那么此时ie的下载过程会启动单独连接进行下载
4 .并且在下载后进行解析,解析过程中,停止页面所有往下元素的下载,阻塞加载
5 .后面的样式表下载之后,将和之前的下载过的所有样式表一起进行解析,解析完成之后,将对此前所有元素(包括已经渲染)的元素重新渲染
6 .js,css中如果有重定义,那么后定义的函数将覆盖前定义的函数。
js的加载
1 .不能并行下载和解析
2 .当应用js之后,浏览器会发送一个js request就会一直等待该request的返回,因为浏览器需要一个稳定的dom树结构,而js中很有可能有代码会修改到dom树结构,甚至直接跳转,浏览器为了防止出现js修改dom树,需要重新构建dom树,所以就会阻塞其他的下载和呈现
3 .行间js将阻塞所有html代码的下载。
指定时区指令示例(指定的时区是上海):useUnicode = true & serverTimezone = Asia/Shanghai
如果是定义的是前世界标准时区GMT或现世界标准时区UTC,而身处中国的我们输入2010-01-01,会变成2009-12-31,时区有八小时的误差。
定义时区示例:
private static final String URL = "jdbc:mysql://localhost:3306/airmessage?" + "useUnicode = true & serverTimezone = Asia/Shanghai" //若指定GMT时区: "useUnicode = true & serverTimezone = GMT" + "& characterEncoding = utf8 & useSSL = false"; private static final String NAME = "root"; private static final String PASSWORD = "201704060320"; private static Connection conn = null; ...
data(){ return { timeout: 28*1000,//30秒一次心跳 timeoutObj: null,//心跳心跳倒计时 serverTimeoutObj: null,//心跳倒计时 timeoutnum: null,//断开 重连倒计时 surpriseNums: null, surpriseReconnect: false,//是否真正建立连接 } }, mounted(){ this.surpriseNum(); }, methods: { surpriseNum() { var _this = this; if (!window.location.origin) { window.location.host = window.location.hostname + (window.location.port ? ":" + window.location.port : ""); } var protocol = "ws"; if (location.protocol === "https:") { protocol = "wss"; } _this.surpriseNums = new WebSocket( `${protocol}://${window.location.host}/api/chatroom/room/` + _this.chatRoomId + "/type/image" + "/member_id/" + _this.
数据库和数据表操作 1.采用可视化软件建立数据库UNIVERSITY,其中包括六个数据表 2.采用SQL语言删除1中建立的数据库和数据表 drop database university; 3.采用SQL语言建立数据库UNIVERSITY CREATE DATABASE UNIVERSITY; 4.采用SQL语言创建UNIVERSITY数据库中的六个数据表 CREATE TABLE Department ( Dno INT, Dname VARCHAR ( 50 ), Daddress VARCHAR ( 50 ), PRIMARY KEY ( Dno ) ); CREATE TABLE Student (Sno CHAR ( 11 ),Sname CHAR ( 8 ),Ssex CHAR ( 2 ),Sage INT,Dno INT,PRIMARY KEY ( Sno ),FOREIGN KEY ( Dno ) REFERENCES department ( Dno ) ); CREATE TABLE Teacher (Tno INT PRIMARY KEY,Tname CHAR ( 8 ),Ttitle CHAR ( 8 ),Dno INT,FOREIGN KEY ( Dno ) REFERENCES department ( Dno ) ); CREATE TABLE course ( Cno INT PRIMARY KEY, Cname CHAR ( 50 ), Cpno INT, CCredit INT, FOREIGN KEY ( Cpno ) REFERENCES Course ( Cno ) ); CREATE TABLE SC (Sno CHAR ( 11 ),Cno INT,Grade INT,PRIMARY KEY ( Sno, Cno ),FOREIGN KEY ( Sno ) REFERENCES Student ( Sno ),FOREIGN KEY ( Cno )REFERENCES Course ( Cno ) ); CREATE TABLE TC (Tno INT,Cno INT,Site CHAR ( 50 ),PRIMARY KEY ( Tno, Cno ),FOREIGN KEY ( Tno ) REFERENCES Teacher ( Tno ),FOREIGN KEY ( Cno ) REFERENCES Course ( Cno ) ); 5.
项目上明明有dev分支,但是切换分支时提示错误 使用git切换分支时报错error: pathspec ‘dev’ did not match any file(s) known to git.使用git branch -a查看有没有你需要切换的分支(git branch加上-a可以查看本地和远程所有分支) 解决方法: git fetch(取回所有更新分支信息)git branch -a(此时可以查看到dev分支)git checkout dev
苹果召开WWDC21大会,发布iOS15,当我们进入手机软件更新界面时,提示已经是最新系统。那么该如何更新至iOS15呢?
首先,由于iOS15目前是测试版系统,暂未对所有的用户开放,所以我们只能用描述文件的方法来安装。我们需要在 九到五科技 获取描述文件的安装地址。
然后,在浏览器中打开,会提示我们,这里点击 允许 按钮。
然后,进入手机的 设置->通用->描述文件与设备管理 这个页面。点击刚刚下载的描述文件,根据提示进行安装。
安装成功之后,我们即可进入系统软件更新页面,更新至iOS15。
摘要:
下文讲述html代码中input type=’password’时的相关属性简介说明,如下所示:
input type=’password’ 简介
当 input标签中 type=’password’时,代表此标签是一个单行文本密码输入框,
单行文本密码框有一个显著的特点:就是输入的字符串都是一个“密文”的形式显示,
单行文本密码框所包含的其它属性同password一样,如下所示:
1.name:此属性必须设置,否则后台无法获取表单数据
2.id:此属性用于在DOM标识文本域的id编号,在DOM中,可使用document.getElementById获取DOM对象
3.value:设置value属性值,通常指我们看见的文本信息
4.size: 可视化宽度信息
5.maxlength:文本域中最大输入字符数量
6.placeholder(HTML5):属性值为提示信息,当未输入value值和未获取焦点时,我们所看见的文本域中的信息
7.required(HTML5):设置文本域内容是必填的
8.pattern(HTML5):设置验证文本域内容格式的正则表达式
9.list(HTML5):设置输入域的datalist
10.form(HTML5):设置输入域所属的一个或多个表单
11.autofocus(HTML5):设置在页面加载时,域自动地获得焦点
12.autocomplete(HTML5):设置文本域是否具有自动完成功能
13.readonly:设置文本域为只读
例:
设置一个只能输入6位数字的密码信息录入框
猫猫教程(www.maomao365.com) ----input type=password密码信息框示例说明
密码 required
pattern="\d{6}$" name="pwd">
html_表单元素input_type_password密码输入框
下载网页 TS视频并自动合成视频 1. 首先使用Chrome打开网页,单击F12打开开发者工具 开始视频播放,在F12出来的界面中单击Network在Network中有文件列表,检查当中是否存在m3u8结尾的文件 2. 如果有m3u8结尾的文件,把它的源地址复制下来 文件链接示例https://xxxxxx/d70556509660c1a29b5b0.m3u8 3. 安装 ffmpeg 进入下载页面 https://ffmpeg.org/download.html选择window 然后选择第二个
4.进入下载界面 https://github.com/BtbN/FFmpeg-Builds/releases选择对应的文件 下载
下载好后,解压到自定义的文件夹 5. 设置环境变量 进入bin 并复制bin文件夹的位置
选中“此电脑”右击,然后点击“属性”
进入高级系统设置
进入环境变量
找到 path 进入
新建环境变量 把bin的路径写入
点击 确定
检验ffmpeg是否安装成功?
win+R 运行 cmd
看出现的信息是否为安装的文件和版本信息 6. 下载视频 拿到第二步获取的 https://xxxxxx/d70556509660c1a29b5b0.m3u8 链接
进入需要存放视频的目录
在地址栏 敲入 cmd 再敲回车键
运行命令
ffmpeg -i https://xxxxxx/d70556509660c1a29b5b0.m3u8 -c copy 自定义视频名.mp4 然后开始下载视频等待视频下载结束 感谢
https://zhuanlan.zhihu.com/p/141765024
https://blog.csdn.net/realDonaldTrump/article/details/82697757
hash 扩容的过程就是针对每一个哈希值重新对第一维数组容量取余。
假设容量从8增加到16,那么原来3号槽位(011)保存的哈希值3(0x0011)和11(0x1011)被各自分配到3号和11号槽位。
特性: 如果采用高位进位的顺序遍历槽位,假设当前遍历到 110 这个槽位,这时从容量8扩容到容量16后,110槽位上所有的元素对应的新槽位是 0110 或1110,是相邻的,并且0110前的所有槽位在容量8时已经遍历完了
取余也可以理解为对二进制哈希值进行截取,比如截取i位作为槽位,导致多个哈希值对应一个槽位。另外可以让多个槽位对应一个桶,做法是继续对槽位进行截取,假设截取位数为 i j i_j ij,那么最多有 2 ( i − i j ) 2^(i-i_j) 2(i−ij)个槽位对应一个桶j。
插入导致桶j超过容量后,如果i= i j i_j ij, 说明一个槽位对应一个桶,这时必须把第一位数组的容量翻倍,并且使i=i+1;
当 i> i j i_j ij 说明此时桶j对应多个槽位,此时不需要更新整个一位数组,只需要把桶j分成两个桶j和z, 且新 i j i_j ij和 i z i_z iz等于旧 i j i_j ij+1。
判断元素是否存在与hash表中,一个思路是使用bloom 过滤器,但是其不支持删除操作,因为(位图中一个bit位被多个元素公用,且不能确定被删除的元素是否在位图中)
C++实现
void ExtendibleHash<K, V>::Insert(const K &key, const V &value) { _mtx.try_lock(); Node<K,V>* newNode=new Node<K,V>(key,value); size_t h=HashKey(key); // std::cout<<"insert"<<h<<" "
经过前面的学习,我们知道如何从一个文件中读取数据。那么,下面,我们学习怎么样往一个文件中写入数据。C语言提供了fwrite()函数,用于往一个打开的文件指针中写入数据。函数的定义如下:
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
函数说明:函数往stream文件指针指向的文件写入数据,要写入的数据存放在ptr缓存中。写入size个数据块,每个数据块的容量是count个字节。所以,总共写入的字节数是size*count个字节。
返回值:返回成功写入的数据块个数。注意:不是实际写入的字节数,是参数size表示的数据块个数。
程序测试例子如下:
程序运行结果如下:
运行程序完成之后,程序创建test.txt文件,并把 "www.mylinux.vip\n" 字符串写入test.txt文件中。所以,可以查看test.txt文件的内容如下:
可以看到,最终,调用fwrite()可以往文件中写入数据。打开文件的时候,想对文件进行写入数据的操作,所以,fopen()函数的第二个参数用"w+"模式,表示对文件进行写入操作。
韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发,微信:13926572996,QQ:1523520001,博客:www.mylinux.vip
解决方法:
在phpcms网站中使用验证码我们要考虑前端模板页面中如何调用验证码和后台程序中如何验证两个方面:
一、在模板中,调用验证码的代码如下:验证码
{form::checkcode('code_img', '4', '14', 100, 30)}
注意,从标签中可知是使用了form类中的checkcode方法,那么就要确保此模板所在的控制器文件中已经调用了该类,调用方法如下:pc_base::load_sys_class('form', '', 0);
此类文件位置/phpcms/libs/classes/form.class.php,你可以通过查看此文件中的checkcode方法参数注释来了解各参数所代表的意义。
二、在后端控制器文件php程序中,演示代码如下:defined('IN_PHPCMS') or exit('No permission resources.');
pc_base::load_sys_class('form','', 0);
class index {
public function init(){
if(isset($_POST['dosubmit'])){ //提交数据
//启动session
$session_storage = 'session_'.pc_base::load_config('system','session_storage');
pc_base::load_sys_class($session_storage);
//验证码
if (($_SESSION['code'] != strtolower($_POST['code'])) || empty($_SESSION['code'])) {
showmessage("验证码错误");
} else {
$_SESSION['code'] = '';
}
这里我们注意三点:第二行,不要忘记引入form类;
第7、8、9行,在读取session数据前先引入session存储配置与启动对应类(一般是mysql);
判断session的if条件即将表单填入的code值与session中的code值进行对比;
PS:大家还可以参考phpcms系统中原有的调用表单的地方进行研究学习或参照,例如会员注册模板页(/phpcms/templates/default/member/register.html)以及对应的后台php文件(phpcms/modules/member/index.php中的register方法).
前言 有时候我们在用requests抓取页面的时候,得到的结果可能和在浏览器中看到的不一样,在浏览器中可以看到正常显示的页面数据,但使用requests得到的结果并没有。这是因为在requests获得的都是原始的HTML文档,而浏览器中的页面则是经过JavaScript处理数据后生成的结果,这些数据的来源有很多种,可能是通过Ajax加载的,可能是包含在HTML文档中的,也可能是经过JavaScript和特定的算法计算后生成的。
本文将讲解什么是Ajax以及如何分析和抓取Ajax请求。
Ajax Ajax即异步的JavaScript和XML,它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。
对于前言的第一种情况,数据加载是一种异步加载方式,原始的页面最初不会包含某些数据,原始页面加载完后,会再向服务器请求某个接口获得数据,然后数据才被处理从而呈现到网页上,这其实就是发送了一个Ajax请求。
对于传统的网页,如果想更新其内容,那么必须要刷新整个页面,但有了Ajax,便可在页面不被全部刷新的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器进行了数据交换,获取到数据之后,再利用JavaScript改变网页,这样网页内容就会更新了。
Ajax应用场景 浏览网页的时候,我们会发现很多网页都有下滑查看更多的选项。
例如进入微博(https://weibo.com/),下滑几个微博之后,再向下就没有了,转而会出现一个加载动画的,不一会就会刷线新的微博内容,整个过程其实就是Ajax加载的过程。
我们注意到页面其实并没有整个刷新,也就意味着页面的链接没有变化,但是网页中却多了新内容,也就是后面刷出来的新微博。这就是通过Ajax获取新数据并呈现出来的过程。
Ajax分析方法 我们知道真实的数据其实都是一次次Ajax请求得到的,如果想要抓取这些数据,需要知道这些请求到底是怎么发送的,发往哪里,发了哪些参数,如果我们知道了这些,不就可以用python模拟这个发送操作,获取到其中的结果了吗?
查看请求 我们知道拖动刷新的内容由Ajax加载,而且页面的URL没有变化,那么应该到哪里去查看这些Ajax请求呢?这里以知乎-发现(https://www.zhihu.com/special/all)为例,借助Chrome浏览器的开发者工具来介绍。
首先,用Chrome浏览器打开知乎-发现(https://www.zhihu.com/special/all),随后在页面中右击鼠标,从弹出的快捷菜单中选择“检测”选择,此时便会弹出开发者工具。如下图:
此时在Elements选项卡中便会观察到网页的源代码,但这不是我们想要寻找的内容。切换到Network选项卡,随后重新刷新页面,可以发现这里出现了非常多的条目,如下图:
Ajax其实有其特殊的请求类型,它叫作xhr。我们发现有个名称list?limit=10&offset=20的请求,这就是一个Ajax请求,用鼠标点击这个请求,可以查看到这个请求的详细信息。
右侧可以观察到其Request Headers、URL和Respouse Headers等信息。其中Request Headers中有一个信息为X-Requested-with:fetch,这个就是标记了此请求是Ajax请求。
随后点击一下Preview,即可看到响应的内容,它是JSON格式的。观察可以发现,这里返回结果是专题的信息,如:标题、点击量和介绍等,这也是用来渲染个人主页所使用的数据。JavaScript接收到这些数据之后,再执行相应的渲染方法,整个页面就渲染出来了。如下图:
另外,也可以切换到Respouse选项卡,从中观察到真实的返回数据,如下图:
接下来,切回到第一个请求,观察一下它的Respouse是什么,如下图:
这是最原始的链接(https://www.zhihu.com/special/all)返回的结果,其代码只有不到20行,结构也非常简单,只是执行了一些JavaScript。
所以我们看到的知乎-发现的真实数据并不是最原始的页面返回的,而是后来执行JavaScript后再次向后台发送了Ajax请求,浏览器拿到数据后再进一步渲染出来的。
过滤请求 使用Chrome开发者工具筛选功能筛选出所有的Ajax请求。如下图:
不断滑动页面,可以看到页面底部有一条条新的专题被刷新出,而开发者工具下方也一个个地出现Ajax请求,这样我们就可以捕获到所有的Ajax请求了。
随意点开一条目,都可以清楚地看到其Request URL、Request Headers、Respouse Headers、Respouse Body等内容,此时想要模拟请求和提取就非常简单了。如下图:
Ajax结果提取 接下来用Python来模拟这些Ajax请求,把知乎-发现-全部专题的部分内容爬取下来。
分析请求 打开Ajax的XHR过滤器,然后一直滑动页面以加载新的专题内容,可以看到,会不断有Ajax请求发出。
选定其中一个请求,分析它的参数信息。点击该请求,进入详情页面,如下图:
可以发现,这是一个GET类型的请求,请求链接为:https://www.zhihu.com/api/v4/news_specials/list?limit=10&offset=10,请求的参数有2个:limit和offset。看看其他请求,可以发现,它们的limit没有改变,改变的值就是offset,很明显这个参数就是用来控制分页的,offset=1代表第一页,offset=2代表第二页,以此类推。
分析响应 观察这个请求的响应内容,如下图:
这个内容是JSON格式的,浏览器开发者工具自动做了解析以方便我们查看,最关键的两部分信息就是data和paging:前者是一个列表,包含10个元素,展开其中一个看一下。后者包含一个比较重要的信息total,它是专题的总个数,我们可以根据这个数字来估算分页数。如下图:
可以发现,它包含了知乎-发现-全部专题的一些信息,例如:banner(图片链接),id(发帖者id)、introdunction(简介)、title(标题)、updated(更新时间)、view_count(点击量)等,而且它们都是一些格式化的内容。
这样我们请求一个接口,这样就可以得到10个专题,而且请求时只需要改变offset参数即可。
这样的话,我们只需要简单一个循环,就可以获得所有专题了。
实战演练 这里我们用程序模拟这些Ajax请求,将全部专题爬取下来。
爬取首页信息数据
首先,定义一个方法来获取每次请求的结果,在请求时,offset是一个可变参数,所以我们将它作为方法的参数传递进来,相关代码如下:
from urllib.parse import urlencode import requests base_url='https://www.zhihu.com/api/v4/news_specials/list?' headers={ 'Host':'www.zhihu.com', 'Referer':'https://www.zhihu.com/special/all', 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.
RPC和HTTP的关系 RPC是一种概念,代表远程过程调用,HTTP是一种协议,RPC可以基于HTTP实现,也可以基于其它协议如TCP实现,而TCP是比HTTP快的,一般说的RPC比HTTP快说的是基于TCP实现的RPCRPC和HTTP算了一种包含关系,RPC包含http,因为RPC可以基于HTTP协议或者其它协议实现,HTTP只能基于Http协议实现,下面讲的RPC是指非HTTP协议的RPC下面讲一下基于TCP的RPC和HTTP的对比 基于TCP的RPC和HTTP的对比: RPC:Remote Produce Call远程过程调用,类似的还有RMI(Remote Methods Invoke 远程方法调用,是JAVA中的概念,是JAVA十三大技术之一)。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型
RPC的框架:webservie(cxf)、dubbo(阿里巴巴开源的基于 Java 的高性能 RPC)
RMI的框架:hessian
HTTP:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议。也可以用来进行远程服务调用。缺点是消息封装臃肿。
现在热门的Rest风格,就可以通过http协议来实现。
http的实现技术:HttpClient
相同点:底层通讯都是基于socket,都可以实现远程调用,都可以实现服务调用服务
不同点:
RPC:框架有:dubbo、cxf、(RMI远程方法调用)Hessian
当使用RPC框架实现服务间调用的时候,要求服务提供方和服务消费方 都必须使用统一的RPC框架,要么都dubbo,要么都cxf
跨操作系统在同一编程语言内使用
优势:调用快、处理快
http:框架有:httpClient
当使用http进行服务间调用的时候,无需关注服务提供方使用的编程语言,也无需关注服务消费方使用的编程语言,服务提供方只需要提供restful风格的接口,服务消费方,按照restful的原则,请求服务,即可
跨系统跨编程语言的远程调用框架
优势:通用性强
总结:对比RPC和http的区别
1 RPC要求服务提供方和服务调用方都需要使用相同的技术,要么都hessian,要么都dubbo
而http无需关注语言的实现,只需要遵循rest规范
2 RPC的开发要求较多,像Hessian框架还需要服务器提供完整的接口代码(包名.类名.方法名必须完全一致),否则客户端无法运行
3 Hessian只支持POST请求
4 Hessian只支持JAVA语言
如何选择? 既然两种方式都可以实现远程调用,我们该如何选择呢?
速度来看,RPC要比http更快,虽然底层都是TCP,但是http协议的信息往往比较臃肿
难度来看,RPC实现较为复杂,http相对比较简单
灵活性来看,http更胜一筹,因为它不关心实现细节,跨平台、跨语言。
因此,两者都有不同的使用场景:
如果对效率要求更高,并且开发过程使用统一的技术栈,那么用RPC还是不错的。
如果需要更加灵活,跨语言、跨平台,显然http更合适
那么我们该怎么选择呢?
微服务,更加强调的是独立、自治、灵活。而RPC方式的限制较多,因此微服务框架中,一般都会采用基于Http的Rest风格服务。
总结
RPC服务和HTTP服务还是存在很多的不同点的,一般来说,RPC服务主要是针对大型企业的,而HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。
前后端交接、调用后端接口时遇到很多报错!把孩子心态搞掉(狗头)
记录下来让大家解决报错,不用像我一样苦苦搜寻了(泪目)
更多 请见文章:前端vue 前后端交接错误汇总 跨域问题/报错404/405/415/带请求token
问题 报错例如
Access to XMLHttpRequest at 'http://47.110....' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
是跨域问题
解决方法: 在根目录下新建一个名为vue.config.js的文件(不需要手动引入)
内容为:
module.exports = { assetsDir: 'static', devServer: { proxy: { '/api': { //之后就使用/api代指根路径 target: 'http://.....', // 这是根路径 changeOrigin: true, pathRewrite: { '^/api': '' } } } } } 如
ZFNet出自论文《 Visualizing and Understanding Convolutional Networks》,作者Matthew D. Zeiler和Rob Fergus——显然ZFNet是以两位作者名字的首字母命名的。ZFNet通常被认为是ILSVRC 2013的冠军方法,但实际上ZFNet排在第3名,前两名分别是Clarifai和NUS,不过Clarifai和ZFNet都出自Matthew D. Zeiler之手,见ILSVRC2013 results。
ZFNet的网络架构是在AlexNet基础上修改而来,与AlexNet相比,差异不大:
第1个卷积层,kernel size从11减小为7,将stride从4减小为2(这将导致feature map增大1倍)为了让后续feature map的尺寸保持一致,第2个卷积层的stride从1变为2 仅这2项修改,就获得了几个点的性能提升。所以,重要的是为什么这样修改?这样修改的动机是什么?文中这样叙述:
通过对AlexNet的特征进行可视化,文章作者发现第2层出现了aliasing。在数字信号处理中,aliasing是指在采样频率过低时出现的不同信号混淆的现象,作者认为这是第1个卷积层stride过大引起的,为了解决这个问题,可以提高采样频率,所以将stride从4调整为2,与之相应的将kernel size也缩小(可以认为stride变小了,kernel没有必要看那么大范围了),这样修改前后,特征的变化情况如下图所示,第1层呈现了更多更具区分力的特征,第二2层的特征也更加清晰,没有aliasing现象。
这就引出了另外一个问题,如何将特征可视化?正如论文标题Visualizing and Understanding Convolutional Networks所显示的那样,与提出一个性能更好的网络结构相比,这篇论文更大的贡献在于提出一种将卷积神经网络深层特征可视化的方法。
可视化操作,针对的是已经训练好的网络,或者训练过程中的网络快照,可视化操作不会改变网络的权重,只是用于分析和理解在给定输入图像时网络观察到了什么样的特征,以及训练过程中特征发生了什么变化。
给定1张输入图像,先前向传播,得到每一层的feature map,如果想可视化第i层学到的特征,保留该层feature map的最大值,将其他位置和其他feature map置0,将其反向映射回原始输入所在的像素空间。对于一般的卷积神经网络,前向传播时不断经历 input image→conv → rectification → pooling →……,可视化时,则从某一层的feature map开始,依次反向经历 unpooling → rectification → deconv → …… → input space,如下图所示,上方对应更深层,下方对应更浅层,前向传播过程在右半侧从下至上,特征可视化过程在左半侧从上至下:
可视化时每一层的操作如下:
Unpooling:在前向传播时,记录相应max pooling层每个最大值来自的位置,在unpooling时,根据来自上层的map直接填在相应位置上,如上图所示,Max Locations “Switches”是一个与pooling层输入等大小的二值map,标记了每个局部极值的位置。Rectification:因为使用的ReLU激活函数,前向传播时只将正值原封不动输出,负值置0,“反激活”过程与激活过程没什么分别,直接将来自上层的map通过ReLU。Deconvolution:可能称为transposed convolution更合适,卷积操作output map的尺寸一般小于等于input map的尺寸,transposed convolution可以将尺寸恢复到与输入相同,相当于上采样过程,该操作的做法是,与convolution共享同样的卷积核,但需要将其左右上下翻转(即中心对称),然后作用在来自上层的feature map进行卷积,结果继续向下传递。 不断经历上述过程,将特征映射回输入所在的像素空间,就可以呈现出人眼可以理解的特征。给定不同的输入图像,看看每一层关注到最显著的特征是什么,如下图所示:
步骤1:点击Eclipse的“Help”菜单的“Eclipse Marketplace”选项 点击“Eclipse Marketplace”选项表示打开Eclipse的应用市场,如果后续需要安装其它插件,也是打开此选项后操作。
步骤2:在弹出的“Eclipse Marketplace”对话框中,先在“Search”的输入框中输入“SpringTools”并点击搜索按钮,然后,在搜索结果的“Spring Tools 4”一栏点击“Install”按钮 第一次打开“Eclipse Marketplace”对话框时可能需要加载一些文件,等加载完毕后再输入搜索关键字,搜索过程也可能需要等待一定时间,在此过程中,需要保证网络畅通。
在搜索结果中可能会显示多个Spring Tools的版本,推荐选择最新的版本,并且,新版本的SpringBoot等框架对Eclipse的版本有一定要求,推荐使用较新的Eclipse软件,一般,不推荐使用低于4.11版本的Eclipse。
步骤3:点击下方的“comfirm”按钮表示确认,继续下一步操作 当前界面显示的是Spring Tools插件的软件列表,默认是全部勾选的,推荐全部勾选,直接进入下一步操作。
步骤4:选中“I accept the terms of the license agreements”后点击“Finish”按钮以完成安装向导 当前界面显示的使用许可协议,默认选中的是不同意,需要先选中“I accept the terms of the license agreements”表示同意许可协议的条款,左侧有3个选项,在右侧只需要选中1次即可。
步骤5:等待Eclipse下载并安装插件 此时Eclipse会自动开始下载并安装插件,因为需要下载一系列的文件,所以,整个过程可能耗时几分钟,请耐心等待。
步骤6:安装完成后,Eclipse会提示重新启动,点击“Restart Now”按钮后,Eclipse将重新启动 步骤7:重新启动后,Spring Tools插件已经安装完成 在Eclipse顶部的按钮栏中,会显示“Boot Dashboard”按钮。
如果重新打开“Eclipse Marketplace”对话框,在“Installed”选项卡中可以看到已安装的插件,其中就有刚才安装的Spring Tools插件。
如检查无误,至此,整个安装过程全部完成!
有不少小伙伴在使用win10系统的时候,因为设置win10开机密码太过复杂,导致自己忘记了win10开机密码怎么办?我们可以借助工具进pe系统内重置win10开机密码,下面小编就教下大家win10忘记密码强制重置密码的方法。
具体的步骤如下:
1、首先在一台可用的电脑上制作好一个u盘启动盘,制作完成之后重启电脑进入PE系统桌面。具体的u盘启动盘制作教程参照:小白u盘启动盘制作方法。
2、插入启动盘重启电脑,不断按f12,f2或者del等启动热键进快速启动项选择u盘启动进入,选择01项pe系统进入。
3、进入pe系统界面后,点击打开桌面上的“清除系统密码”图标。
4、文件路径一般使用默认,双系统的朋友需要自己手动找到,点击打开。
5、选择想要清楚密码的用户名,点击【修改密码】。接着弹出一个框,输入两遍相同的新密码点击【OK】。
6、最后点击【保存更改】。
7、以上步骤完成后,拔掉u盘进行重启电脑,此时你就可以输入刚刚录入的密码进入电脑系统了。
以上便是win10忘记密码强制重置密码的方法,有遇到这个问题的小伙伴可以参照教程进行解决哦。
相关资源:小白一键重装系统.exe
反射的思想及作用 在学习反射之前,先来了解正射是什么。我们平常用的最多的 new 方式实例化对象的方式就是一种正射的体现。假如我需要实例化一个HashMap,代码就会是这样子。
Map<Integer, Integer> map = new HashMap<>(); map.put(1, 1); 某一天发现,该段程序不适合用 HashMap 存储键值对,更倾向于用LinkedHashMap存储。重新编写代码后变成下面这个样子。
Map<Integer, Integer> map = new LinkedHashMap<>(); map.put(1, 1); 假如又有一天,发现数据还是适合用 HashMap来存储,难道又要重新修改源码吗?
发现问题了吗?我们每次改变一种需求,都要去重新修改源码,然后对代码进行编译,打包,再到 JVM 上重启项目。这么些步骤下来,效率非常低。
对于这种需求频繁变更但变更不大的场景,频繁地更改源码肯定是一种不允许的操作,我们可以使用一个开关,判断什么时候使用哪一种数据结构。
public Map<Integer, Integer> getMap(String param) { Map<Integer, Integer> map = null; if (param.equals("HashMap")) { map = new HashMap<>(); } else if (param.equals("LinkedHashMap")) { map = new LinkedHashMap<>(); } else if (param.equals("WeakHashMap")) { map = new WeakHashMap<>(); } return map; } 通过传入参数param决定使用哪一种数据结构,可以在项目运行时,通过动态传入参数决定使用哪一个数据结构。
记得给博主点点赞加加油噢!
public class PrintTable { //使用循环嵌套输出10*10的表格,每个表格内显示表格当前行列值 public static void main(String[] args) { // TODO 自动生成的方法存根 int row=0; while(row<10) { int column=0; while(column<10) { System.out.print("("+row+","+column+")"); column++; } row++; System.out.println(" "); } } }
记得给博主点点赞加加油噢!
public class CLSS_ch2 { //在1-100的累加过程当中,跳过个位是3的数字,输出选择性累加之和 public static void main(String[] args) { // TODO 自动生成的方法存根 int sum=0,i=0; while(i<100) { i++; if(i%10==3) { continue; } else { sum+=i; } } System.out.println("1~100,跳过个位数字是3的数字之和:"+sum); } }
补充说明:
通过此方法集成后,用户、组以及用户和组的关系都在Crowd系统中存储,但各个系统的权限仍由各系统控制,也可在JIRA和Confluence中添加和删除用户。在做步骤4和步骤5的时候,要特别小心,确保当前系统的超级权限用户(一般为admin,具体看当前系统的全局权限配置)和组以及它们的关系已经在Crowd中同样存在了,才可切换并禁用当前系统的内部用户目录,否则可能造成权限丢失等严重问题(因为禁用了内部用户目录,而Crowd中又不存在这个超级权限用户和组或它们的关系,所以权限就丢失了)维护示例:情景一:比如Confluence默认全局权限是属于confluence-users组中的成员才允许访问Confluence,那么在Crowd中添加用户A后,想让其能访问Confluence,则需要将其加入confluence-users组情景二:在JIRA上添加了用户A并加入confluence-users组后,JIRA和Crowd上这个用户A信息立即是最新的,但是Confluence上默认要过60分钟后自动同Crowd同步后,用户A信息才会更新,如果想Confluence也立即更新用户A信息,则需您以有管理员权限的用户登录Confluence后台->用户目录,手动点击“用户来自Crowd”用户目录的[同步]按钮进行立即同步。 1、在Crowd中,将其它系统中的用户、组以及用户和组的关系同样在Crowd中建一份 比如本例以JIRA和Confluence与Crowd集成为例,JIRA和Confluence的环境如下:
JIRA默认有4个组:jira-administrators、jira-software-users、jira-core-users、jira-servicedesk-users(是否有这绿色的3个组取决于你JIRA是否安装和授权了相应的模块),JIRA默认管理员admin都属于这4个组。
Confluence默认有2个组:confluence-administrators、confluence-users,confluence默认管理员admin都属于这2个组。
在Crowd中,添加上面的所有用户、组以及用户和组的关系,具体的添加方法如下图:
添加组
添加用户
如果您按照本系列教程安装的Crowd,在初始化配置Crowd过程中,就已经添加了名为admin 的管理员以及默认的Crowd内部用户目录Atlassian Common User Directory。则直接设置 admin和组的关系即可。
如果没有相应JIRA和Confluence的系统中的用户,你需要在Crowd上添加这些用户。
设置用户和组的关系
这样,最终在Crowd的用户目录Atlassian Common User Directory中有:
用户组6个:jira-administrators、jira-software-users、jira-core-users、jira-servicedesk-users、confluence-administrators、confluence-users用户1个:admin用户和组的关系:admin是这6个组的成员 2、在Crowd中,添加Application(供JIRA和Confluence的连接通道) 2.1. 添加JIRA连接通道 2.2、添加Confluence连接通道 类似添加JIRA连接通道。
3、在JIRA中,配置JIRA用户和组来自Crowd 3.1、在JIRA中,建一个Crowd类型的用户目录 【JIRA后台】>【用户管理】>【用户目录】里添加个Crowd类型的用户目录
3.2、在JIRA中,同步用户目录并将顺序调为第一 3.3、在JIRA中,禁用JIRA内部用户目录 最终如下:
4、配置Confluence用户和组来自Crowd 4.1、在Confluence中,建一个Crowd类型的用户目录 【Confluence后台】>【用户&安全】>【用户目录】里添加个Crowd类型的用户目录
4.2、在Confluence中,同步用户目录并将顺序调为第一 4.3、在Confluence中,禁用Confluence内部用户目录 最终如下:
5、单点登录SSO配置 以上步骤已经完成了JIRA、Confluence与Crowd的用户集成,但还没实现SSO单点登录(即登录JIRA后访问Confluence时也自动登录了,反过来也一样)。在没设置单点登录之前现在他们虽然是用一套用户,但是jira和confluence会互t。只能登录一个系统。接下来实现单点登录:
5.1、复制CROWD安装目录/client/conf/crowd.properties到下面对应程序目录: (JIRA)JIRA/atlassian-jira/WEB-INF/classes/crowd.properties
(Confluence)CONFLUENCE/confluence/WEB-INF/classes/crowd.properties
5.2、修改jira/atlassian-jira/WEB-INF/classes/crowd.properties文件 5.3、修改jira/atlassian-jira/WEB-INF/classes/seraph-config.xml文件 在文件末尾附近
5.4、修改confluence/confluence/WEB-INF/classes/crowd.properties文件 5.5、修改confluence/confluence/WEB-INF/classes/seraph-config.xml文件 在文件末尾附近
5.6、重启jira和confluence,至此完成单点登录,可以登录jira,然后打开confluence看看是否为自动登录
阿里云盘在前不久正式上线了Windows版本,但被众多用户吐槽功能和界面都有点简陋,6盘小白羊版的作者便基于阿里云盘网页版开发出了一个第三方客户端:阿里云盘小白羊版(软件下载点击这里),拥有强大的网盘存储功能,能够轻松实现高速下载,秒速上传大文件,以及分享秒传链接,满足用户的文件存储需求。而且与官方版相较而言,该版本不仅有着官方版的所有功能,还在其基础上加入了许多独有的功能,例如所增加的新建秒传链接的功能,可以选中任意一个文件轻松创建一条秒传链接,无需等待,可以设置加密及备注,但生成后的链接必须在软件内才能使用。当然,小伙伴们肯定还是关注下载限速问题,在阿里云盘第三方小白羊版中可以完全放心,完美实现阿里云盘的高速下载特性,能够榨干你的带宽,为你提供高效、便捷的网盘资源下载服务,除此之外,阿里云盘小白羊版还支持在线预览,一键即可享受原画质量的观影体验,特别的香,总的来说,略胜一筹,绝对妥妥的网盘下载神器呀,相信不少用户都会喜欢,下文奉上了详细的使用图文教程,希望对用户有所帮助。
功能特点 1、支持 扫码登录/Cookie登录
2、支持 阿里云盘基本功能(列出文件/重命名/移动/回收站/收藏夹)
3、支持 在线预览全格式原画视频(非转码),在线预览图片
4、支持 批量下载文件/文件夹,多文件同时下载+断点续传,满速下载
5、支持 批量上传文件/文件夹,多文件同时上传,支持断点续传
6、支持 创建秒传短链接,支持保存别人通过秒传链接分享的文件(支持115链)
JSON.parse(JSON.stringify ())在实现深拷贝时是有一些弊端的。
有以下几种情况时,不能正确的进行深拷贝:
1、obj里面有new Date(),深拷贝后,时间会变成字符串的形式。而不是时间对象;
var a = { name: 'a', date: [new Date(1536627600000), new Date(1540047600000)], }; let b; b = JSON.parse(JSON.stringify(a)) console.log(a,b) 2、obj里有RegExp、Error对象,则序列化的结果会变成空对象{};
const a = { name: 'a', date: new RegExp('\\w+'), }; // debugger const b = JSON.parse(JSON.stringify(a)); a.name = 'test' console.log( a, b) 3、obj里有function,undefined,则序列化的结果会把function或 undefined丢失;
const a = { name: 'a', date: function hehe() { console.log('fff') }, }; // debugger const b = JSON.parse(JSON.stringify(a)); a.name = 'test' console.
整数比较:
-eq(equal) : 测试两个整数是否相等;比如 $A -eq $B -ne(inequality) : 测试两个整数是否不等;不等,为真;相等,为假; -gt(greter than) : 测试一个数是否大于另一个数;大于,为真;否则,为假; -lt(less than) : 测试一个数是否小于另一个数;小于,为真;否则,为假; -ge(greter equal): 大于或等于 -le(less equal) :小于或等于 命令的间逻辑关系:
逻辑与: && 第一个条件为假时,第二条件不用再判断,最终结果已经有; 第一个条件为真时,第二条件必须得判断; 逻辑或: || vim pushflow.sh
#!/bin/bash # 查询push-flow的进程个数 count=`ps -ef | grep push-flow-system-5.1.2.jar | grep -v "grep" | wc -l` # echo $count sec=7 nowtime=`date +"%Y-%m-%d %H:%M:%S"` nowDate=`date +"%Y-%m-%d"` for i in 1 do if [ $count -gt 0 ];then echo sleep $sec ,the push-flow is still alive else # 若进程未关闭则,重新启动,并列出循环 cd /app/push-flow nohup java -jar push-flow-system-5.
js动态添加数组可以按下面的步骤:
1、在数组的开头添加新元素 - unshift()
源代码:
Click the button to add elements to the array.
Try it
function myFunction()
{
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon","Pineapple");
var x=document.getElementById("demo");
x.innerHTML=fruits;
}
Note: The unshift() method does not work properly in Internet Explorer 8 and earlier, the values will be inserted, but the return value will be undefined.
测试结果:
Lemon,Pineapple,Banana,Orange,Apple,Mango
2、在数组的第2位置添加一个元素 - splice()
源代码:
Click the button to add elements to the array.
文本生成技术是自然语言处理领域的另一重要技术。应用者可以利用既定信息与文本生成模型生成满足特定目标的文本序列。文本生成模型的应用场景丰富如生成式阅读理解、人机对话或者智能写作等。当前深度学习的发展也推动了该项技术的进步,越来越多高可用的文本生成模型诞生,促进行业效率,服务智能化社会。
10.1 文本生成的发展现状 文本生成的技术路线发展与其他NLP技术路线类似,均是从简单的规则逐步发展至大型深度神经网络的过程。当然,文本生成显然难于其他NLP技术,因为文本生成技术的预测目标并不在既定的文本中,其需要根据既定文本去生成符合目标的文本,而阅读理解、命名实体识别等技术则是通过抽取既定文本里的相应文本段来达成预测的目标。
10.1.1 文本生成模板 文本生成技术的发展同样离不开简单规则的约束。本文所说的规则就是预先定义好的模板,每一个模板对应一种应用场景。根据应用场景的特性,我们将需要生成的通用性语句事先规范化(模板),而后再利用NLP技术去抽取相应的非通用语句对模板进行插空,从而完成文本生成任务。如图10-1所示,图中标红的字体就是模板,黑色字体则可通过计算涨跌来填充模板中的空缺,从而完成股市新闻的签发。
图10-1文本生成模板 当然,图10-1只是一个简单的模板呈现,要生成符合复杂应用场景的文字模板,这需要考虑模板中的内容、文本结构、句子语法与阅读流畅度等,这就需要大量的专业人员去维护每一套模板的产生。
10.1.2 变分自编码器 变分自编码器(VAE)是自编码器中的一种。常见的自编码器如图10-2所示,最简单的自编码器只有三层结构,中间的隐藏层才是我们所需要关注的地方,以隐藏层为界限,左边为编码器(encoder), 右边为解码器(decoder),所以在训练过程中,输入才能在经过编码后再解码,还原成原来的模样。
对传统机器学习有所了解的读者应该都知道主成分分析(PCA),它就是用来对数据进行降维。假如我们通过一组数据训练出了我们的自编码器,然后我们拆掉自编码器的解码器(decoder),就可以用剩下的编码器(encoder)与隐藏层来表征我们的数据了。隐藏层的神经元数目远低于输入层,那么就相当于我们用更少的特征(神经元)去表征我们的输入数据,从而达到数据降维压缩的目的。
当然,自编码器学习到的特征表征不仅仅可以用来数据降维,也可以将特征表征接入一个简单的分类器,将抽象的特征用来文本分类。同样地,我们可以利用自编码器所得到的特征(这里也称隐变量)并对编码器与解码器进行改造,从而实现文本生成技术。
图10-2自编码器网络结构 10.1.3 序列到序列技术 虽然序列到序列(Seq2Seq)技术与变分自编码器在文本生成都利用了编码器与解码器,但两者仍然存在些许不同,变分自编码的文本生成技术在预测过程中会从隐变量的分布中进行采样,在这种方法下,对于同一条文本输入,模型能够得到不一样的文本输出。而Seq2Seq文本生成模型则能保证在预测过程中的文本输入与输出是确定的。因此,当前采用Seq2Seq结构的文本生成模型更为主流,Seq2Seq的优点是能够处理变长文本,常见的Seq2Seq结构首先利用编码器将输入序列映射成固定的中间序列h4,而后解码器再对中间序列h4进行解码,如图10-3所示。
图10-3 常见的Seq2Seq结构 然而,图10-3的Seq2Seq结构存在一定缺陷,因为编码器将文本统一映射成了固定的中间序列,这让文本中每一个词语在固定的中间序列的信息(贡献量)是一致的。显然,一句话的中心往往有文本中的几个词来表征,故而固定的中间序列信息对后续的解码产生了一定影响。这里就诞生了基于注意力机制的Seq2Seq模型,如图10-4所示。注意力机制下的Seq2Seq模型的输入中间序列不是固定的,而是经过编码器转换的中间语义C。
图10-4注意力模型(解码器部分) 而这些输入C也各不相同,每一个C都是由权重w和译码器的隐藏层输出h加权组成,如图10-5所示。在解码器decoder部分,中间语义C1,C2,C3之间的权值表征是不同的,这也就是我们所说的注意力机制。
图10-5中间语义转换示意图 换言之,随着训练过程的进行,重点一直在变化,而这些变化则由上图的权重w去表示,当训练停止时,权重值也就确定下来了,此时的权重值是最拟合当前训练数据的。例如C1的重点在“中”这个字,那么中间语义可以表示为C1=0.6h1 + 0.2h2 + 0.1h3 + 0.1h4 (权值可以看成概率,所有权值值加起来为1)。因此中间语义的转换公式如式(10-1)所示。其中,n为输入序列的长度。
此时,我们唯一要解决的是,如何去求中间语义C的权值w表征。这就涉及到注意力模型的编码器部分,如图10-6所示。F函数和softmax函数可以理解为我们要计算当前的hi与全部h(包括hi)之间的差别,从而计算出在i时刻下,每一个h对应的权值(即概率)。换言之,大家可以将下图看成分类问题,与hi越相近的,输出的概率也就越大。
图10-6注意力模型(编码器部分) 10.2 基于预训练模型的文本生成模型 Seq2Seq模型需要预训练模型的语义表征作为输入,而当前类BERT预训练模型发展迅猛。Li等人[1]提出的UniLM模型则是将Seq2Seq与BERT模型结合起来。UniLM能够在不改变以往BERT模型微调的方式进行文本生成任务,使得BERT模型在自然语言生成(NLG)任务与自然语言理解(NLU)任务中实现统一。
为了统一NLG与NLU两种任务,UniLM模型使用了三种目标函数进行预训练:双向语言模型,单向语言模型和序列到序列语言模型,模型框架如图10-7所示。三种不同目标函数的语言模型共享同一个Transformer网络,而这三种目标函数则通过自注意力掩盖矩阵(self-attention mask)来实现。
1. 双向语言模型:与BERT模型一致,在预测被掩蔽的字符令牌时,可以观察到所有的字符令牌。
2. 单向语言模型:从左到右掩盖策略与从右到左掩盖策略。从左到右方向的掩盖策略是通过被掩盖的字符令牌(token)的左侧文本来预测被掩盖的字符令牌。从右到左掩盖策略则与前者相反。
3. 序列到序列语言模型:如果被掩蔽字符令牌在第一个文本序列中,那么仅可以使用第一个文本序列中所有字符令牌,不能使用第二个文本序列的任何信息;如果被掩蔽字符令牌在第二个文本序列中,那么使用一个文本序列中所有字符令牌和第二个文本序列中被掩蔽字符令牌的左侧文本序列来预测被掩蔽字符令牌。
在模型预训练过程中,三分之一的数据用于双向语言模型,三分之一的数据用于序列到序列语言模型优化,三分之一的数据用于单向语言模型。实验证明,三种不同的掩盖策略能够让模型在预训练过程学习NLU与NLG任务的信息。UniLM模型的微调与BERT模型的微调没有区别。我们可以使用BERT模型代码直接加载开源出来的UniLM模型进行微调。
图10-7 UniLM 模型结构图 10.3 文本生成任务实践 笔者在10.2节中介绍的UniLM模型需要利用大量的无监督语料数据进行预训练,最终得到可用的模型。受限于预训练所需的硬件设备,本文实验将对利用UniLM模型的序列到序列掩盖策略与预训练模型进行结合,直接构造下游任务进行微调,这样可以省去了预训练的过程,而且我们还能沿用文本分类的代码框架结构,达到代码复用且文本生成性能优良的效果。
预训练模型如BERT模型本身就经过了大量无监督语料的预训练,其已经具备很好的语义表征能力,在NLU任务上表现出色。为了在NLG任务上表现优良,文本生成模型可以利用预训练模型强大的表征能力,再配以相应的下游结构进行微调,就能学习到NLG任务的信息,无需耗费过高的时空成本进行预训练学习。
UniLM模型应用的三种预训练掩盖策略中,序列到序列的掩盖策略对文本生成任务起到较大的作用。在其他参数与正常使用预训练模型一致的前提下,序列到序列的掩盖策略只需要修改输入到预训练模型的自注意力掩盖矩阵(self-attention mask)就能直接使用预训练模型的权重,修改成本低,但却能有效地保证文本生成任务的准确性。
文本生成任务可以简单理解为模型根据输入句子A的语义信息,输出符合既定目标的句子B。序列到序列的网络结构是通过句子A的语义信息,逐字迭代出句子B的每一个字。因此,通过修改自注意力掩盖矩阵,我们首先保证句子A中的每一个字符令牌能够互相观看到句子A中的所有字符令牌,这样能满足自注意力机制(self-attention)。其次,在自注意力掩盖矩阵中,保证句子B的每一个字符令牌只能从左往右地被查看,这样就能保证序列到序列的策略能够有效。
由图10-8可知,“[CLS]你是哪国人[SEP]”可以看成句子A,“中国人[SEP]”可以看成句子B。句子A对应的掩盖矩阵是全1矩阵,也就是句子A中的每一个字符令牌在训练过程中都能互相看到对方的信息,而句子B则对应一个下三角为1的矩阵,这样保证句子B从左往右的每一个字符令牌在训练过程中只能看到左边序列的信息,也就是“国”字符令牌只能看到它之前的字符令牌但看不到“人”与“[SEP]”字符令牌,从而保证模型拥有序列到序列的能力。其中,自注意力矩阵中的0代表模型无需关注的信息,在计算自注意力(self-attention)的时候会被自动忽略,这也包含用来保证模型输入长度一致的补充字符令牌“[PAD]”,其在自注意力掩盖矩阵中同样用0表示。
另外,我们也可以从图10-8中看到行为“[CLS]你是哪国人[SEP]中国人”,列为“你是哪国人[SEP]中国人[SEP]”,掩盖矩阵同时也通过字符令牌的错位来保证模型有用序列到序列的能力,因此这两句话分别构成了文本生成模型的输入与输出,模型结构如图10-9所示。
图10-8序列到序列的自注意力掩盖矩阵 图10-9文本生成模型结构图 因此,在构建完自注意力矩阵之后,我们将该矩阵与其他参数输入到预训练模型中,获得预训练模型的语义表征,并将这个语义表征喂入序列到序列下游结构中进行迭代训练,从而得到一个文本生成模型。
10.3.1 数据介绍 本文实验采用阿里天池的中医药文本生成数据集,每一条数据由一个文本段(text)与多组问答对(Q&A)组成。文本生成的任务是根据文本段(text)与答案(A),生成对应的问题(Q)。根据本节所介绍的模型原理,我们可以将输入数据构造成“[CLS] text [SEP] A [SEP] Q”,输出数据构造成“text [SEP] A [SEP] Q [SEP]”,通过预训练模型与序列到序列模型构造的模型进行逐字递归预测,从而完成文本生成任务。
一些ubuntu系统问题的解决汇总(持续更新) 一、ubuntu16.04下无法连接wifi(试遍所有方法及解决方案)二、PLC安装踩坑总结(Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9)三、xubuntu桌面系统和ubuntu桌面系统相互切换四、ubuntu20.04下找不到NVIDIA相关命令【未完待续】 一、ubuntu16.04下无法连接wifi(试遍所有方法及解决方案) 《ubuntu16.04下无法连接wifi(试遍所有方法及解决方案)》
问题描述:前一天正常使用,第二天突然没网,右上角网络标识无连接(非扇形),且不显示附近的wifi信息。
注:由于安装的是双系统不是虚拟机,在win下解决的方案未尝试。
二、PLC安装踩坑总结(Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9) 《PLC安装踩坑总结(Ubuntu 16.4+PCL1.8.1+VTK7.1+Qt5.9.9)》
台式机(有anaconda环境,许多依赖文件和库与PCL中冲突,比较难搞)
三、xubuntu桌面系统和ubuntu桌面系统相互切换 《由xubuntu桌面系统恢复到ubuntu桌面系统》
不知怎么回事,笔记本和台式机相继自己变成了xubuntu,好不习惯。大佬教程,亲测可用。
毕竟2021了,Ubuntu 16.04各种提示升级新版本,网上很多教程、还有软件及库的配置都逐渐匹配高版本了,本着节约时间、减少麻烦的目的,决定抛弃老旧观念、升级了Ubuntu 20.04(据说比18.04稳定且好用)。
嗯,装好了,Ubuntu 20.04真香!!!
四、ubuntu20.04下找不到NVIDIA相关命令【未完待续】 之前也炼丹过,知道nvidia显卡驱动是安装了的。最近想跑一个Elasticfusion,配置环境的时候发现nvidia驱动不能用了,于是重装,记录一下。
《ubuntu20.04下找不到NVIDIA相关命令》
使用LSTM算法处理的序列经常是变长的,这里介绍一下PyTorch框架下使用LSTM模型处理变长序列的方法。需要使用到PyTorch中torch.nn.utils包中的pack_padded_sequence()和pad_packed_sequence()两个函数。pack:压缩;pad:填充。
pack_padded_sequence()函数
def pack_padded_sequence(input, lengths, batch_first=False, enforce_sorted=True): # type: (Tensor, Tensor, bool, bool) -> PackedSequence r"""Packs a Tensor containing padded sequences of variable length. :attr:`input` can be of size ``T x B x *`` where `T` is the length of the longest sequence (equal to ``lengths[0]``), ``B`` is the batch size, and ``*`` is any number of dimensions (including 0). If ``batch_first`` is ``True``, ``B x T x *`` :attr:`input` is expected.
文章目录 前言搭建效果环境创建html文件创建css文件绑定按钮事件 创建messaage组件construct()setOption(options)完整的js代码小结 结语 前言 使用vue的朋友应该或多或少都知道element-ui组件吧,这篇博客我将使用原生js实现一个“低配”版本的message组件。
开始前先给出element-ui message组件的网址链接,不论是否有使用过,大家都可以参照的对比。
目标message组件
搭建效果环境 为了演示实现效果,所以我们必须得需要一个完整的运行环境,以如下图案例搭建一个基本的环境:
创建html文件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>messageComponent</title> <link rel="stylesheet" href="./index.css"> <style> body { width: 100%; height: 1000px; overflow: hidden; } .button { width: 100px; height: 30px; border: none; cursor: pointer; display: block; margin-top: 20px; } </style> </head> <body> <button id="button1" class="button" style="background-color:rgb(167, 167, 163);">消息</button> <button id="button2" class="button" style="background-color: rgb(12, 199, 137);"
最近写算法的时候发现网上关于BiLSTM加Attention的实现方式五花八门,其中很多是错的,自己基于PyTorch框架实现了一版,主要用到了LSTM处理变长序列和masked softmax两个技巧。代码如下:
1、attention_utils.py
from typing import Dict, Optional import numpy as np import torch import torch.nn.functional as F from torch import Tensor def create_src_lengths_mask( batch_size: int, src_lengths: Tensor, max_src_len: Optional[int] = None ): """ Generate boolean mask to prevent attention beyond the end of source Inputs: batch_size : int src_lengths : [batch_size] of sentence lengths max_src_len: Optionally override max_src_len for the mask Outputs: [batch_size, max_src_len] """ if max_src_len is None: max_src_len = int(src_lengths.
centos7 安装 mysql8 总结(离线) 目录
centos7 安装 mysql8 总结(离线)
1,资源准备
1.1 mysql安装包下载
1.2 上传工具下载
1.3 数据库连接工具
2,安装与配置
2.1 上传数据库安装包
2.2 解压
2.3 重命名
2.4 修改配置文件
2.5 初始化数据库(初始化过程有随机的 root 密码,注意输出信息)
2.6 安装加密算法
2.7 启动mysql
2.8 配置数据库的 sock 文件,并修改 root 用户的初始密码
2.9 配置mysql用户允许远程访问:
2.10 mysql密码模式修改
2.11 关闭防火墙
2.12 mysql的其他命令: 启动,进入,停止, 重启,状态
3,连接测试
于使用环境原因, 这里只写离线安装的步骤,本流程在centos7.8上安装成功
1,资源准备 1.1 mysql安装包下载 下载地址:mysql官网
1.2 上传工具下载 XshellXftpPortable
提取码:4dpl 1.3 数据库连接工具 Navicat Premium 12.zip
提取码:l9fg 2,安装与配置 2.0创建用户组 [root@localhost ~]# groupadd mysql [root@localhost ~]# useradd -r -g mysql -s /bin/false mysql 2.
mysql设置wait timeout_mysql修改wait_timeout_MySQL(转载) 原文链接:【mysql设置wait timeout_mysql修改wait_timeout_MySQL_宽客之家的博客-CSDN博客】https://blog.csdn.net/weixin_42221522/article/details/113169105
mysql修改wait_timeout
mysql mysql> show global variables like ‘wait_timeout’;
其默认值为8小时
mysql的一个connection空闲时间超过8小时,mysql会自动断开该连接。
1.修改配置 vi /etc/my.cnf [mysqld] wait_timeout=10 # /etc/init.d/mysql restart 2.直接用sql命令行修改 mysql> set global wait_timeout=10; mysql> show global variables like ‘wait_timeout’; ±---------------------------±------+ | Variable_name | Value | ±---------------------------±------+ | wait_timeout | 10 | ±---------------------------±------+ show variables like ‘%time%’; timeBetweenEvictionRunsMillis = 20000 #dbcp每2000秒进行一次connection的检 minEvictableIdleTimeMillis = 28700 #每次检验中将超过28700秒处于空闲的connection断开
bitsCN.com
本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉
本文系统来源:php中文网
TAG标签:mysql
命令:show variables like ‘%timeout%’;
1.select选择列表
1.查询全部信息
select * from 表名; (*代表全部)
2.局部查询 (中括号中内容可加可不加)
select 字段1 [字段1列别名] ,字段2 [字段2列别名] from 表名;
3.查询不重复的信息
select distinct 字段 [列别名] from 表名;
2.mysql中的运算符
1.算数运算符: +(加),- (减),* (乘), / (除) , % (取余)
2.比较运算符:=(等于),<=>(完全等于),!=(不等于),>=(大于等于),<= (小于等于) >(大于),<(小于),is null(判断一个值是否为null),in not null(判断一个值是否不为null)
3.逻辑运算符:and或&&(与),or或||(或),not或!(非),xor(异或)
3.定制显示查询
1.对列进行升序排序
select * from 表名 [where] order by asc
order by为排序,排序默认为升序 asc 升序
2.对列进行降序排序
select * from 表名 [where] order by desc
desc为降序
如果有多个字段需要排列,则按从前到后排序,每个排序需用逗号隔开
例:select * from 表名 [where] order by 字段1 排序方式,字段2 排序 方式;
我是结合的vant weapp的checkbox实现的,官网文档地址
要实现以上复选框功能:
官网文档中举例子
复选框组 需要与van-checkbox-group一起使用,选中值是一个数组,通过value绑定在van-checkbox-group上,数组中的项即为选中的Checkbox的name属性设置的值。 <van-checkbox-group value="{{ result }}" bind:change="onChange"> <van-cell-group> <van-cell wx:for="{{ list }}" wx:key="index" title="复选框 {{ item }}" value-class="value-class" clickable data-index="{{ index }}" bind:click="toggle" > <van-checkbox catch:tap="noop" class="checkboxes-{{ index }}" name="{{ item }}" /> </van-cell> </van-cell-group> </van-checkbox-group> Page({ data: { list: ['a', 'b', 'c'], result: ['a', 'b'] }, onChange(event) { this.setData({ result: event.detail }); }, toggle(event) { const { index } = event.currentTarget.dataset; const checkbox = this.
需求:unity内置的调节间距的只有行距,无法调节字的间距,只能通过代码来实现调节字间距的效果。
内容我是百度别人的拿来直接用的,附一下大佬的地址
using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Playables; using UnityEngine.SceneManagement; using UnityEngine.UI; namespace ZXL { /// <summary> /// 对话系统 /// </summary> public class DialogueSystem : MonoBehaviour { public Sprite[] sprites; public Image img_HeadPortrait; public Text txt_Context; public string path;//文件路径 List<string> imgList; List<string> txtList; private int index; public float logSpeed;//打印速度 private bool isLoging;//打印中 private bool isLog;//直接打印 private void Awake() { imgList = new List<string>(); txtList = new List<string>(); index = 0; isLoging = false; isLog = true; path = Application.
export1(){ axios.get(`/api/medical-live/logininfor/export`, { params: {}, contentType: 'application/json', cache: true, responseType: "blob" }).then((res) => { const link = document.createElement("a"); let blob = new Blob([res.data], { type: "multipary/form-data" }); link.style.display = "none"; link.href = URL.createObjectURL(blob); link.setAttribute("download", decodeURI(Date.now()+'访问量.xlsx')); document.body.appendChild(link); link.click(); document.body.removeChild(link); console.log(res); }) }, 后台返回
设置 responseType: “blob”
参考:https://blog.csdn.net/whitehats/article/details/111671444
多线程有什么用?线程和进程的区别是什么?ava实现线程有哪几种方式?启动线程方法start()和run()有什么区别?怎么终止一个线程?如何优雅地终止线程?一个线程的生命周期有哪几种状态?它们之间如何流转的?线程中的wait()和sleep()方法有什么区别?多线程同步有哪几种方法?什么是死锁?如何避免死锁?多线程之间如何进行通信?线程怎样拿到返回结果?violatile关键字的作用?新建T1、T2、T3三个线程,如何保证它们按顺序执行?怎么控制同一时间只有3个线程运行?为什么要使用线程池?常用的几种线程池并讲讲其中的工作原理。线程池启动线程submit()和execute()方法有什么不同?CyclicBarrier和CountDownLatch的区别?什么是活锁、饥饿、无锁、死锁?什么是原子性、可见性、有序性?什么是守护线程?有什么用?怎么中断一个线程?如何保证中断业务不影响?一个线程运行时发生异常会怎样?什么是重入锁?Synchronized有哪几种用法?Fork/Join框架是干什么的?线程数过多会造成什么异常?说说线程安全的和不安全的集合。什么是CAS算法?在多线程中有哪些应用。怎么检测一个线程是否拥有锁?Jdk中排查多线程问题用什么命令?线程同步需要注意什么?线程wait()方法使用有什么前提?Fork/Join框架使用有哪些要注意的地方?线程之间如何传递数据?保证”可见性”有哪几种方式?说几个常用的Lock接口实现锁。ThreadLocal是什么?有什么应用场景?ReadWriteLock有什么用?FutureTask是什么?怎么唤醒一个阻塞的线程?不可变对象对多线程有什么帮助?多线程上下文切换是什么意思?Java中用到了什么线程调度算法?Thread.sleep(0)的作用是什么?Java内存模型是什么,哪些区域是线程共享的,哪些是不共享的什么是乐观锁和悲观锁?Hashtable的size()方法为什么要做同步?同步方法和同步块,哪种更好?什么是自旋锁?Runnable和Thread用哪个好?Java中notify和notifyAll有什么区别?为什么wait/notify/notifyAll这些方法不在thread类里面?为什么wait和notify方法要在同步块中调用?为什么你应该在循环中检查等待条件?Java中堆和栈有什么不同?你如何在Java中获取线程堆栈?如何创建线程安全的单例模式?什么是阻塞式方法?提交任务时线程池队列已满会时发会生什么?
毕业设计是CV方向的,一直在调试tracker_benchmark_v1.0的代码,遇到了很多的问题,本篇博客记录我遇到的问题和解决的办法,也许还有错误的地方,欢迎大家一起讨论研究~
一、介绍和注意事项
我用的环境是MATLAB2019b
首先是到Visual Tracker Benchmark官网下载压缩包
解压得到文件后会有十五个项目,这里我对几个重要的项目进行介绍
项目名称存储的内容或功能figsoverall文件夹下存储perfPlot.m运行得到的图像,每次运行结果会得到24张图片,其中12张准确率图12张成功率图,12张图片中1张是全局对比图11张是11种挑战属性下对比图perfMatoverall文件夹下存储perfPlot.m运行得到的图像对应的.mat文件,一般有两个results存储的是main_running.m运行生成的.mat文件tmpimgs文件夹下存储的是drawResultBB.m运行得到的实时跟踪图trackers一共23个项目,其中VIVID_Tracker中包含5种跟踪算法util存储的是一些重要的.m文件drawResultBB.m用于绘制实时跟踪图main_running.m用于生成.mat文件perfPlot.m用于绘制准确率和成功率对比曲线 注意
1.11种挑战属性
挑战属性缩写挑战属性含义IV光照变化SV尺度变化OCC遮挡DEF形变MB运动模糊FM快速运动IPR平面内旋转OPR平面外旋转OV离开视野BC相似背景LR低分辨率 2.我有一个习惯就是每次运行不同跟踪算法的perfPlot.m之前,我都会删除figs\overall和perfMat\overall下的所有文件
3.我们需要手动在results文件夹下创建一个results_OPE_CVPR13文件,存放OPE标准下生成的.mat文件
4.我们需要手动在tmp文件夹下创建OPE.txt和SRE.txt,用于存储OPE标准下或SRE标准下运行程序生成的日志
5.util文件夹下我们主要修改configSeqs.m和congfiTrackers.m
运行的流程主要是main_running.m生成.mat文件,drawResultBB.m生成实时跟踪图,perfPlot.m生成对比曲线图。
二、configSeqs.m配置
1.到Visual Tracker Benchmark官网下载OTB数据集所有视频序列,包括OTB50和OTB100(依次点击每个图片)
如果你觉得费劲
OTB50网盘链接,提取码:2gvh
OTB100网盘链接,提取码:cqiw
2.修改configSeqs.m视频路径
按照下述方法修改,主要就是把视频路径更改一下然后在后面加上\img
如果你觉得费劲
修改好的configSeqs.m网盘链接,提取码:59jv
(视频是在OTB50还是OTB100我已经对应好了,你只需要修改前面的路径,也就是C:\Users\86139\Desktop\这块内容)
seqVTD={struct('name','singer1','path','C:\Users\86139\Desktop\otb100\Singer1\img\','startFrame',1,'endFrame',351,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','soccer','path','C:\Users\86139\Desktop\otb50\Soccer\img\','startFrame',1,'endFrame',392,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','matrix','path','C:\Users\86139\Desktop\otb50\Matrix\img\','startFrame',1,'endFrame',100,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','ironman','path','C:\Users\86139\Desktop\otb50\Ironman\img\','startFrame',1,'endFrame',166,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','deer','path','C:\Users\86139\Desktop\otb50\Deer\img\','startFrame',1,'endFrame',71,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','skating1','path','C:\Users\86139\Desktop\otb50\Skating1\img\','startFrame',1,'endFrame',400,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','shaking','path','C:\Users\86139\Desktop\otb50\Shaking\img\','startFrame',1,'endFrame',365,'nz',4,'ext','jpg','init_rect', [0,0,0,0]),... struct('name','singer2','path','C:\Users\86139\Desktop\otb50\Singer2\img\','startFrame',1,'endFrame',366,'nz',4,'ext','jpg','init_rect', [0,0,0,0])}; 三、configTrackers.m配置
1.其中包含三个部分trackersVIVID、trackers1、trackersEXE,我是注释了三个部分(ctrl+r),然后自己写了一个模块trackersTEST,测试CXT和CSK跟踪算法(你有什么需求可以更改对应的代码),对应的代码如下
function trackers=configTrackers trackersTEST={struct('name','CSK','namePaper','CSK'),... struct('name','CXT','namePaper','CXT')}; trackers = [trackersTEST]; 2.至于trackerVIVID中包含的MS、PD、RS、TM、VR5种跟踪算法,我一直没有调试出来,调试运行到每个run_XXX.m文件中报错
函数或变量tkMeanShift_Init未定义 函数或变量tkMeanShift_Next未定义 函数或变量tkPeakDifference_Init未定义 函数或变量tkPeakDifference_Next未定义 函数或变量tkRatioShift_Init未定义 函数或变量tkRatioShift_Next未定义 函数或变量tkTemplateMatch_Init未定义 函数或变量tkTemplateMatch_Next未定义 函数或变量tkVarianceRatio_Init未定义 函数或变量tkVarianceRatio_Next未定义 其中每个函数都有对应的dll文件,我一开始怀疑自己的MATLAB版本过高,无法解析动态dll库,以致函数无法识别,但是我尝试了很多版本的MATLAB以后发现还是不行,如果有解决这个问题的同学,欢迎一起交流讨论(最后我是放弃了这五个跟踪算法,还有很多跟踪算法在调试的过程中出现问题,我也是直接选择了放弃,我主要利用这个数据集进行自己算法和KCF等一些算法的比较,所以这些算法没有调试出来也没有太大的影响)
注意
1.像视频序列Jogging里面有两个groundtruth_rect.txt,对于这种视频序列,我们把其一分为二,分成Jogging-1和Jogging-2两个视频序列(其中的img文件夹是一样的,这种情况是因为视频序列中由两个跟踪目标,每一个.txt文件对应其中一个目标的pos和target_sz)
四、main_running.m配置
1.我建议把MATLAB的当前文件夹改成tracker_benchmark_v1.0,这样所有的addPath都不会报错,否则需要更改为绝对路径
概述
数据元素是数据模型的基本要素,用于描述图形网元,业务网元,或者纯数据。TWaver HTML5中所有数据元素都继承自twaver.Data。为不同功能的需求,预定义了三类数据类型:twaver.Element,twaver.Alarm,twaver.Layer,分别用来描述拓扑的网元,告警和图层。其中拓扑网元扩展定义了十几种网元类型,用以描述丰富的拓扑网元特性,其中最常用的几类拓扑网元包括:Node、Link、Group、SubNetwork、Grid等,TWaver中网元的继承关系如下图,本章将详细介绍这些网元以及其他数据类型的特性,使用以及扩展应用。
基本数据元素(Data)
twaver.Data是TWaver HTML5中最基本的数据元素,默认定义了id,name,name2,icon,toolTip,parent,children等基本属性,支持事件派发和监听,由它扩展出来还有twaver.Element,twaver.Alarm,twaver.Layer等数据类型。
事件派发与监听
twaver.Data继承于twaver.PropertyChangeDispatcher类,内部包含一个twaver.EventDispatcher实例对象,这使得Data具有派发事件和监听事件的功能,可以通过调用下面的方法派发事件或者添加监听器:
//派发属性变化事件
firePropertyChange:function(property,oldValue,newValue)//添加属性变化监听器
addPropertyChangeListener:function(listener,scope,ahead)//删除属性变化监听器
removePropertyChangeListener:function(listener)//属性发生变化的处理方法
onPropertyChanged:function(listener)
基本属性
定义了一些基本属性,包括id,name,name2,icon,toolTip等。
/**
*id:网元的id,如果未设置,TWaver内部会分配唯一的Id。*/twaver.Data:function(id)
getId:function()
setName:function(value)
getName:function()
setName2:function(value)
getName2:function()
setIcon:function(value)
getIcon:function()
setToolTip:function(value)
getToolTip:function()
Note:name2为新增加的属性,增大了label设置的灵活性。
如果需要设置其他属性,可以通过setClient()/getClient()方法设置自定义的属性(包括对象)。
//设置Client属性;
setClient = function(clientProp,newValue)//获取Client属性
getClient = function(clientProp)
Note:setClient()存放数据类似于Java中的HashMap。
示例:
var box = newtwaver.ElementBox();var network = newtwaver.vector.Network(box);functioninit() {
initNetwork();
initDataBox();
}functioninitNetwork() {var view =network.getView();
document.body.appendChild(view);
network.adjustBounds({x:0, y: 0, width: 1300, height: 600});
network.getToolTip= function(element) {var Id =element.getId();var name =element.getName();var name2 =element.getName2();var icon =element.
目录 一、入门基础1.1 单选题1.2 多选题1.3 判断题 二、数据集2.1 单选题2.2 多选题2.3 判断题 三、模板3.1 单选题3.2 多选题3.3 判断题 四、报表设计4.1 单选题4.2 多选题4.3 判断题 五、参数5.1 单选题5.2 多选题5.3 判断题 六、图表6.1 单选题6.2 多选题6.3 判断题 七、填报7.1 单选题7.2 多选题7.3 判断题 八、设计器操作8.1 单选题8.2 多选题8.3 判断题 九、变量与函数9.1 单选题9.2 多选题9.3 判断题 十、控件10.1 单选题10.2 多选题10.3 判断题 十一、移动端11.1 多选题11.2 判断题 十二、服务器部署12.1 单选题12.2 多选题12.3 判断题 十三、后端开发能力13.1 单选题13.2 多选题13.3 判断题 十四、前端开发能力14.1 单选题14.2 多选题14.3 判断题 十五、linux指令15.1 单选题15.2 判断题 十六、平台操作16.1 单选题16.2 多选题16.3 判断题 十七、网络环境17.1 单选题17.2 多选题17.3 判断题 十八、常见数据库特性18.1 单选题18.2 判断题 一、入门基础 1.
js中foreach是用于遍历数组的方法,将遍历到的元素传递给回调函数,遍历的数组不能是空的要有值。
foreach 语法: [ ].forEach(function(value,index,array){ //code something }); forEach()方法对数组的每个元素执行一次提供的函数。
var array = ['a', 'b', 'c']; array.forEach(function(element) { console.log(element); }); 输出为:
a; b; c; forEach()方法对数组的每个元素执行一次提供的函数。总是返回undefined;
var arr = [1,2,3,4]; arr.forEach(alert); //等价于: var arr = [1, 2, 3, 4]; for (var k = 0, length = arr.length; k < length; k++) { alert(array[k]); } forEach方法中的function回调有三个参数:
第一个参数是遍历的数组内容,
第二个参数是对应的数组索引,
第三个参数是数组本身
forEach使用的坑 1.forEach不支持break
大家都知道,在使用for循环时可以使用break跳出循环,比如我希望找到数组中符合条件的第一个元素就跳出循环,这对于优化数组遍历是非常棒的。很遗憾,forEach并不支持break操作,使用break会导致报错。
let arr = [1, 2, 3, 4], i = 0, length = arr.
太原理工大学2021软件学院数据结构课程设计第二题(构造可以使n个城市连接的最小生成树)核心代码 Java+c(2021.6.6) 声明:这里只是给出核心代码 核心代码指程序的计算部分,不是完整程序 题目背景:P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式 第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。
接下来 M 行每行包含三个整数xi,yi,zi,表示有一条长度为zi的无向边连接结点 xi,yi.
输出格式 如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
输入输出样例 **输入 **
4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3 输出 #1
7 最小生成树背景知识 1.最小生成树的代价指最小生成树各边长度之和
Kruscal算法代码 import java.io.*; import java.util.Arrays; import java.util.Comparator; /** * @see 图论 Kruscal https://www.luogu.com.cn/problem/P3366 https://www.acwing.com/solution/content/30279/ */ public class Main { static class Edge { int a, b, w; public Edge(int a, int b, int w) { this.
目录 字符串的概念字符串的定义举例1结果 举例二结果 经典例题解析 字符串的概念 在C语言中,所谓的字符串,就是一个字符型的数组,可以看作多个字符组合在一起,我们将它理解为字符串。
eg: “abcd”
字符串的定义 字符串的定义有两种方式:
char s1[ ] = “abcd”;char s2[ ] = {‘a’,‘b’,‘c’,‘d’}; 如果你认为上面两种定义看似没什么区别,那么你可就大错特错了。
这里我们将引入'\0'(字符串结束标志)这个转义字符的概念。
举例1 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { char s1[]="abcd"; //方式1定义,默认结尾处补充一个'\0' char s2[]={'a','b','c','d'};//方式2定义,不会补充'\0' printf("s1 大小 %d\n",sizeof(s1)); printf("s2 大小 %d\n",sizeof(s2)); } 结果 解析:
1.这里sizeof() 分别计算s1,s2的大小,发现s1除了’a’,‘b’,‘c’,‘d’,四个元素外,还多了一个元素,根据监视窗口,可以证明多出来的元素就是'\0'
2.用方式2定义的s2的大小为4,证明没有自动在末尾追加'\0'
那么我们为什么要研究'\0'这个东西呢?
举例二 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <string.h> int main() { char s1[]="abcd"; //方式1定义,默认结尾处补充一个'\0' char s2[]={'a','b','c','d'};//方式2定义,不会补充'\0' printf("s1 长度 %d\n",strlen(s1)); printf("s2 长度 %d\n"
目录 1. yum包管理器1.1 yum包管理器是干什么的?1.2 yum的基本使用命令 2. Linux开发工具相关2.1 vim编辑器2.1.1 vim是什么?2.1.2 vim的简单介绍2.1.3 vim的功能按键2.1.4 底行模式中常用的指令 2.2 gcc/g++编译器2.2.1 作用2.2.2 命令格式及参数解释2.2.3 编译过程及参数使用 2.3 gdb调试工具2.3.1 gdb调试前的准备2.3.2 gdb调试的小命令2.3.3 gdb调试命令的演示 2.4 make/makefile自动化构建工具2.4.1 自动化构建是什么2.4.2 makefile文件怎么写2.4.3 makefile工作原理2.4.4 内置变量和自定义变量 2.4 git代码管理工具2.4.1 linux下的git工具使用 总结 注:以下所有命令执行,都是基于linux系统centos7.5版本下
1. yum包管理器 1.1 yum包管理器是干什么的? 在linux系统中安装软件,通常是下载软件源码,并进行编译得到可执行程序。这种做法过于复杂,所以就有了形同windows的软件商店,通过商店直接下载软件包,进行直接安装。
1.2 yum的基本使用命令 罗列liunx下的所有可以下载的软件包,命令: yum list。
上图可以看出直接罗列出来软件实在太多了,难以分辨,所以使用grep筛选出我们想看到的软件包。命令: yum list | grep [软件包名]
安装软件,命令: yum install (-y) [软件包名] linux中安装文件需要向系统目录中写入文件,所以需要使用sudo命令或者切换到root用户下。
安装软件时必须逐个安装,不能同时安装多个。
这里以安装 lrzsz 为例,该软件是用于windows和远端linux机器通过xshell传输文件的。
此页面显示已经安装了该软件,进行的更新操作。
卸载软件 yum remove (-y) [软件包名称]
这里以卸载lrzsz为例。
2. Linux开发工具相关 在liunx系统中,我们最常用的功能无疑就是对软件的开发了,如何进行程序的书写,程序的编译,调试,代码的管理,将会在下文中详细介绍以上功能。
java系统 性能优化实战 java代码优化可优化的代码 java代码优化 架构师在优化java系统性能的过程中,可以做出很多重要决策以全面提升系统的性能,例如使用高版本的jdk,引入Redis或redis+JVM缓存,甚至考虑JVM缓存分成多层,比如热点缓存+普通数据缓存等。
在数据上可以考虑数据库分库分表或者一主多从,考虑引入中间件提供表的路由,引入分布式管理器或者状态机保证事务一致性。对于大数据查询,可以考虑Elasticsearch或Hive大数据系统建立统一的数据查询接口,架构师需要考虑如何把数据库的数据同步带大数据系统,以及Redis缓存中。
系统交互上使用消息中间件实现异步通信,也可以使用RPC进行远程调用,架构师还可以把单体系统服务改成微服务系统,这种架构的改变“牵一发而动全身”。
优化系统的方式主要是优化自己或者他人写的代码。代码是系统的基石,没有良好的代码,系统架构不牢固。
可优化的代码 来看一段优化前的代码:
public Map buildArea(List<Area> areas){ if(areas.isEmpty()){ return new HashMap(); } } Map<String,Area> map =new HashMap(); for(Area area :areas){ String key=area.getProvinceId()+"#" +area.getCityId(); map.put(key,area); } return map; 当判断这段代码每次请求都被调用说明这段代码需要进行优化、方法返回值是个Map,非常不容易阅读,因为当其他代码阅读者看到方法签名是并不清楚Key和Value的类型,必须阅读代码才知道,因此将方法签名改成如下内容:
public Map<String,Area> buildArea(List areas)
Map中的key是字符串类型,使用者必须了解方法的实现才知道如何使用Key,这里有两种方法改善方法。
一是在方法的Javadoc注释说明Key的格式:
/** *构建一个地址Map *@param areas 初始化地址列表 *@return Key的格式是省编号+“#”+市编号 */ public Map<String,Area> bulidArea(List<Area> areas) 二是在使用buildArea方法是通过一个有意义的名称来描述,例如:
Map<String,Area> provinceCityMap=buildArea(areas); 这两种方法都能帮助阅读者明白bulidarea返回值的含义,但仍然有一定的阅读负担,使用者不得不再次阅读注释来了解Map的含义,注释很少跟随代码的改动很少,而重构往往遗漏了注释,如果Key值得构成发生了变化,比如包含城镇编号:
String key=area.getProvinceId()+"#"+areaa.getCityId()+"#"+area.getTownId(); 以String来描述对象,这个改动对于项目来说是一个巨大的灾难,所有使用buildArea的地方都必须改动,如服务果忘记了,则会造成损失,导致服务不可用。
这段代码从可读性和性能上来说,最大的问题时Key值得类型是String, 从可读性上来说,字符串让人难以理解其构成,即使方法签名从Map变成Map<String,Area>,仍然难以理解,如果想用字符串来表达一个对象,那么嗨不如直接使用一个对象,我们可以创建一个新的对象来描述“需求”:
@Getter @Setter public class CityKey { private Integer provinceId; private Integer cityId; } 这样,代码可以改成如下内容:
实现目标 输入 N = 4 N=4 N=4 个数,通过简单选择排序,对这个四个数进行简单选择排序:每次选择最小的,将最小的数移到起始位置,之后输出。这是同步时序电路和状态机的高级应用。
伪代码 设输入 N N N 个数,将其存在寄存器数组 R R R 中;两个循环变量 i , j i,j i,j;将每次遍历到的数分别赋值给 A , B A,B A,B。
简单选择排序的伪代码可以描述如下:
for i = 0 to N-2 do A = R[i]; for j = i to N-1 do B = R[j]; if B < A then R[i] = B; R[j] = A; A = R[i]; end if; end for; end for; 数据通路设计 主要牵涉到两大块结构:
一、confluence7.11版本的excel插件点击编辑后不能直接跳转 问题描述 老版本confluence6.9.1里使用excel插件点击编辑后直接跳转到excel软件,但在新装的confluence7.11里点击编辑却出现下面的问题
解决办法: 等待右上角的变成上图一样后,点击下载Windows版,下载完成后点击安装.安装完成后如下图
回到要编辑的excel里面再次点击编辑,会出现打开Atlassian Companion的提示。
点击信任,就能打开了。
二、confluence批量删除页面历史版本 问题 编辑Confluence页面,容易产生大量的Confluence页面历史版本,而这在存储硬盘中也占用了大量的空间。默认Confluence页面上没有地方提供批量删除页面历史版本。
解决办法 使用Confluence命令行删除页面历史版本:
./confluence.sh --user ${USER} --password ${PASSWORD} --action removePageVersions --space "${SPACE}" --title "${TITLE}" --limit "${LIMIT}" 其中:
${USER} - Confluence用户名${PASSWORD} - Confluence密码${SPACE} - Confluence空间Key${TITLE} - Confluence页面标题${LIMIT} - Confluence页面最大版本号。如"12",则表示删除12及小于12的页面版本。 还可以使用命令行清理空间:
./confluence.sh --user ${USER} --password ${PASSWORD} --action removeTrash --space "${SPACE}" 三、confluence-还原后浏览器访问不了或者显示不完全 问题描述: confluence还原到另外一台机器上,不同的电脑访问可能会出现访问不了或者能访问成功,但是内容显示不完整
问题原因: 浏览器里面有缓存,缓存可能会影响你的访问
解决方法
这里一谷歌浏览器做演示
1.打开设置,在搜索框里搜索缓存
2.点击清除缓存,时间选择不限,点击清除缓存即可
3.新建一个标签页去访问confluence,你就会发现已经可以了。
一、confluence关联JIRE 1.用管理员账号登录到confluence——>点击设置——>点击一般配置
2.在左侧导航栏里找到应用程序链接
3.在出入框里输入JIRE的地址,点击创建新链接然后根据步骤一步步走下去即可。
二、以JIRA为用户服务器 1.补充说明 通过此方法集成后,用户、组以及用户和组的关系都在JIRA系统中维护,但各个系统的权限仍由各系统控制在做步骤4和步骤5的时候,要特别小心,确保当前系统的超级权限用户(一般为admin,具体看当前系- - 统的全局权限配置)和组已经在JIRA中同样存在了,才可切换并禁用当前系统的内部用户目录,否则可能造成权限丢失等严重问题(因为禁用了内部用户目录,而JIRA中又不存在这个超级权限用户和组,所以权限就丢失了)维护示例:
比如Confluence默认全局权限是属于confluence-users组中的成员才允许访问Confluence,那么在JIRA中添加用户A后,想让其能访问Confluence,则需要将其加入confluence-users组在JIRA上添加了用户A并加入confluence-users组后,JIRA上这个用户A信息立即是最新的,但是Confluence上默认要过60分钟后自动同JIRA用户服务器,如果想Confluence也立即生效,则需您以有管理员权限的用户登录Confluence后台->用户目录,手动点击“用户来自JIRA”用户目录的[同步]按钮进行立即同步。 2.在JIRA中,将Confluence系统中的用户、组以及用户和组的关系同样建一份 比如Confluence默认两个用户组:confluence-administrators、confluence-users,confluence默认管理员admin属于这两个组。JIRA默认两个用户组:jira-administrators、jira-software-users,jira默认管理员admin属于这两个组。在JIRA中建一遍confluence中的两个用户组,并将admin也加入这两个组中,最终jira中有4个用户组:jira-administrators、jira-software-users、confluence-administrators、confluence-users,并且admin加入了这4个组 3.在JIRA中,建一个用户服务器 【JIRA后台】>【用户管理】>【JIRA用户服务器】里添加个JIRA用户服务器 4、在Confluence中,建一个JIRA类型的用户目录 【Confluence后台】>【用户&安全】>【用户目录】里添加个JIRA类型的用户目录
5、在Confluence中,同步用户目录并将顺序调为第一 6、在Confluence中,禁用Confluence内部用户目录
前言:大家是不是经常很头疼数据中存在一些诸如undefined、null等字符的情况呢?本文介绍如果快速过滤掉这些数据 用map操作数组一般是很常见的使用方式,但是map需要我们返回一个值,我们通常会判断这个值是否存在,存在才会返回,如下:
const cameraData = collect.map(item => { const res = await service.getCameraInfo(item.id); if(res) return res; }) 但是呢,eslint/snoar又会要求我们返回一个默认值,即当if条件不成立时,返回一个其他值,如下:
const cameraData = collect.map(item => { const res = await service.getCameraInfo(item.id); if(res) return res; return null; }) 这样有可能会导致我们最终拿到的数据存在一些实际并不需要的返回值,结果如下:
camera : [ { cameraId: '1', cameraName: '摄像头一', cameraUrl: 'http://1.2.3.4.flv' }, { cameraId: '2', cameraName: '摄像头二', cameraUrl: 'http://1.2.3.5.flv' }, null ] 还有一种场景是,我们会在map里去获取数据里某个指定的字段返回后组成一个数组,当不含有这个字段也会默认返回undefined,如下:
const data = [ { name: '123', count: 1 }, { name: '456', count: 2 }, { name: '789', count: 3 }, { count: 1, age: 23 }, ] const result = data.