Springboot上传文件的问题(上传到本地文件夹中)
java代码:
先建立一个controller包:
如图所示:
FileUploadController.java代码如下所示:
package com.zcc.springboot_uploadfiles.controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; @RestController public class FileUploadController { SimpleDateFormat sdf = new SimpleDateFormat("yyy/MM/dd/"); @PostMapping("/upload") public String upload(MultipartFile uploadFile, HttpServletRequest req) { String realPath = req.getSession().getServletContext().getRealPath("/uploadFile/"); String format = sdf.format(new Date()); String file = realPath + format; File folder = new File(realPath + format); if(!folder.isDirectory()) { folder.mkdirs(); } String oldName = uploadFile.
先看个例子:
点击box2结果如下:
分析:
因为box2在box1里面,所以点击box2时,也同时点击了box1,这就是事件冒泡
事件冒泡 从最具体的元素到不具体的元素(由内到外)
当子元素(事件源)事件触发,事件会沿着包含关系,依次往上级传递,每一级都可以感知到事件,直到触发根元素(根源) 上面例子的结果显然不是我们想要的, 我们希望的是点谁就显示谁,这时我们可以通过终止事件冒泡来得到我们想要的结果。
终止事件冒泡 方法一:在相应的函数中加上event.stopPropagation()
这是阻止事件的冒泡方法,不让事件向documen上蔓延。
修改第一个例子:
点击box2结果如下:
方法二:判断event.target 和 event.currentTarget是否相等
event.target:指真正触发事件的元素
event.currentTarget:指绑定了事件监听的元素(触发事件元素的父级元素)
这时判断两者相等,则执行相应的处理函数;当事件冒泡到上一级时,event.currentTarget变成 了上一级元素,这时候判断二者不相等,则就不作响应处理逻辑。
修改第一个例子:
点击box2结果如下:
看上面代码,假如有几百个元素,就要判断几百次,会不会有点傻,哈哈哈~
因为每个元素都要添加事件监听处理函数,元素较多时容易代码冗余。所以我们是不是可以找一个父节点统一带领这些小兵嘞。
event.target可以准确地获取事件源(指的是真正触发事件的那个元素),并且在使用的过程中可以比较判断
event.target属性:
event.target.nodeName //获取事件触发元素标签name
event.target.id //获取事件触发元素id
event.target.className //获取事件触发元素classname
event.target.innerHTML //获取事件触发元素的内容
方法二修改如下:
“ 在上一篇文章中讲述了git的相关基础,这一篇就会带领大家具体的进行动手操作,让大家在工作中对git有一个更好的理解。”
提示:在使用git的时候,你需要对linux脚本命令有所了解,如果你很熟悉vim的话,那么恭喜你接下来的相关内容对你来说会非常简单,当然如果你不会的话,也没关系,照着下面的操作你也可以成功实现。 01
—
git rebase的使用
如何修改commit提交
(1)首先我在github远程仓库中创建了一个git的项目,这个时候它里面只有一个READEME.md文件,然后我在本地会使用ssh方式来克隆线上的git项目;
(2)在你指定的文件夹中,右键选择Git Bash Here打开相应的界面,然后使用clone指令克隆文件:
git clone git@github.com:daipi173/git.git ,克隆完成之后你就会在本地看到一个git文件夹,它里面有一个READEME.md文件,此时就证明你已经克隆成功了;
(3)接着我们将git文件夹用vscode编辑器打开,然后开始进行相关的开发操作;
(4)现在我在项目中新增加了两个文件,分别是index.html和second.html文件,这个时候我向本地仓库提交了两个版本,使用git log --oneline查看commit提交的历史,如下图所示:
(5)这个时候我又在second.html文件中添加了一部分内容,然后又commit提交了一个版本,但是这个时候我不小心将commit中的注释内容写错了,如下图所示:
解决办法:由于该提交是最后一次提交的,因此我们可以git commit --amend来修改最后一次提交的信息,需要注意的是:git commit --amend只能修改最后一次提交的信息。当我在vscode终端中敲入指令:git commit --amend之后会显示如下所示内容: 只要你会linux脚本语言就应该很熟悉怎么修改,当我们将光标移动到你修改的地方,然后点击键盘中的i就可以开始进行修改,当你修改完之后先按下键盘上的esc,然后再同时按下shift+:之后(如果没有效果的话,可以尝试先按下键盘上的esc,然后再连续按两次大写字母z),然后再在冒号后面输入wq即可,这个时候你再在vscode终端中输入指令git log --oneline然后会看到修改之后的commit,如下图所示: (6)接着你是不是会想到git commit --amend只能修改最后一次提交的信息,那么如果想修改指定的历史提交应该如何做呢?很简单,这个时候我们应该使用git rebase -i来进行一个解决(在这里i表示interactive互动)。接下来我举一个例子:
假设我将第三次提交的commit进行修改,这个时候我将second.html改为second01.html,然后不想再提交一个注释,而是想将第三次提交的commit中的second.html修改为second01.html,然后具体的步骤如下所示:
a. git add .将修改全部内容放入暂存区中;
b. git commit -m "xxx...";
c. git log --oneline看看我们的commit提交历史,然后找到你要修改的内容,在这里我举的例子如下图所示:
d. 这个时候当我找到要修改第三个commit的内容,然后执行指令:git rebase -i HEAD~3(这里的意思是:从HEAD版本开始往过去数3个版本,3可以换位你要修改内容的位置数);e. 在进入到vim之后,我们找到要修改的commit提交内容之后,然后将它的pick修改为edit,然后保存退出(先按下键盘上的esc,然后再同时按下shift+:之后(如果没有效果的话,可以尝试先按下键盘上的esc,然后再连续按两次大写字母z),然后再在冒号后面输入wq即可),如下图所示:
f. 接着退出vim界面之后,可以按照退出之后git给你的提示进行下一步的操作,接着我们按照提示进行相应的指令:git commit –amend进入修改commit的vim页面,然后我们找到要修改内容之后点击键盘i进行相应的编辑,然后保存退出(保存退出布置和第5步一致);g. 此时你会看见vscode显示的是变基,其原因是因为我们使用rebase的原因,接着要解决的话也是按照git给你的提示来进行:git rebase –continue;h. 这个时候我们再使用指令:git log –oneline就会发现我们指定commit提交的内容已经修改了。注意:如果你想终止rebase的话,可以使用指令:git rebase –abort
如何压缩合并commit提交 就拿上面举的例子来接着做测试,我们是不是会感觉因为修改了一个second01.
之前的系列文章从 CPU 和内存方面简单介绍了一下汇编语言,但是还没有系统的了解一下汇编语言,汇编语言作为第二代计算机语言,会用一些容易理解和记忆的字母,单词来代替一个特定的指令,作为高级编程语言的基础,有必要系统的了解一下汇编语言,那么本篇文章希望大家跟我一起来了解一下汇编语言。
汇编语言和本地代码
我们在之前的文章中探讨过,计算机 CPU 只能运行本地代码(机器语言)程序,用 C 语言等高级语言编写的代码,需要经过编译器编译后,转换为本地代码才能够被 CPU 解释执行。
但是本地代码的可读性非常差,所以需要使用一种能够直接读懂的语言来替换本地代码,那就是在各本地代码中,附带上表示其功能的英文缩写,比如在加法运算的本地代码加上add(addition) 的缩写、在比较运算符的本地代码中加上cmp(compare)的缩写等,这些通过缩写来表示具体本地代码指令的标志称为 助记符,使用助记符的语言称为汇编语言。这样,通过阅读汇编语言,也能够了解本地代码的含义了。
不过,即使是使用汇编语言编写的源代码,最终也必须要转换为本地代码才能够运行,负责做这项工作的程序称为编译器,转换的这个过程称为汇编。在将源代码转换为本地代码这个功能方面,汇编器和编译器是同样的。
用汇编语言编写的源代码和本地代码是一一对应的。因而,本地代码也可以反过来转换成汇编语言编写的代码。把本地代码转换为汇编代码的这一过程称为反汇编,执行反汇编的程序称为反汇编程序。
哪怕是 C 语言编写的源代码,编译后也会转换成特定 CPU 用的本地代码。而将其反汇编的话,就可以得到汇编语言的源代码,并对其内容进行调查。不过,本地代码变成 C 语言源代码的反编译,要比本地代码转换成汇编代码的反汇编要困难,这是因为,C 语言代码和本地代码不是一一对应的关系。
通过编译器输出汇编语言的源代码
我们上面提到本地代码可以经过反汇编转换成为汇编代码,但是只有这一种转换方式吗?显然不是,C 语言编写的源代码也能够通过编译器编译称为汇编代码,下面就来尝试一下。
首先需要先做一些准备,需要先下载 Borland C++ 5.5 编译器,为了方便,我这边直接下载好了读者直接从我的百度网盘提取即可 (链接:https://pan.baidu.com/s/19LqVICpn5GcV88thD2AnlA 密码:hz1u)
下载完毕,需要进行配置,下面是配置说明 (https://wenku.baidu.com/view/22e2f418650e52ea551898ad.html),教程很完整跟着配置就可以,下面开始我们的编译过程
首先用 Windows 记事本等文本编辑器编写如下代码
// 返回两个参数值之和的函数int AddNum(int a,int b){ return a + b;}// 调用 AddNum 函数的函数void MyFunc(){ int c; c = AddNum(123,456);} 编写完成后将其文件名保存为 Sample4.c ,C 语言源文件的扩展名,通常用.c 来表示,上面程序是提供两个输入参数并返回它们之和。
在 Windows 操作系统下打开 命令提示符,切换到保存 Sample4.c 的文件夹下,然后在命令提示符中输入
bcc32 -c -S Sample4.
文章目录 1. 定义2. 示例2.1 源码分析2.1.1 聚合算子回撤2.1.2 Sink算子回撤2.1.3 聚合算子回撤 VS Sink算子回撤 1. 定义 Flink中,Kafka Source是非回撤流,Group By是回撤流。所谓回撤流,就是可以更新历史数据的流,更新历史数据并不是将发往下游的历史数据进行更改,要知道,已经发往下游的消息是追不回来的。更新历史数据的含义是,在得知某个Key(接在Key BY / Group By后的字段)对应数据已经存在的情况下,如果该Key对应的数据再次到来,会生成一条delete消息和一条新的insert消息发往下游。
2. 示例 public class RetractDemo { public static void main(String[] args) throws Exception { // set up execution environment StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // use blink planner in streaming mode EnvironmentSettings settings = EnvironmentSettings.newInstance() .inStreamingMode() .build(); StreamTableEnvironment tEnv = StreamTableEnvironment.create(env, settings); // 用fromElements模拟非回撤消息 DataStream<Tuple2<String, Integer>> dataStream = env.fromElements(new Tuple2<>("hello", 1), new Tuple2<>("
习题2 2.1 考虑下面的 3 × 4 3\times4 3×4矩阵 [ 1 2 3 4 5 6 7 8 9 10 11 12 ] \begin {bmatrix} 1 & 2 &3&4 \\ 5 & 6 &7&8\\ 9&10&11&12 \end{bmatrix} \quad ⎣⎡159261037114812⎦⎤
(1)使用array函数在Python中构建该矩阵
A = np.array(((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))) (2)使用arange函数构造该矩阵
A = np.arange(1, 13).reshape(3, 4) (3)表达式A[2,:]的结果是什么?类似的表达式A[2:]的结果是什么?
[ 9 10 11 12] [[ 9 10 11 12]] 2.
1
在Python中,要知道一个字符串有多少个字符(以获得字符串的长度),或者一个字符串需要多少字节,可以使用len函数。len函数的基本语法格式如下:
2
其中string用于指定要计算长度的字符串。例如,定义一个内容字符串“http://c.biancheng.net“然后使用len()函数计算字符串的长度。执行代码如下:
3
在实际开发中,除了获取字符串的长度外,有时还需要获取字符串的字节数。在Python中,不同的字符占用不同的字节数。数字、英文字母、小数点、下划线和空格各占一个字节。一个汉字可以占用2-4个字节。具体数字取决于所采用的编码方法。例如,汉字在GBK/GB2312编码中占2个字节,在UTF-8编码中占3个字节。以UTF-8编码为例,字符串“life is short,I use Python”占用的字节数如图所示。
4
我们可以使用encode()方法对字符串进行编码,然后获取其字节号。例如,使用UTF-8编码方式计算“生命短暂,我使用Python”的字节数,可以执行以下代码:
5
因为有7个汉字加上中文标点符号,占21个字节,而英文字母和英文标点符号占6个字节,共占27个字节。同样,如果要获取GBK编码字符串的长度,可以执行以下代码:
END
sass和less地出现大大的提升了代码的复用性,按常理来说它们也是css,被称为CSS扩展语言(简称强化版的css),理论来说sass也需要编译成为css才能在浏览器上面运行的。那么为什么会出现sass和less呢?开发者应该选择哪一个预处理语言来开发呢?
编译语言让开发变得更加高效
众所周知,css的诞生就是为了作为网站的样式所用(你可以试试把一些网站的css去掉,就能看到网站的用户体验感基本为0),其实原理都差不多,saas和less无非就是在css上面加入了变量等,它能让你的前端开发工作更加的轻松。
为什么要选择saas和less预处理语言?
css面临的下面的几个问题:
语法不够强大,比如无法嵌套书写,导致模块化开发中需要书写很多重复的选择器; 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。 saas和less之间的区别
一:编译方式不同:less和sass都是css的拓展语言,最主要的区别是less是通过Javascript编译,而sass是通过ruby编译的,如果没有引入前端工程化,less会消耗客户端性能,sass会消耗服务端性能,但是引入前端工程化的话,gunt,gulp,webpack等,less和sass在打包阶段都会转化成css,所以不会有区别,只是sass是基于ruby,所以每次npm的时候相对慢一点点。
二:定义变量时候不同:less的定义变量是用@,而sass则用跟php一样的定义方式$。
三:混合模式的不同:Less中使用混合时,只需在classB中根据classA的命名来是用;Sass中首先在定义混合时需要使用@mixin命令,其次在调用时需要使用@include命令来引入之前定义的混合。
四:语法使用上的不同:比如变量的作用域等。
新手建议用less,有经验的程序员用saas开发
Sass有很多可用的方法和逻辑。例如:条件和循环语句。LESS也可以做到,但不是很高效且不直观。像LESS一样,Sass也内置了一些非常友好的函数,像颜色,数字,还有变量列表。
Sass用户可以使用功能强大的Compass库。这些库LESS用户也可以用,但并不完全一样,因为这是由一个庞大的社区来共同维护的。Compass有非常强大的特性,像自动生成图片切片(CSS Sprites),传统浏览器支持,还有对CSS3的跨浏览器支持等。
Compass同样允许你使用外部框架像Blueprint, Foundation 或 Bootstrap。这也意味着你可以非常容易地使用你喜欢的框架而不需要掌握各种不同的工具。
预处理语言也不是万能的,因为css是直接写完可以在浏览器可以解析的,但是例如saas就需要编译完之后才能运行的,如果并非大型的网站项目开发的话,我觉得没必要用saas等预处理语言。
springboot开启事务很简单,只需要一个注解@Transactional 就可以了。因为在springboot中已经默认对jpa、jdbc、mybatis开启了事事务,引入它们依赖的时候,事物就默认开启。当然,如果你需要用其他的orm,比如beatlsql,就需要自己配置相关的事物管理器。
准备阶段
以上一篇文章的代码为例子,即springboot整合mybatis,上一篇文章是基于注解来实现mybatis的数据访问层,这篇文章基于xml的来实现,并开启声明式事务。
环境依赖
在pom文件中引入mybatis启动依赖:
org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.0 引入mysql 依赖
初始化数据库脚本
配置数据源
通过配置mybatis.mapper-locations来指明mapper的xml文件存放位置,我是放在resources/mybatis文件下的。mybatis.type-aliases-package来指明和数据库映射的实体的所在包。
经过以上步骤,springboot就可以通过mybatis访问数据库来。
创建实体类
数据访问dao 层
接口:
public interface AccountMapper2 { int update( @Param("money") double money, @Param("id") int id);} mapper:
service层
@Transactional,声明事务,并设计一个转账方法,用户1减10块,用户2加10块。在用户1减10 ,之后,抛出异常,即用户2加10块钱不能执行,当加注解@Transactional之后,两个人的钱都没有增减。当不加@Transactional,用户1减了10,用户2没有增加,即没有操作用户2 的数据。可见@Transactional注解开启了事物。
结语
springboot 开启事物很简单,只需要加一行注解就可以了,前提你用的是jdbctemplate, jpa, mybatis,这种常见的orm。
在《 C语言的三套标准:C89、C99和C11 》一节中我们讲到,目前经常使用的C语言有三个版本,分别是 C89、C99 和 C11。C89(也称 ANSI C)是较早的版本,也是最经典的版本,国内大学几乎都是以该版本为基础进行授课。C99 和 C11 是后来对 C89 的升级,增添了一些新内容(不多),语法更加灵活了,同时兼容 C89。各种编译器都能很好地支持 C89 标准,但对 C99 的支持却不同:开源组织的 GCC 和 Xcode 使用的 LLVM/Clang 已经支持了大部分(几乎全部)的 C99 标准,而微软的 VC、VS 对 C99 却不感兴趣,直到后来的 VS2013、VS2015、VS2017 才慢慢支持,而且支持得还不好。为什么要讨论这个问题呢?因为 C89 和 C99 对数组做出了不同的规定: 在 C89 中,必须使用常量表达式指明数组长度;也就是说,数组长度中不能包含变量,不管该变量有没有初始化。而在 C99 中,可以使用变量指明数组长度。 下面的代码使用常量表达式指明数组长度,在任何编译器下都能编译通过: int a[10]; //长度为10int b[3*5]; //长度为15int c[4+8]; //长度为12 下面的代码使用变量指明数组长度,在 GCC 和 Xcode 下能够编译通过,而在 VC 和 VS(包括 VC 6.0、VS2010、VS2013、VS2015、VS2017 等)下都会报错: int m = 10, n;scanf("%d", &n);int a[m], b[n]; 在实际编程中,有时数组的长度不能提前确定,如果这个变化范围小,那么使用常量表达式定义一个足够大的数组就可以,如果这个变化范围很大,就可能会浪费内存,这时就可以使用变长数组。请看下面的代码: #include int main(){ int n; printf("
时隔多年,居然又要在Linux下编译OpenCV,然而这次居然折腾了一晚上,没想到会出现那么多问题。索性写个文章记录一下,防止下一次又碰壁。
我是在虚拟机上跑的ubuntu18.04。
配置如下: 第一步 :下载依赖文件,这一步非常重要,如果是缺少某个依赖文件,编译过程也不会出错,但是在使用opencv函数的时候就是提示错误,只能删了重新编译,非常的坑。 所以一定要先下载依赖文件。 所以一定要先下载依赖文件。 所以一定要先下载依赖文件。 通过以下命令来安装依赖文件。
sudo apt-get install build-essential sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev liblapacke-dev sudo apt-get install libxvidcore-dev libx264-dev sudo apt-get install libatlas-base-dev gfortran sudo apt-get install ffmpeg 第二步:从GitHub下载opencv和opencv_contrib源码,如果你是刚刚安装Linux,那么最好就是修改源,不然下载会非常非常慢。具体操作请移步百度: 如何修改Linux源。 我这里用的都是4.2.0的版本。
OpenCV和contirb的源码下载路径:
https://github.com/opencv/opencv/releasesgithub.com https://github.com/opencv/opencv_contrib/releasesgithub.com 然而在下载过程中可能会出现下载不完全的情况(起码我是这样的),往往出现的问题是缺少boostdesc_bgm.i等问题。所以我们需要提前下载好这些文件,以防不时之需。文件我已经集合在了我的GitHub里面。 GitHub地址(欢迎大佬给小星星):
https://github.com/omega-Lee/OpenCV-boostdesc-vgg-github.com 下载完以后应该是这样子的:
第三步:通过命令解压opencv和opencv_contirb: tar -zxvf opencv-4.
LaTex安装 已经使用一段时间texlive2020了,结果小伙伴增加了一个longtable之后编译器死活不通过,也找不到原因(现在中文版的问题解答实在是太少了),愤怒之下就把它给卸载了。安装了MiKTeX+WinEdt10。安装过程真的是一波三折,反复安装卸载了三四次才成功。
第一步 这里推荐大家在官网下载并安装:
MiKTex:
https://miktex.org/download
WinEdt:
http://www.winedt.com/download.html
可以把这两个.exe文件包括后面安装过程中产生的文件放在同一个文件夹里。
我看到有个博主说要添加路径,好像自动就添加了,不用管。
第二步 推荐官网下载的原因就是我从其他地方下载后,不会自动提示安装包,导致我使用时不停提示我少了.sty文件。
随便找一个代码运行一下
\documentclass{article} \begin{document} Hello, world! \end{document} 正常情况下应该是编译直接可以通过的。
上面两个步骤完成后我还遇到MiKTeX Console没有更新的问题,搜索后都说要从开始那打开MiKTeX Console然后更新,我每次打开MiKTeX Console都弹出它在运行,根本打不开,任务管理器上又没有显示,就很迷惑。
于是我又反复卸载了这两个程序之后再安装,终于可以编译成功了。
现在安装好像更简便了,下载安装包直接无脑点击下一步什么的即可。
SumatraPDF安装 如果想更方便使用可以安装 SumatraPDF阅读器,甩个链接
https://www.sumatrapdfreader.org/free-pdf-reader
安装完成后需要和winedt建立连接,点击Options
选择第二个Execution Modes,修改成SumatraPDF的路径即可。
latex使用问题 1: 问题:Undefined control sequence. \lstset
解决办法:最近使用另一台电脑,重新安装miktex,出现上述问题,是版本不一致造成的。最新版本是basic-miktex-21.2-x64,报错。之前版本是basic-miktex-20.11-x64,可用。
我发现把安装过程写出来之后下次安装就很方便了哈哈哈
一、MyBatis依赖和约束 1.1 MyBatis依赖 要使用 MyBatis,只需将mybatis-x.x.x.jar jar包引入即可,或者使用Maven来构建项目 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> //版本号根据实际情况自己定义 1.2 Mybatis XML约束文件 <!-- config约束 --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- Mapper约束 --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 约束文件附件:📎mybatis-3-mapper.dtd📎mybatis-3-config.dtd 二、MyBatis的主配置文件 2.1 环境的配置 MyBatis 可以配置多种环境,例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。如果你想连接多个数据库,就需要创建多个 SqlSessionFactory 实例,每个数据库对应一个。
每个数据库对应一个 SqlSessionFactory 实例 为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。如果忽略了环境参数,那么默认环境将会被加载。默认的环境和环境 ID 是自解释的,你可以对环境随意命名,但一定要保证默认的环境 ID 要匹配其中一个环境 ID。可以接受环境配置的两个方法签名是:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().
MQTT简介
MQTT定义
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和制动器(比如通过Twitter让房屋联网)的通信协议。
MQTT特点
MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:
1.使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合;
2.对负载内容屏蔽的消息传输;
3.使用 TCP/IP 提供网络连接;
4.有三种消息发布服务质量:
“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。“至少一次”,确保消息到达,但消息重复可能会发生。“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。 5.小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;
6.使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制;
MQTT特征原理
image
实现MQTT协议需要:客户端和服务器端
MQTT协议有三种身份:发布者(Pushlish)、代理(Broker)、订阅者(Subscribe)
MQTT的消息分为:主题(Topic)和负载(payload)两部分
Topic,可以理解为消息的类型,订阅者Subscribe之后,就会收到该主题的消息内容(payload)。
payload,可以理解为消息的内容,是指订阅者具体的使用内容
消息类型:
CONNECT:客户端连接到MQTT代理CONNACK:连接确认PUBLISH:新发布消息PUBACK:新发布消息确认,是QoS 1给PUBLISH消息的回复PUBREC:QoS 2消息流的第一部分,表示消息发布已记录PUBREL:QoS 2消息流的第二部分,表示消息发布已释放PUBCOMP:QoS 2消息流的第三部分,表示消息发布完成SUBSCRIBE:客户端订阅某个主题SUBACK:对于SUBSCRIBE消息的确认UNSUBSCRIBE:客户端终止订阅的消息UNSUBACK:对于UNSUBSCRIBE消息的确认PINGREQ:心跳PINGRESP:确认心跳DISCONNECT:客户端终止连接前优雅地通知MQTT代理 MQTT应用
通过MQTT协议,目前已经扩展出了数十个MQTT服务器端程序,可以通过PHP,JAVA,Python,C,C#等系统语言来向MQTT发送相关消息。
此外,国内很多企业都广泛使用MQTT作为Android手机客户端与服务器端推送消息的协议。其中Sohu,Cmstop手机客户端中均有使用到MQTT作为消息推送消息。据Cmstop主要负责消息推送的高级研发工程师李文凯称,随着移动互联网的发展,MQTT由于开放源代码,耗电量小等特点,将会在移动消息推送领域会有更多的贡献,在物联网领域,传感器与服务器的通信,信息的收集,MQTT都可以作为考虑的方案之一。在未来MQTT会进入到我们生活的各各方面。
百度物接入loT及MQTT测试
配置
1.注册百度云账号,打开物接入界面:
image
2.在管理控制平台创建:
image
image
3.点击刚才创建的实例名称,并创建设备:
image
image
4.填写身份、策略、主题等信息
需要注意的是Topic和生成的密钥一定要记住,如果密钥丢了的话只能去重置密钥了。
image
image
基本配置就是这些了。
MQTT连接测试
1.点击连接测试:
image
2.填写刚才生成密钥,以及用户名称,然后点击Connect
image
3.连接之后开始测试,填写一下你刚才设置的主题,比如我设置的主题是qzsservice,步骤如下:
image
image
image
发送后底下就会显示Messages信息了,说明测试成功!
百度物接入服务器与手机连接测试
上面我们已经讲完了百度物接入怎么创建实例+连接测试了,下面讲一下连接测试发送消息怎么与手机程序相连。也就是服务器发送一条消息,手机程序接收。:
VisualStudio2019安装完成之后,如果后续还有继续安装其他模块或组件时,可以通过以下步骤添加。
点击工具,选择获取工具和功能,进行选择安装。
然后在选择自己要安装的模块。
目标网站 https://movie.douban.com/explore#!type=movie&tag=%E8%B1%86%E7%93%A3%E9%AB%98%E5%88%86&sort=rank&page_limit=20&page_start=0
(豆瓣电影——选电影——豆瓣高分——按评价排序)
爬虫基本思路 1.首先发送请求并返回requests(最好模拟谷歌浏览器的头部访问(即下面的headers),并且设置一个每次访问的间隔时间,这样就不容易触发网站的反爬机制(说白了就是模拟人类的访问行为))
2.获得requests对象后使用BeautifulSoup (美丽的汤??也不知道为啥要起这个名)来解析requests对象,注意这里要用request.text,就取文本,解析后的soup打印出来其实就是整个html的字符串内容,但是类型并不是string,应该是bs4类型,这就是这个美丽的汤的魅力所在,它可以直接在python用类似于ccs选择器那样的方式一层一层的寻找我们要的div内容。
3.搜寻soup对象中我们需要的内容,就是一层一层div找到对应的属性,然后拿取我们需要的内容。(看html或者把之前的soup对象打印出来)
4.打印或保存文件
在分析过网页之后发现传统的从html中拿前三部电影不太方便,对于json更建议从xhr中的preview获取,这样一看就一目了然了。
至于如何获取xhr中preview的内容,可以用如下方式:
首先看header里的url:
res = requests.get(url, headers=headers,timeout=20) (假设这里我们已经获得了request对象)
首先把res转化为json对象:
js = res.json() #这样才能用键值对的方式访问到我们要的名称和url
全部代码: import requests from bs4 import BeautifulSoup import json headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'} #从xhr中获取链接 url = 'https://movie.douban.com/j/search_subjects?type=movie&tag=%E8%B1%86%E7%93%A3%E9%AB%98%E5%88%86&sort=rank&page_limit=20&page_start=0' res = requests.get(url, headers=headers,timeout=20) #print(res.status_code) js = res.json() #转化成json才能用键值对访问 response对象不能 def topCinema(num): #获取评分排名前n部电影的名称和链接 top_info = js['subjects'][:num] top_cinema = {} for i in range(num): top_cinema[top_info[i]['title']] = top_info[i]['url'] return top_cinema #print(topCinema(4)) def getComment(movieUrl,pageNum): #爬取某个电影的第i页影评 start = (pageNum-1) * 20 headers = {'User-Agent': 'Mozilla/5.
/**map.js*/ //引入地图 export function MapLoader() { const mp = new Promise(function (resolve, reject) { if (window.AMap) { resolve(window.AMap) } else { var url = 'https://webapi.amap.com/maps?v=1.4.15&key=youkey&callback=onLoad&plugin=AMap.DistrictSearch' var script = document.createElement('script') script.src = url script.id = "amap"; script.onerror = reject document.head.appendChild(script) } window.onLoad = () => { resolve(window.AMap) } }); //引入地图UI库 const mpUI = new Promise(function (resolve, reject) { if (window.AMapUI) { resolve(window.AMapUI) } else { var url = 'https://webapi.amap.com/ui/1.0/main.js' var script = document.
1.市场分析---用户行为,定义第二次 Users table: +---------+------------+----------------+ | user_id | join_date | favorite_brand | +---------+------------+----------------+ | 1 | 2019-01-01 | Lenovo | | 2 | 2019-02-09 | Samsung | | 3 | 2019-01-19 | LG | | 4 | 2019-05-21 | HP | +---------+------------+----------------+ Orders table: +----------+------------+---------+----------+-----------+ | order_id | order_date | item_id | buyer_id | seller_id | +----------+------------+---------+----------+-----------+ | 1 | 2019-08-01 | 4 | 1 | 2 | | 2 | 2019-08-02 | 2 | 1 | 3 | | 3 | 2019-08-03 | 3 | 2 | 3 | | 4 | 2019-08-04 | 1 | 4 | 2 | | 5 | 2019-08-04 | 1 | 3 | 4 | | 6 | 2019-08-05 | 2 | 2 | 4 | +----------+------------+---------+----------+-----------+ Items table: +---------+------------+ | item_id | item_brand | +---------+------------+ | 1 | Samsung | | 2 | Lenovo | | 3 | LG | | 4 | HP | +---------+------------+ 写一个 SQL 查询确定每一个用户按日期顺序卖出的第二件商品的品牌是否是他们最喜爱的品牌。如果一个用户卖出少于两件商品,查询的结果是 no 。题目保证没有一个用户在一天中卖出超过一件商品
项目中使用LocalDateTime系列作为DTO中时间的数据类型,但是SpringMVC收到参数后总报错,为了配置全局时间类型转换,尝试了如下处理方式。注:本文基于Springboot2.x测试,如果无法生效可能是spring版本较低导致的。PS:如果你的Controller中的LocalDate类型的参数啥注解(RequestParam、PathVariable等)都没加,也是会出错的,因为默认情况下,解析这种参数是使用ModelAttributeMethodProcessor进行处理,而这个处理器要通过反射实例化一个对象出来,然后再对对象中的各个参数进行convert,但是LocalDate类没有构造函数,无法反射实例化因此会报错!!!
完成目标 请求入参为 String(指定格式)转 Date,支持get、post(content-type=application/json)返回数据为Date类型转为指定的日期时间格式字符串支持Java8 日期 API,如:LocalTime、localDate 和 LocalDateTime GET请求及POST表单日期时间字符串格式转换 这种情况要和时间作为Json字符串时区别对待,因为前端json转后端pojo底层使用的是Json序列化Jackson工具(HttpMessgeConverter);而时间字符串作为普通请求参数传入时,转换用的是Converter,两者在处理方式上是有区别。
使用自定义参数转换器(Converter) 实现 org.springframework.core.convert.converter.Converter,自定义参数转换器,如下:
@Configurationpublic class DateConverterConfig { @Bean public Converter localDateConverter() { return new Converter() { @Override public LocalDate convert(String source) { return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd")); } }; } @Bean public Converter localDateTimeConverter() { return new Converter() { @Override public LocalDateTime convert(String source) { return LocalDateTime.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } }; }} 点评:以上两个bean会注入到spring mvc的参数解析器(好像叫做ParameterConversionService),当传入的字符串要转为LocalDateTime类时,spring会调用该Converter对这个入参进行转换。
注意:关于自定义的参数转换器 Converter,这里我遇到了一个坑,我在这里详细记录下,本来我的想法是为了代码精简,将上面匿名内部类的写法精简成lambda表达式的方式:
@Bean@ConditionalOnBean(name = "requestMappingHandlerAdapter")public Converter localDateConverter() { return source -> LocalDate.
oc与iloc函数
loc函数
import pandas as pd
import numpy
# 导入数据
df = pd.read_csv(filepath_or_buffer="D://movie.csv")
df_new = df.set_index(["country"])
df_new.loc[list(["Canada"])] # 1
df_new.loc[df_new["duration"]>160] # 2
df_new.loc[((df_new["duration"] > 200) & (df_new["director_facebook_likes"] > 300 )),"flage"] =1 # 3
df_new.loc[df_new["duration"].isin([100])] # 4
df_new.query("duration > 100 & index == 'UK'") # 5
1:根据列中的元素,选取对应元素的数据集
2:根据元素的选取条件来选取对应的数据集
3:根据元素的选取条件来来选取对应的数据集,并在符合条件的数据行添加flage标签
4:isin函数是series用来判断值是否在目标值是否在series
5:query函数中用来判断条件符合的数据集并返回
iloc函数
df_new.iloc[0:4]
iloc比较简单,它是基于索引位来选取数据集,0:4就是选取 0,1,2,3这四行,需要注意的是这里是前闭后开集合
使用标签选取数据:
df.loc[行标签,列标签]
df.loc['a':'b']#选取ab两行数据
df.loc[:,'one']#选取one列的数据
df.loc的第一个参数是行标签,第二个参数为列标签(可选参数,默认为所有列标签),两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回的是DataFrame,否则,则为Series。
本篇文章主要讲述ES5中的数组,包括数组两种创建方式,属性,以及 9 大类 ,总共23个操作方法,非常全面,看完之后ES5数组这一部分基本都了解了,下一篇文章,我会讲述ES6中对数组的加成,新增了哪些方法,以及定型数组,类数组和类数组的所有方法,记得关注哦!
数组作为javascript中最常用的数据类型之一,掌握好数组的方法在日常的开发中是非常有必要的,javascript中的数组相比其他语言来说更灵活,因为数组的每一项都可以是不同的数据类型,可以是对象,数组,字符串,数值等等,接下来一点一点的了解吧!
1.数组的创建 说到数组首先肯定是创建,只有创建或者声明一个变量是数组之后才可以使用它,以及他的一些属性和方法。数组的创建有两种方式,即,构造函数式和数组字面量式。
第一种构造函数式创建,利用new Array来创建,下面先上一段例子:
1 分析一下,第一行创建了一个空数组;第二行创建了一个长度为3的空数组,注意这个3是数组的长度为3,不是数组的第一项是数值3,切记!在下一篇讲到的类数组方法Array.of()方法就可以创建数值3;第三个是创建了一个字符串数组,里面只有一个值;第四行,第五行都目前chrome浏览器无法编译通过,写法有问题,特意列出来注意一下。 在使用Array 的时候new也可以省略,其效果也是一样的。
第二种是数组字面量创建数组,即直接用[]。
1 再分析一下,第一行也是创建了一个空数组;第二行创建了一个长度为2的数组,数组中包含12,34,在有的浏览器中长度为3,注意一下。第三行创建了一个长度为4的空数组,数组的每一项值是undefined,有的浏览器也可能数组的长度是5。第四行创建了一项含有字符串的数组;第五行创建一个全是数值的数组,最后一行创建了一个长度为4的数组,每一项都是不同的数据类型。
注意: 1. var arr = new Array(,,,,);是报错的,而var arr = [,,,,];是可以创建数组的;以及var arr = new Array(12,34,)也是报错的,而var arr = [12,34,]是可以的,这些注意不要搞混淆了,日常工作中都不推荐此种方法创建数组; 2. 虽然两种方法都可以创建数组,但是数组字面量要比构造函数的性能好,原因是:json格式的语法浏览器引擎能直接解析,而new Array需要调用Array的构造器。日常工作中可以使用前者,方便快速省性能。
2. length属性 大家都知道length属性表示数组的长度为多少,现在用构造函数式和数组字面量式创建一个长度为10的空数组,试试看:
1 现在用数组的length属性来操作数组的长度,不用arr.pop()和arr.shift()方法怎么来搞呢?
1 分析一下:首先arr1 是一个长度为10的数组,当把数组的长度成为8的时候,此时会从数组的第一个元素开始向后截取8个作为数组的新值,此操作会改变数组。 arr2是一个长度为2的数组,将数组的长度设为100后,将依次为数组的剩余97项设置值为undefined,当再改变某一项的元素的时候就是正常的赋值了,最后一个给数组添加一项,当前数组的最后一项的索引是length-1,当arr.length就是添加一项。
3.数组的检测 数组作为引用类型之一,检测方法有两种:instanceof和isArray。其中instanceof适用于在一个网页或者一个全局作用域的情况比较实用,随着前端框架越来越多,在项目 中引入太多的框架的时候,每个框架对数组可能进行过二次封装,这样导致一个问题就是instanceof 返回的结果可能会不同,使用时得注意,基本用法如下:
1 基于以上的问题,ES5又新增了新的检测方法,isArray 来确定某个值到底是不是数组,而不用管其他的作用域问题。写法如下:
1 4.类栈操作相关 数据结构栈的特点就是后进先出(LIFO, last-in-first-out) ,比喻成容器罐好理解点,最后放的在上面,拿的时候也先从上面拿,操作推入和弹出,都发生在栈的顶部,javascript数组中有专门的方法push()和pop()来模拟栈的操作。
push()方法,接受不限制个数的参数,在数组的末尾插入元素,返回值是修改后的数组的长度,此方法会改变原数组;
pop()方法,不接受参数,从数组的末尾来删除最后一个元素,返回值是删除的元素,此方法也会改变原数组。下面我们来看看具体用法:
1 5.类队列操作相关 上面聊完了栈,现在来看看队列,相信这两个词大家都不陌生,队列的特点是:先进先出(FIFO , first-in-first-out),看做是一个空的管道比较好理解,从一端进入,另一端出去。javscript数组提供了shift()和push()方法来模拟队列的特点。
shift() , 从数组的头部删除一个元素,返回值是删除的元素,此方法会改变原数组,看看使用情况:
1 跟shift()方法结果刚好相反的是unshift()方法,shift()是从数组头部删除元素,而unshift()刚好是从头部添加元素,接受不限个数的参数,返回值是改变后的数组的长度,此方法会改变数组,其实,这个方法效果跟push()一样,只不过一个在数组前面插入,一个在后面插入,看看效果:
NTFS (New Technology File System)是 Windows NT 操作环境和 Windows NT 高级服务器网络操作系统环境的文件系统。
NTFS的优点:
1.具备错误预警的文件系统。
2.文件读取速度更高效。
3.磁盘自我修复功能。
4.“防灾赈灾”的事件日志功能。
5.ntfs动态磁盘功能。
6.能解决大文件传输电脑不支持问题
FAT32 到 NTFS
例如,将D盘转换为NTFS格式,则需命令 convert d:/fs:ntfs。
问题:eclipse 加载android工程,报错Type The type org.apache.http.Header
解决:将android SDK 下面的jar包放在对应工程的lib下解决问题
路径:android-sdk-windows\platforms\android-23\optional\ 里的org.apache.http.legacy.jar 包
ShapeGeometry几何体介绍和使用 1.ShapeGeometry几何体介绍2.demo说明3.demo代码 1.ShapeGeometry几何体介绍 ShapeGeometry可以用来创建自定义的二维图形,实际上ShapeGeometry创建图形必须要用到基类Shape,我们先来看看它的原型链:
没错,Shape类继承自Path类,Path类由继承自CurvePath类,我们用来画图的方法实际都是从CurvePath继承来的,现在我们介绍一下这些方法:
函数名描述moveTo(x,y)将函数绘图点移动到指定的坐标lineTo(x,y)从moveTo指定的位置开始画一条线到(x,y)指定的坐标quadricCurveTo(aCPx,aCPy,x,y)(二次曲线)你可以用两种方法来定义曲线,用quadricCurveTo或bezierCurveTo函数,这两种方法的不同是一个通过一个点控制曲线的曲率,一个用两个点,下图是二者的示意图对于二次曲线,需要额外指定一个点(使用aCPx和aCPy参数),还需要指定端点(x和y)。对于三次曲线需要用bezierCurveTo函数绘制,需要多指定两个点才能绘制, 起点都是路径的当前点bezierCurveTo(aCPx1,aCPy1,aCPx2,aCPy2,x,y)根据提供的参数画一条曲线,相关说明参考前一行内容,该曲线绘制需要四个点:起点是路径的当前点,连个点用来控制曲率,最后一个点是端点splineThru(pts)该函数沿着提供的坐标集合绘制一条光滑的曲线,这个参数是一个THREE.Vector2对象数组,起点是路径的当前位置arc(ax,ay,aRadius,aStartAngle,aEndAngle,aClockwise)画圆(或者一段弧),起始于路径的当前位置,ax和ay用来指定圆心与当前位置的偏移量,aRadius设置圆的大小,aStartAngle和aEndAngle用来定义弧的长度,布尔属性aClockwise决定这段弧是顺时针还是逆时针absArc(ax,ay,aRadius,aStartAngle,aEndAngle,aClockwise)参考arc的描述,该方法绘制的弧是绝对位置,而不是相对位置ellipse(ax,ay,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise)画椭圆参考arc的描述,可以通过xRadius指定x轴半径,通过yRadius指定y轴半径absEllipse(ax,ay,xRadius,yRadius,aStartAngle,aEndAngle,aClockwise)参考ellipse的描述,该方法绘制的椭圆是绝对位置,而不是相对位置 继续往下看:
CurvePath继承自Curve类,Curve类又继承自Object类,果然一切皆对象啊,随后我们要介绍一下继承自Curve类的getPoints和getSpacedPoints方法
函数名描述getPoints(n)从路径的每一个部分返回n个点getSpacedPoints(n)从整个路径返回n个点 2.demo说明 该示例可以通过drawType属性切换不同的绘图方式,绘出上面三种不同的图形,
3.demo代码 <template> <div> <div id="container"></div> <div class="controls-box"> <section> <el-row> <el-col :span="8" class="label-col"><label>drawType</label></el-col> <el-col :span="16"> <el-select v-model="drawType" placeholder="请选择"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-col> </el-row> </section> </div> </div> </template> <script> import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import { SceneUtils } from 'three/examples/jsm/utils/SceneUtils.js' export default { data() { return { options: [ { value: 'asGeom', label: 'asGeom' }, { value: 'asPoints', label: 'asPoints' }, { value: 'asSpacedPoints', label: 'asSpacedPoints' } ], drawType: 'asGeom', activeShapeMesh: null, camera: null, scene: null, renderer: null, controls: null } }, mounted() { this.
文章来源:知了堂冯老师原创
1.回顾 ARP协议
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址,说白了就是将IP地址转化为MAC地址。
2.ARP缓存 如果每个发送IP Packet都要执行一次 ARP, 网络将是不可承受的
ARP缓存机制 Static: arp -s Dynamic: 根据ARP应答更新 ARP应答并非都是由请求触发的 主机启动时会主动发送ARP应答 刷新邻居的ARP缓存
3.ARP协议安全问题 ARP协议在设计存在着什么安全问题? ARP广播请求/应答 ARP缓存
ARP欺骗 (ARP Spoofing) 发送伪造ARP消息,对特定IP所对应的MAC地址进行假冒欺骗,从而达到恶意目的。
4.ARP攻击原理 PC1和PC2正常通信的时候,会双方会记录对方的IP和MAC地址的映射,就是生成ARP缓存表,当PC1信息发送至交换机端口1的时候再转发到PC2,交换机同样会记录MAC1,生成一条MAC1和端口1的映射,之后交换机可以跟MAC桢的目的MAC进行端口转发。
如果现在有一台PC3,当PC1和PC2建立关系的时候,PC3处于监听状态,也就是会把广播包给丢弃,但PC3同样也可以把包抓起,并回复虚假包,告诉PC1,我是PC2,那么PC1就收到了两条PC2的回应包(一个真的,一个假的),PC1不知道谁是真谁是假,所以PC3就可以连续发包,覆盖掉真正的PC2的包,与PC1建立联系,进行ARP欺骗
5.欺骗实战 5.1断网攻击 实验准备
攻击机:kali ip:192.168.2.135
靶机 :win10 ip:192.168.2.196 网关:192.168.2.1
攻击机发起攻击 arpspoof命令 -i(interface) 网卡eth0 -t(target) 目标IP:192.168.2.196 目标主机网关192.168.2.1
5.2 流量截获 实验准备
攻击机:kali ip:192.168.2.135
靶机 :win10 ip:192.168.2.196 网关:192.168.2.1
攻击机发起攻击
arpspoof命令 -i(interface) 网卡eth0 -t(target) 目标IP:192.168.2.196 目标主机网关192.168.2.1 arpspoof命令 -i(interface) 网卡eth0 -t(target) 目标IP:192.168.2.1 目标主机网关192.168.2.196
首先目前几个rc版本可能表现是不一致的。比如rc5就很容易有问题。我目前使用rc1.感觉这个问题少一些。值得注意的是,如果使用Npm安装的话,要么锁版本,要么指定明确的版本。即:
// 使用--sav-exact 锁定版本 npm install html2canvas@1.0.0-rc1 --save-exact // 或者文件目录中包含了package-lock.json + src + package.json + package-lock.json + .... 空白的问题或者错位的问题。与需要生成Html所在可视区可能有关系。我这里发现如果html结构正好在可视区内外各显示一部分,那么有可能出现错位或者空白。我这里解决方案是使用固定定位,定位到可视区之外。比如:
.canvas-html { position: fixed; top:0; left:-200%; } 然后设置
{ // offset, 可尝试调整一下对应的参数 x: 0 } 最后关于跨域的问题,首先本地图片,同域的图片是没问题的。其次对于与当前域名不同的图片,如果图片所在服务器或者CDN不支持跨域,那是不可能绘的出来的,也就别费力气了。所以先和相关人协商让他们支持跨域。其次配置html2canvas的参数如下
{ useCORS: true } 值得注意的,如果本身是同域,也就是不涉及跨域,就别加这个属性。否则如果图片服务器不支持跨域导致本来没问题,结果出现跨域问题。
更多参数调整,参考官方文档 http://html2canvas.hertzen.com/configuration
深入理解图卷积神经网络(GCN)原理 文章目录 深入理解图卷积神经网络(GCN)原理前言一、为什么需要GCN二、GCN的原理1.图的定义2.GCN来了2.1 矩阵计算公式2.2 以小规模矩阵讲解公式含义2.3 综上所述: 三、GCN有多牛总结 前言 深度学习的发展日新月异,从经典的深度网络(DNN、CNN、RNN)到GAN、强化学习。深度学习覆盖的应用场景越来越丰富。今天介绍的图神经网络是另一类深度学习方法。虽然,图神经网络也可以纳入深度学习的范畴,但它有着自己独特的应用场景和算法实现,对初学者并不算太友好。GCN,全称Graph Convolutional Network,图卷积网络,本文主要实现对GCN的深入理解,帮助快速理解GCN的原理以及用途。
一、为什么需要GCN 卷积神经网络(CNN)的输入是图片等具有欧几里得结构的图结构,也就是这样的图:
从欧式空间里面利用卷积核(kernel)来提取特征,因为图片是比较规则的图结构,因此使用卷积核就可以平移提取节点特征,即CNN的核心在于它的kernel,kernel是一个个小窗口,在图片上平移,通过卷积的方式来提取特征。这里的关键在于图片结构上的平移不变性:一个小窗口无论移动到图片的哪一个位置,其内部的结构都是一模一样的,因此CNN可以实现参数共享。这就是CNN的精髓所在。但是通常我们会遇到拓扑网络或者社交网络,即如下
像这种图结构,并不整齐,一个网络包含不同数量的节点,不同的节点也包含不同的邻居,这使得传统的CNN无法作用在该图结构中,并且图中的每个node之间通常具有联系,因此当GCN问世,解决了这一难题。
二、GCN的原理 1.图的定义 图结构用G=(V,E)来表示,图包括有向图或者无向图,但是在GCN中只考虑无向图,V表示node的几何,E表示edge的几何,n表示的是node的数量,m则表示边的个数。
下面我们介绍一个图结构在GCN中各种符号表示的含义:
G = ( V , E ) 表 示 当 前 图 结 构 v i ∈ V 表 示 v i 是 一 个 n o d e e i j = ( e i , e j ) ∈ E 表 示 n o d e i 与 j 之 间 的 边 N ( v ) = { u ∈ V ∣ ( v , u ) ∈ E } 表 示 点 v 的 所 有 邻 居 集 合 A i j 表 示 图 的 邻 接 矩 阵 A i j = 1 表 示 n o d e i 和 j 之 间 存 在 边 D 表 示 当 前 图 的 度 矩 阵 , D 是 对 角 矩 阵 d i i ∈ D 表 示 A 中 每 个 节 点 的 度 X ∈ R n × d 表 示 n 个 节 点 的 特 征 向 量 , 特 征 向 量 维 度 是 d G=(V,E) \qquad 表示当前图结构 \\v_i\in V\qquad表示v_i是一个node \\e_{ij}=(e_i,e_j)\in E\qquad表示node\quad i与j之间的边 \\N(v)=\{u\in V|(v,u)\in E\}\qquad表示点v的所有邻居集合 \\A_{ij}\qquad表示图的邻接矩阵 \\A_{ij}=1\qquad表示node\quad i和j之间存在边 \\D\qquad 表示当前图的度矩阵,D是对角矩阵 \\d_{ii}\in D\quad 表示A中每个节点的度 \\X\in R^{n\times d}表示n个节点的特征向量,特征向量维度是d G=(V,E)表示当前图结构vi∈V表示vi是一个nodeeij=(ei,ej)∈E表示nodei与j之间的边N(v)={u∈V∣(v,u)∈E}表示点v的所有邻居集合Aij表示图的邻接矩阵Aij=1表示nodei和j之间存在边D表示当前图的度矩阵,D是对角矩阵dii∈D表示A中每个节点的度X∈Rn×d表示n个节点的特征向量,特征向量维度是d
一、模块引脚分析
可以看到模块有四个引脚,分别是
Vcc :5V输入,网上说3.3V输入也可以,没试过。
Trig :触发信号输入
Echo :回响信号输出
Gnd:地
二、工作原理
1.给超声波模块接入电源和地。
2.给脉冲触发引脚(Trig)输入一个至少10us的高电平方波
3.输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(Echo)端的电平会由0变为1;(此时应该启动定时器计时)
4.当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;(此时应该停止定时器计数),定时器记下的这个时间即为超声波由发射到返回的总时长。
5.根据声音在空气(25℃) 中的速度346m/s,即可计算出所测的距离。距离=高电平时间*速度/2
HC-SR04的时序图如下:
一,通过AccessibilityService实现 简介
AccessibilityService其实是一个Servic,是其子类;设计AccessibilityService的初衷在于帮助残障用户使用android设备和应用,在后台运行,可以监听用户界面的一些状态转换,例如页面切换、焦点改变、通知、Toast,自动安装APP等模拟操作(你能做的他都能),辅助用户操作、发音(本意是这样的)等,并在触发AccessibilityEvents时由系统接收回调。后来被开发者另辟蹊径,用于一些插件开发,比如微信红包助手,还有一些需要监听第三方应用的插件。
1,能模拟的物理按键有 AccessibilityService.GLOBAL_ACTION_POWER_DIALOG 重启和关机 GLOBAL_ACTION_NOTIFICATIONS 下拉通知栏 GLOBAL_ACTION_QUICK_SETTINGS 打开快速设置 GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN 分屏 GLOBAL_ACTION_LOCK_SCREEN 锁屏----无效 GLOBAL_ACTION_KEYCODE_HEADSETHOOK 截屏 ---无效 GLOBAL_ACTION_BACK 返回 GLOBAL_ACTION_HOME 桌面 GLOBAL_ACTION_RECENTS 最近任务 2,具体实现 2.1,新建服务继承AccessibilityService,名字自定义比如我的:KeyService,如下是服务的所有代码:
package com.example.test; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.PixelFormat; import android.os.Build; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; public class KeyService extends AccessibilityService { private static final String TAG = KeyService.
情景 判断输入的字符串中是否存在数字判断输入的字符串是否为纯数字 解决方案 用正则匹配解决 对场景1:是否有数字 //正则判断字符串有无数字 String haveNum = ".*\\d+.*"; final Pattern pattern = Pattern.compile(haveNum); Matcher match = pattern.matcher(searchParam); JSONArray jsonArray; if (match.find()) { //do something } 对场景2:是否纯数字 //判断是否为纯数字 String pureNum = "-?[0-9]+(\\\\.[0-9]+)?"; Pattern compile = Pattern.compile(pureNum); Matcher matcher = compile.matcher("the string need to test"); if (matcher.matches()){ //do something } 注意 在使用match的时候,要注意find()和matches()的区别,前者是匹配到就返回,后者是对全字段进行检测。
使用Aspose.cells将Excel转成PDF 源文档地址 https://blog.csdn.net/dxyzhbb/article/details/90408092 下载jar包 链接:https://pan.baidu.com/s/1QbhZ-6qmG1N-n6BoF3yZTQ 提取码:npdy 添加到自己的mvn仓库 mvn install:install-file -Dfile="jar包位置" -DgroupId="groupId" -DartifactId="artifactId" -Dversion="版本" -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true 导包 <!--将excel转成pdf(自己的打包方式)--> <dependency> <groupId>com.aspose</groupId> <artifactId>aspose-cells</artifactId> <version>8.5.2</version> </dependency> 代码 @Test public void excelToPdf() throws Exception { //去除水印 String licenseXml = "<License><Data><Products><Product>Aspose.Total for Java</Product><Product>Aspose.Words for Java</Product></Products><EditionType>Enterprise</EditionType><SubscriptionExpiry>20991231</SubscriptionExpiry><LicenseExpiry>20991231</LicenseExpiry><SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber></Data><Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature></License>"; ByteArrayInputStream is = new ByteArrayInputStream(licenseXml.getBytes()); com.aspose.cells.License license = new com.aspose.cel`在这里插入代码片`ls.License(); license.setLicense(is); //创建Workbook对象 Workbook workbook = new Workbook("C:\\Users\\wucn\\Desktop\\work\\OA\\测试.xls"); //保存成pdf workbook.save("C:\\Users\\wucn\\Desktop\\work\\OA\\测试.xls.pdf", com.aspose.cells.SaveFormat.PDF); }
要说现在什么邮箱用的最频繁,个人认为是QQ邮箱,但如今我们都喜欢在手机上处理一些事情,接收和回复邮件也不例外。不过许多iPhone用户可能都遇到过,在苹果手机自带邮件内添加QQ邮箱时,总是显示用户名或密码不正确,今天就来帮大家解决这个问题。
1️⃣ 首先打开浏览器搜索QQ邮箱,点击并登陆;(手机端需要切换成网页版)
2️⃣ 进入邮箱主页,点击设置;
3️⃣ 进入设置页面后,点击账户;
4️⃣ 选择IMAP/SMTP服务,点击开启;
5️⃣ 开启后根据弹窗内容提示,进行QQ密保短信验证;
6️⃣ 验证成功后,会收到一条IMAP/SMTP服务授权码,进入iPhone自带邮件重新输入QQ邮箱账号,密码输入刚刚收到的授权码,就能成功登陆上了。
C语言中冒泡排序 分享一些关于C语言的算法,冒泡排序,这个是C语言中最常用的算法之一。主要采用的是相邻数两两进行比较的思想。如果后一个比前一个大或者小,则将其调换位置,直至所有的数都比较完。如果给定一个大小为n的数组,那么需要比较n-1趟,每一趟比较n-1-i次 ,i 表示上次循环中已经比较完的下标。写两个循环判断,如需交换则进行交换,如果不需要交换则进行下两个数的比较,直到所有的数比较完。最后,用一个循环将排序完成后的数全部输出。
代码如下:
#include <stdio.h> void bubble_sort(int arr[], int sz) { //确定冒泡排序的趟数 int i = 0; for (i = 0; i <= sz - 1; i++) { int flag = 1;//假设这一趟要排序的数据已经有序 int j = 0; for (j = 0; j <= sz - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = 0;//本趟排序的数据其实不完全有序 } } if (flag == 1) { break; } } } int main() { int arr[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz);//冒泡排序函数 for (i = 0; i < sz; i++) { printf("
1.Broker集群模式(宏观) RocketMQ天生对集群的支持非常友好,天然支持高可用,它可以支持多主多从的部署架构,这也是和kafka大区别之一(PS:Kafka的分区副本可以看成一主多从)。
那为什么要将这么多broker组织成多主多从,而不是采用一主多从然后主节点down机后再选举啊?因为。。。RocketMQ中并没有master选举功能,在RocketMQ集群中,1台机器只能要么是Master,要么是Slave,这个在初始的机器配置里面,就定死了。不会像kafka那样存在master动态选举的功能,所以通过配置多个master节点来保证rocketMQ的高可用。
其中Master的broker id = 0,Slave 的broker id > 0。 有点类似于mysql的主从概念,master挂了以后,slave仍然可以提供读服务,但是由于有多主的存在,当一个master挂了以后,可以写到其他的master上。
和所有的集群角色定位一样,master节点负责接受事务请求、slave节点只负责接收读请求,并且接收master同步过来的数据和slave保持一致。
既然说到集群模式了,那我们再来看看常见的四种集群模式:
单Master
- 优点:除了配置简单没什么优点
- 缺点:不可靠,该机器重启或宕机,将导致整个服务不可用多Master
- 优点:配置简单,性能高
- 缺点:可能会有少量消息丢失(配置相关),单台机器重启或宕机期间,该机器下未被消费的消息在机器恢复前不可订阅,影响消息实时性多Master多Slave,每个Master配一个Slave,有多对Master-Slave,集群采用异步复制方式,主备有短暂消息延迟,毫秒级
- 优点:性能同多Master几乎一样,实时性高,主备间切换对应用透明,不需人工干预
- 缺点:Master宕机或磁盘损坏时会有少量消息丢失多Master多Slave,每个Master配一个Slave,有多对Master-Slave,集群采用同步双写方式,主备都写成功,向应用返回成功
- 优点:服务可用性与数据可用性非常高
- 缺点:性能比异步集群略低,当前版本主宕备不能自动切换为主 而RocketMQ采用的就是的第三种。在多主多从架构下,由于每个master可以配置多个slave,所以如果其中一个master挂了,那么只是当前Broker不能写消息了,但Consumer仍然可以从slave节点消费到。可以完美的实现rocketmq消息的高可用。
如果当前rocketmq是一主多从,就意味着无法接受发送端的消息,但是消费者仍然能够继续消费。如果当前rocketmq是多主多从,另外一个master节点仍然能够对外提供消息发送服务。 这里特别注意一点,当存在多个主节点时,一条消息只会发送到其中一个主节点。rocketmq对于多个master节点的消息发送,会做负载均衡,使得消息可以平衡的发送到多个master节点上。 一个消费者可以同时消费多个master节点上的消息,在上面这个架构图中,两个master节点恰好可以 平均分发到两个消费者上,如果此时只有一个消费者,那么这个消费者会消费两个master节点的数据。
2.Broker队列分区(微观) 在RocketMQ中,是基于多个Message Queue来实现类似于kafka的分区效果。如果一个Topic 要发送和接收的数据量非常大, 需要能支持增加并行处理的机器来提高处理速度,这时候一个Topic 可以根据需求设置一个或多个Message Queue。
Topic 有了多个Message Queue 后,消息可以并行地向各个 Message Queue 发送,消费者也可以并行地从多个Message Queue 读取消息并消费。从而提高消费者并发处理的能力与消费者拉取消息时的负载均衡
注:RocketMQ是通过多Master实现了对Producer发送消息的负载均衡,而不是kafka那样通过分区分片存储实现Producer发消息负载均衡
我们可以直接在控制台创建队列(分区):
图中那两个参数是什么意思呢?
writeQueueNums:写队列数,表示producer发送到的MessageQueue的队列个数readQueueNums:读队列数,表示Consumer读取消息的MessageQueue队列个数 注:这两个值需要相等,在集群模式下如果不相等,writeQueueNums=6,readQueueNums=3, 那么每个broker上会有3个queue的消息是无法消费的。
上面创建一个TestTopic的主题,这个主题下有两个队列,即两个分区。
为了Producer发来的消息每个master都能写,所以每个Broker上都要有TestTopic主题而且每个Broker上的TestTopic,都要有两个分区 注:类似于kafka,分区 + Consumer group ==> 对于consumer的消息广播。
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
~通过使用另一个同类型的对象来初始化新创建的对象。
~复制对象把它作为参数传递给函数。
~复制对象,并从函数返回这个对象。
如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。
拷贝构造函数的最常见形式如下:
classname (const classname &obj)
{
// 构造函数的主体
}
在这里,obj 是一个对象引用,该对象是用于初始化另一个对象的。
#include <iostream> using namespace std; class Line { public: int getLength( void ); Line( int len ); // 简单的构造函数 Line( const Line &obj); // 拷贝构造函数 ~Line(); // 析构函数 private: int *ptr; }; // 成员函数定义,包括构造函数 Line::Line(int len) { cout << "调用构造函数" << endl; // 为指针分配内存 ptr = new int; *ptr = len; } Line::Line(const Line &obj) { cout << "
MOS管相比于三极管,开关速度快,导通电压低,电压驱动简单,所以越来越受工程师的喜欢,然而,若不当设计,哪怕是小功率MOS管,也会导致芯片烧坏,原本想着更简单的,最后变得更加复杂。这几年来一直做高频电源设计,也涉及嵌入式开发,对大小功率MOS管,都有一定的理解,所以把心中理解的经验总结一番,形成理论模型。MOS管等效电路及应用电路如下图所示:
把MOS管的微观模型叠加起来,就如下图所示:
我们知道,MOS管的输入与输出是相位相反,恰好180度,也就是等效于一个反相器,也可以理解为一个反相工作的运放,如下图:
有了以上模型,就好办了,尤其从运放这张图中,可以一眼看出,这就是一个反相积分电路,当输入电阻较大时,开关速度比较缓慢,Cgd这颗积分电容影响不明显,但是当开关速度比较高,而且VDD供电电压比较高,比如310V下,通过Cgd的电流比较大,强的积分很容易引起振荡,这个振荡叫米勒振荡。所以Cgd也叫米勒电容,而在MOS管开关导通或者关断的那段时间,也就是积分那段时间,叫米勒平台,如下图圆圈中的那部分为米勒平台,右边的是振荡严重的米勒振荡:
因为MOS管的反馈引入了电容,当这个电容足够大,并且前段信号变化快,后端供电电压高,三者结合起来,就会引起积分过充振荡,这个等价于温控的PID中的I模型,要想解决解决这个米勒振荡,在频率和电压不变的情况下,一般可以提高MOS管的驱动电阻,减缓开关的边沿速度,其次比较有效的方式是增加Cgs电容。在条件允许的情况下,可以在Cds之间并上低内阻抗冲击的小电容,或者用RC电路来做吸收电路。下图给出我常用的三颗大功率MOS管的电容值:LCR电桥直接测量。
从图上可以看出,Inifineon6代MOS管和APT7代MOS管性能远远不如碳化硅性能,它的各个指标都很小,当米勒振荡通过其他手段无法降低时,可以考虑更换更小的米勒电容MOS管,尤其需要重视Cgd要尽可能的小于Cgs。
**声明:**以上文章内容、图片由泰德兰电子网编整理于网络,如涉及到版权问题,请第一时间与我们联系。泰德兰电子是专业代理销售国内外品牌元器件公司,长期代理MOS管、IC芯片等产品。欢迎大家留言互动。
1. 从简单线性分类器到深度学习 给定4个特征,简单线性分类器进行的是加权计算。
深度学习中,在输入层和输出层之间加入了中间层,即隐藏层。
在中间层,由原来的4个特征变成了3个,深度学习的一个特点就是:通过组合低层特征形成更加抽象的高层特征。
传统机器学习先从图像中提取特征量,再用机器学习技术学习这些特征量的模式。这里所说的“特征量”是指可以从输入数据(输入图像)中准确地提取本质数据(重要的数据)的转换器。图像的特征量通常表示为向量的形式。在计算机视觉领域,常用的特征量包括SIFT、 SURF和HOG等。使用这些特征量将图像数据转换为向量,然后对转换后的向量使用机器学习中的SVM、 KNN等分类器进行学习。但是需要注意的是,将图像转换为向量时使用的特征量仍是由人设计的。也就是说,即使使用特征量和机器学习的方法,也需要针对不同的问题人工考虑合适的特征量。
神经网络直接学习图像本身。神经网络都是通过不断地学习所提供的数据,尝试发现待求解的问题的模式。也就是说,与待处理的问题无关,神经网络可以将数据直接作为原始数据,进行“端对端”的学习。
2. 感知机 2.1 什么是感知机 感知机是两类分类的线性分类模型。假设输入为实例样本的特征向量 x x x,输出为实例样本的类别 y y y,则由输入空间到输出空间的如下函数称为感知机:
y = g ( ∑ i = 1 n w i x i + b ) y=g(\sum_{i=1}^{n}w_ix_i+b) y=g(∑i=1nwixi+b)或者 y = g ( w ⋅ x + b ) y=g(w \cdot x+b) y=g(w⋅x+b)
g为激励函数,已到达对样本分类的目的。Rosenblatt的感知机用阶跃函数作为激励函数,其公式如下:
g ( z ) = { 1 , ( z > 0 ) 0 , ( z < = 0 ) \begin{aligned} g(z)=\left\{\begin{matrix} 1, (z>0)\\ 0,(z<=0) \end{matrix}\right.
一、需求:实现Springboot中MyBatisplus使用IPage和Page分页 二、技术:MyBatisplus的IPage和Page 三、实现 1、代码结构 2、代码详情 (1)Controller
package com.xkcoding.rbac.security.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Map; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xkcoding.rbac.security.service.InterService; @Slf4j @RestController @RequestMapping("/inter") public class InterController { @Autowired private InterService interService; @GetMapping("/test") public IPage<Map> test() { Integer currentPage = 1; //当前页数:显示第一页数据 Integer pageSize = 2; //每页显示多少:每页显示2条数据 Page<Map> page = new Page<Map>(currentPage, pageSize); IPage<Map> findList = interService.findlistpage(page); return findList; } } (2)Service
package com.xkcoding.rbac.security.service; import java.util.Map; import org.springframework.stereotype.Service; import com.
笔者正在用的老款的MacBook Air,办公还算够用,但是非retina屏实在看不下去了,一直想着换机。本以为今年苹果会发布14英寸的macbook pro,结果大家都知道了,并没有。除屏幕尺寸,新款macbook pro蝶式键盘改为剪刀脚键盘好评,容量256g起步好评,不足为低配仍然使用8代的intel处理器以及雷电口只有两个,观望许久最终还是没有下手。偶然看到网上的贴子小新pro13黑苹果不错,安装也简单,正好618,果断下手i5 8g 512核显版本,为什么没下手16g版本?因为8g办公够用。
2005,苹果宣布使用intel处理器,2006年,第一台搭载intel处理器的mac问世,黑苹果就一直是少部分人群喜爱折腾的东西,从最初的Chameleon到clover,再到现在的Opencore,黑苹果的安装似乎变得越来越容易,这些都得益于全球各地的大神们为此做的贡献。
小新pro13的黑苹果项目由宪武和黑果小兵在维护,网上很容易找到教程和EFI文件,讲讲在安装过程中的遇到的情况。我是使用原版的镜像写入优盘后,放入黑果小兵的Clover的EFI安装,安装过程中要始终选择“config-installer-revoery”来安装,注意是“始终”,直到进入Mac桌面,然后加载硬盘的EFI盘,将Clover或OC的EFI放进去做硬盘引导(单系统放进去就行,多系统黑果小兵网站安装教程中有详细说明)。注意如果要使用0602的OC引导要先解锁DVMT和CFG(单系统注意先在windows中先解锁再抹盘)。
小新pro13使用中遇到的一些问题
intel的网卡和蓝牙我没尝试去驱动,直接换了94360CS2拆机卡加转接卡,wifi、蓝牙、隔空投送使用正常0602的OC引导type-c转dp在设置-显示器中可以看到外接显示器型号,但是显示器不亮屏,若显卡仿冒注入platform-id:0x3ea50004的话,外接显示器正常,但是电脑屏幕会花屏,拔插一下type-c视频线能解决睡眠有时还是会不能唤醒,只能强行关机重启,我已设置不睡眠,但有时会随手合盖,然后就不能唤醒了Type-c优盘右键弹出后拔除提示未正确弹出优盘,再插无反应,且电脑无法关机和重启,风扇狂转,只能强行关机重启,使用USB优盘无问题 上述的种种问题,可能只是我这台电脑遇到的问题,不代表大家会遇到。对于一台连macbook pro一半价格都不到的机器,能使用上MacOS已经非常满意,待自研芯片的MacBook成熟时,再入白苹果。
最后,感谢Apple做出如此优秀的MacOS,感谢各路大神为Hackintosh所做的无私贡献。
隐写术 steganographia 概述 隐写术是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。隐写术的英文叫做Steganography,来源于特里特米乌斯的一本讲述密码学与隐写术的著作Steganographia,该书书名源于希腊语,意为“隐秘书写”。
CTF 隐写术分类 语义隐写术 符号码
隐语
虚字密码
技术隐写术 系统结构 纯隐写
密钥隐写
公钥隐写
空间结构 信道隐写
时空域隐写
变换域隐写
载体对象 图像隐写
文本隐写
音视频隐写
其他文件隐写
ctf 中通常使用以下格式作为信息载体进行隐写
图片文件 .jpg .png .gif .bmp
文本文件 .docx .pdf .zip
音视频文件 .wav .mp3 .mp4
其他特殊文件
现状 上来一套组合打击
binwalk + winhex 分析文件结构和内部数据stegsolve 分析lsb隐写stegdetect 检测特殊工具隐写 文件结构分析工具
TrID 工具
file (liunx 命令)
隐写实战 图片隐写 插入 利用文件格式的无关数据或者在空白区域放置需要的数据不会改变原始数据,只会增加隐写的内容
替换 每一字节的最低有效位进行变换不会改变文件大小,源文件会发生变化
考查点 在文件尾部插入字符
图片标记码之间插入字符
zip格式文件分离
图片文件分离 binwalk foremost
LSB 隐写二维码 stegsolve
RabbitMQ Linux下的安装之【极速版】 1.下载所需安装文件2.开始安装3.配置与启动测试 首先说明我们这里使用的Linux版本是CentOS7,相关内容可以参考我之前的博客:
VMware下载,安装及创建虚拟机
VMware安装Centos7 究极逐步详细图文流程
上文末还有Xshell的下载安装使用说明。
1.下载所需安装文件 直接附上资源链接(zip),不需要积分,直接下载,因为是极速版,这里只上传了一个版本的,截至目前最新版本为3.8.9,链接中的版本为3.6.5。(相关安装资源如果想自行下载的话可以参照详尽安装版)
下载链接:https://download.csdn.net/download/cjl836735455/13118790
压缩包中主要是三个文件:
erlang的安装包
erlang-18.3-1.el7.centos.x86_64.rpmsocat的安装包
socat-1.7.3.2-1.1.el7.x86_64.rpmrabbitmq的安装包
rabbitmq-server-3.6.5-1.noarch.rpm
2.开始安装 将我们解压好的安装文件上传到linux上
这里我们使用一个文件上传工具:【Linux】1.Xshell如何连接虚拟机实现文件上传
文件上传工具有很多,直接只简单带出来一个,只要能快速上传就OK。
在线安装依赖环境 yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c++ kernel-devel m4 ncurses-devel tk tc xz 安装Erlang rpm -ivh erlang-18.3-1.el7.centos.x86_64.rpm 我这里是没有出错的,但是注意,如果出现以下错误(没错的可以跳过这一步):
说明gblic 版本太低。我们可以查看当前机器的gblic 版本,语句为:
strings /lib64/libc.so.6 | grep GLIBC 然后根据报错图中提示的版本去升级对应的gblic,例如图中报错说需要2.15版本
升级glibc:
1.使用yum更新安装依赖 sudo yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make -y 2.下载rpm包 wget http://copr-be.cloud.fedoraproject.org/results/mosquito/myrepo-el6/epel-6-x86_64/glibc-2.17-55.fc20/glibc-utils-2.17-55.el6.x86_64.rpm & wget http://copr-be.
1.创建具有高电平有效同步复位的8 D触发器。触发器必须重置为0x34而不是零。所有DFF应由clk的负边缘触发。
module top_module ( input clk, input reset, input [7:0] d, output [7:0] q ); always@(negedge clk)begin if (reset) q <= 8'h34; //0x指十六进制 else q <= d; end endmodule 2.创建具有高电平有效异步复位的8 D触发器。
module top_module ( input clk, input areset, // active high asynchronous reset input [7:0] d, output [7:0] q ); always@(posedge clk or posedge areset)begin if(areset) q <= 8'd0; else q <= d; end endmodule 3.创建16个D触发器。有时只修改一组触发器的一部分很有用。字节使能输入控制在该周期是否应写入16个寄存器的每个字节。byteena [1]控制高字节d [15:8],而byteena [0]控制低字节d [7:0]。
Office全家桶卡死卡顿的解决方案 1、可能是部分office文件被破坏,此时可以下载office官网的修复工具链接,此方案针对于office完全不能使用的情况。
2、可能是打印机的问题,本人遇到Excel编辑卡死,过两分钟自动恢复和word卡顿及插入公式卡死的问题。这个就是共享打印机的问题了,就是你使用的是局域网内的打印机。解决方案是在系统中删除远程打印机即可,或者将网络切换到此打印机的局域网。这个是office的bug,如果你使用的是公网的打印机,是不会出现这种情况的,但是你使用的是局域网内的打印机,而当前网络不是该打印机所在的局域网,则会导致office全家桶的各种奇葩问题。
3、最麻烦的,卸载重装,我认为前两条基本可以解决大家遇到的问题了。
文章目录 DruidDataSource简介实现步骤 DruidDataSource简介 Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。Github地址:https://github.com/alibaba/druid/com.alibaba.druid.pool.DruidDataSource 基本配置参数如下: 实现步骤 导入添加上 Druid 数据源依赖。 <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> 通过 spring.datasource.type 指定数据源。完整配置 spring: datasource: username: root password: listen #?serverTimezone=UTC解决时区的报错 url: jdbc:mysql://localhost:3306/java_11_15?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.
echarts中清空图画 如图加上 myChart.clear(); 就可以了
<template> <div> <div id="brokenLine1" style="width: 100%; height: 600px"></div> </div> </template> <script> import echarts from "echarts"; export default { components: {}, props: {}, data() { return { }; }, watch: {}, computed: {}, methods: { myEchartSbrokenLine1() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById("brokenLine1")); // 指定图表的配置项和数据 letoption = { tooltip: { trigger: 'axis', axisPointer: { // 坐标轴指示器,坐标轴触发有效 type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' } }, legend: { data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'] }, grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, xAxis: { type: 'value' }, yAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] }, series: [ { name: '直接访问', type: 'bar', stack: '总量', label: { show: true, position: 'insideRight' }, data: [320, 302, 301, 334, 390, 330, 320] }, { name: '邮件营销', type: 'bar', stack: '总量', label: { show: true, position: 'insideRight' }, data: [120, 132, 101, 134, 90, 230, 210] }, { name: '联盟广告', type: 'bar', stack: '总量', label: { show: true, position: 'insideRight' }, data: [220, 182, 191, 234, 290, 330, 310] }, { name: '视频广告', type: 'bar', stack: '总量', label: { show: true, position: 'insideRight' }, data: [150, 212, 201, 154, 190, 330, 410] }, { name: '搜索引擎', type: 'bar', stack: '总量', label: { show: true, position: 'insideRight' }, data: [820, 832, 901, 934, 1290, 1330, 1320] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.
1、 为什么要做这个研究(理论走向和目前缺陷) ?
这是一篇比较早的做点云和图像融合做3D目标检测的论文,以前的融合没有做多层融合的,融合过程也过于单一,这篇论文提出了比较有新意的融合思路。
2、 他们怎么做这个研究 (方法,尤其是与之前不同之处) ?
双流,一个处理点云的鸟瞰图,一个处理图像,这里的关键是如何将鸟瞰图特征和图像特征对应起来然后融合(对应元素特征相加),3D点云恰好就是这个负责联系鸟瞰图特征和图像特征的媒介。具体说来就是,每个鸟瞰图像素点可以找到对应的点云中的3D点(找不到的化取最近的),然后这个点又可以投影到图像上找到对应的像素点(不一定位置就是整数,故需要用到双线性插值),那么就可以将鸟瞰图中的像素点和图像中的像素点对应起来了,然后由于主干网络用的是相同的,又是在同一个stage融合,故两个特征的维度是一样的,就可以将图像上的的像素点特征加到点云鸟瞰图上的对应像素点特征上,完成特征融合。
3、 发现了什么(总结结果,补充和理论的关系)?
思路很新,效果也还行,中间的参数化连续卷积实际就是一个MLP操作,但是在输入设计上还是很有思考的。
**摘要:**提出了一个可以利用连续卷积融合lidar和图像信息的3D目标检测器。所提出的连续融合层可以同时编码离散的图像特征和连续的几何信息。
**注:**本文所说的图像是离散的,是指处理图像特征的过程中是离散的,即任意两个像素点的位置偏移是整数,比如B点相对A点偏移是(1,1)。所说的点云是连续的,是指点云中任意两个点的距离可以是连续的,比如D点相对C点偏移是(0.0001, 0.002, 0.000001)。
1、 引言
以前基于点云做3D目标检测还是3大路线,把点云投影到图像视图,,或者投影到鸟瞰图上,或者进行3D体素化,或者直接对点云数据进行3D框回归(F-PointNet)。
上述对点云处理的方法各有各的缺点,投影方案会缺少深度信息或者信息丢失,3D体素化也有信息丢失且计算量大,直接对点云数据进行回归(F-PointNet)的准确度依赖于前面2D检测器的分割精度。
本文提出了一种基于鸟瞰图的3D目标检测网络,但是这个鸟瞰图通过把图像特征投影到了鸟瞰图上因而融合了图像特征。
2、 相关研究
基于雷达的检测:VeloFCN,3DFCN,PIXOR.
联合图像和点云的检测:F-PointNet.
在3D点云上的卷积:此文中的连续卷积其实就是对点云中的某个点,和其邻近点的位置关系利用一个MLP提取特征。
3、 多模态3D目标检测
融合点云和图像信息并不容易,因为图像是世界在一个平面视角的表征,而点云是实际世界的3D结构。一种比较好的方案就是将点云信息投影到图像视角,并作为一个深度通道和图像连在一起,然后用2D CNN来处理。但是要从2D输出中获取3D检测结果还是不简单的。
本文提出的思路是点云中的3D点作为一个中间媒介,这个3D点可以连接点云鸟瞰图中的像素点,也可以通过投影到rgb图像视角找到在图像特征中对应的像素点。具体来说就是,首先需要利用点云生成鸟瞰图,鸟瞰图中的任意一个像素可以找到这个像素在实际点云中对应的多个邻近3D点(KNN搜索得到),每个3D点又可以通过投影到前视图找到其在图像特征对应的像素点(如果投影过来的像素位置不是整数就要通过双线性插值来确定此3D点在图像中对应的像素点特征)。最后通过将此3D点和其在点云鸟瞰图中对应的那个像素点(3D点是点云鸟瞰图中像素点的临近点)偏移输入到MLP中计算3D点在图像视角对应的像素特征的权重。
3.1 连续融合层
深度参数化连续卷积(Deep Parametric Continuous Convolution):深度参数化连续卷积是基于同期的另外一篇论文出来的(Deep Parametric Continuous Convolutional Neural Networks Shenlong),这个卷积的可以在类似点云这样的数据上进行操作,我们传统意义上的卷积可以视为深度参数化连续卷积的一个特例。
参数化连续卷积可以用下式表示:
其中Xi是点云中的参考点,Xj是Xi的邻近点,可通过KNN算法找到,fj是Xj点对应图像特征。MLP对Xi的每个邻近点都计算一个fj的权重(卷积权重)。
上述过程就是计算一个Xi的参数化连续卷积特征。参数化连续卷积的好处就是它能够捕获局部特征,而且不用进行体素化那样的会损失几何信息的操作。
连续融合层:给定图像特征和3D点云的情况下,连续融合层的目的就是创建一个图像的鸟瞰图特征图,这个鸟瞰图特征图中的每个像素点的特征来自于图像特征(当然是对多个邻近像素点的图像特征进行加权的结果)。然后这个图像的鸟瞰图特征图和点云的鸟瞰图特征图进行融合。这里面有一个问题就是,在生成图像的鸟瞰图特征图的过程中需要用到点云的鸟瞰特征图中像素点在点云中对应的3D点,但是并不是每个点云鸟瞰图中的像素点都能找到在点云中对应的3D点,故基于2D 欧式距离找距离此像素点最近的K个3D点代替(这里还是没看明白,如果没有对应的3D点的话,z值就没办法确定,即使确定了x,y值也可能在不同的z值会搜索到不同的邻近点,也许实际情况下这种很少见,可能还是要看一下代码看看作者是如何处理的)。故输入到MLP中的包括两个部分:1)点云鸟瞰图像素点对应的K个邻近3D点在图像视角对应的图像特征(Di维),2)此临近3D点与点云鸟瞰图像素点对应的3D的位置偏移。将这两个部分连接成一个特征向量输入到MLP中,然后多个邻近点重复此过程求和,此过程操作如下:
与标准的连续卷积对比:
标注连续卷积公式:
其中g为连续核函数,f也是一个定义域连续的函数。。
本文的参数连续化连续卷积用MLP作为g。
3.3 多传感器目标检测网络
双流分别用来处理图像特征和鸟瞰图特征,并用来4个连续融合层来讲多尺度图像特征融合进鸟瞰图特征里。整体结构如下图所示:
主干网络用的是ResNet-18,通过连续融合层从图像分支里提取到的图像特征大小尺度和lidar stream提取到的对应层的特征是一模一样的,故可以采用对应元素相加来进行融合。
检测头:最后一个融合特征后接一个1X1卷积生成检测结果,每个像素点位置预测4个anchor的精细化定位(中心点位置,尺寸,朝向)和得分。然后紧跟一个NMS层。
训练:分类交叉熵,回归smooth L1.
4、实验
检测结果:
在KITTI 3D上评估是需要预测3D框中心点坐标z值和高度h,而在BEV视图下评估时不需要预测z和h,将这两项从损失函数中移去就行。
消融实验:
消融实验有点意思,KNN pooling代表是否使用knn算法搜素最邻近点,Geometric feature代表是否将临近点相对参考点的偏移也输入到MLP中。
消融实验结果表明:
目录 前言使用背景参考官方文档代码部分小结 前言 请等米下锅的同学直接阅读代码部分。
使用背景 最近项目组小伙伴们在开发使用Apache的Poi导出大批量数据时,总是出现内存溢出的情况。并且在生产环境,如果多个用户都导大批量数据报表时,服务器也很容易宕机。
虽然说Poi有SXSSFWorkbook这个类可以帮助我们导出较大批量的数据。其原理是用硬盘空间换内存这个样子。但是Excel2007最大一个sheet页也就支持1048576行。如果超出这个行数就需要去动态分多个sheet页去写入。由于我们是使用的模板去写入数据的,所以我们需要动态的克隆sheet页。之前只用过XSSFWorkbook类的cloneSheet方法。在阅读SXSSFWorkbook类的源码后,嗯!没实现,好的,算了算了。这也就是使用alibaba的开源项目EasyExcel的由来。EasyExcel重写了Poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出。所以有摩托车不用,非要蹬自行车吗?那不是傻么。
这里也就不介绍EasyExcel了,没有什么比官网更详细了。请各位看官去官网详细阅读。
参考官方文档 EasyExcel官方文档EasyExcel的github地址 代码部分 我们项目是使用Maven搭建的Springboot项目。
Maven依赖: <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency> 工具类 EasyExcelUtil package com.sinosoft.service.util; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.builder.ExcelWriterBuilder; import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.sinosoft.web.rest.util.SplitList; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.Date; import java.util.List; /** * @author QY * @since 2020-08-03 * @description 使用easyExcel来导出xlsx的工具类 */ public class EasyExcelUtil { private static final Logger log = LoggerFactory.
网上有很多方式,例如:skype:// callto:// 但都不适合
sip:<123456@qq.com> 通过这个可以调用Skype 商务版
1.立体匹配的关键任务就是预测精准的视差图,对于视差图每一个像素位置的值并不是(0-255)灰度值,而是一个视差值。
2.那么这些视差值如何得到的呢,最开始是由传统方法的 ’argmin‘得到。
arg min 就是使后面这个式子达到最小值时的变量的取值。例如 函数F(x,y): arg min F(x,y)就是指当F(x,y)取得最小值时,变量x,y的取值。
3.但这个 'argmin’并不可微,也就是说无法反向传播。
所以 GCNet这篇文章提出了’soft argmin’这个函数。
这个函数是‘softmax’操作,经常用于cv的分类任务中,将预测值转换为概率。就是最后的fc-layer将每个分类都赋予概率值。
4.那么在立体匹配中 'soft max’这个函数是如何使用的呢?
首先大家要清楚 经过代价聚合后的’cost volume’仍然是一个4D的代价体,深度学习的loss都是用自己网络的预测值与GT(Groud True)做对比分析,经过梯度计算对权重进行调整反向传播回每个神经元。所以对于输出维视差图的立体匹配网络,用这个4D的’cost volume’是无法生成loss的,所以要把它压缩到2D(把3D的特征体提取到2D的视差图).这时候采用’soft max’的思想把经过代价聚合过程的每个视差等级的feature maps通道压缩成1,每个视差等级只有一个feature map,softmax为每个视差等级都计算一个概率,每个像素的视差d乘以改层视差等级的概率,累加得出最后该像素的视差值,从而生成视差图注:‘softmax’ 分配给每个视差等级的概率和为’1’.soft argmin生成预测的视差图,之后还要经过 loss函数计算,反向传播调整网络。 enjoy~
Web Workers API 一个worker是使用一个构造函数创建的一个对象(e.g. Worker()) 运行一个命名的JavaScript文件 – 这个文件包含将在工作线程中运行的代码; workers 运行在另一个全局上下文中,不同于当前的window. 因此,在 Worker 内通过 window获取全局作用域 (而不是self) 将返回错误
在专用workers的情况下,DedicatedWorkerGlobalScope 对象代表了worker的上下文(专用workers是指标准worker仅在单一脚本中被使用;共享worker的上下文是SharedWorkerGlobalScope对象)。一个专用worker仅仅能被首次生成它的脚本使用,而共享worker可以同时被多个脚本使用
注意 在worker内,不能直接操作DOM节点,也不能使用window对象的默认方法和属性。然而你可以使用大量window对象之下的东西,包括WebSockets,IndexedDB以及FireFox OS专用的Data Store API等数据存储机制只要运行在同源的父页面中,workers可以依次生成新的workers;并且可以使用XMLHttpRequest 进行网络I/O,但是XMLHttpRequest的responseXML和channel属性总会返回nullworkers和主线程间的数据传递通过这样的消息机制进行——双方都使用postMessage()方法发送各自的消息,使用onmessage事件处理函数来响应消息(消息被包含在Message事件的data属性中)。这个过程中数据并不是被共享而是被复制。在框架中运行时需要解析Workers.js文件