不会还有人不懂Stream源码吧?10年架构师带你一次性搞懂

Stream源码解析 Spring Cloud Stream(简称SCS)提供了一系列预先定义的注解来声明输入型和输出型Channel,业务系统基于这些Channel与消息中间件进行通信,而不是直接与具体的消息中间件进行通信。跟踪SCS的源码就会发现,Stream有很多外部依赖,最主要的就是Messaging和Integration两个项目,所以在讲解SCS源码前,有必要先介绍一下Messaging和Integration与SCS体系的关系。 SCS的目标是建立一套统一的基于注解的消息发送机制,屏蔽开发人员直接与底层消息系统进行细节交互,而Messaging模块正是Spring框架中用来做统一消息编程模型的,在Messaging中最关键的数据结构是Message,代码如下: 在Messaging模块中消息通道MessageChannel是一个接口类,用于发送Message消息,可以理解为Messaging模块中的标准接口,类似于J2EE中的Servlet接口,具体实现类可以实现具体消息通道。下面是MessageChannel的代码: 在Messaging模块中,消息通道的子接口SubscribableChannel继承了MessageHandler消息处理器: 由MessageHandler真正地消费/处理消息: Integration基于Spring框架可以实现轻量级的消息传递,也是对Messaging的扩展实现,支持通过声明适配器与SCS集成。它实现了消息 过 滤 、 消 息 转 换 、 消 息 聚 合 和 消 息 分 割 等 功 能 , 提 供 了 对MessageChannel 和 MessageHandler 的 实 现 , 包 括 DirectChannel 、ExecutorChannel、PublishSubscribeChannel,以及MessageFilter、ServiceActivatingHandler、MethodInvokingSplitter等。下面介绍Integration 中 的 两 种 消 息 分 发 器 :DirectChannel 和PublishSubscribeChannel。 从代码可知,DirectChannel内部的UnicastingDispatcher类型分发器会发到对应消息通道的MessageChannel中,从名字也可以看出来,UnicastingDispatcher是一个单播的分发器,只能选择一个消息通道。而PublishSubscribeChannel使用BroadcastingDispatcher作为广播消息分发器,会把消息分发给所有的MessageHandler。 SCS在Integration的集成上进行了封装,通过注解的方式和统一的API进行消息的发送和消费,底层消息中间件的实现细节由各个消息中间件的Binder完成,同时,通过与Spring Boot的ExternalizedConfiguration整合,SCS提供了BindingProperties等外部化配置类,这些具体的配置信息将绑定到具体的消息中间件的配置类中。 SCS的架构流程图 下面是SCS的架构流程图,我们会从几个层次分别讲解其中相关联的源码和它们之间的交互关系。 应用层 SCS为用户提供了三个绑定消息通道的默认实现。 Sink:通过指定消费消息的目标来标识消息消费者。Source:与Sink相反,用于标识消息生产者。Processor:集成了Sink和Source的功能,用于标识消息生产者和消费者。 对应用而言,想要启动SCS的功能 ,需要先启动注解 。 @EnableBinding注解是Stream框架运转的起点,通过这个注解可以实现动态注册BeanDefinition,它会将消息通道绑定到自己修饰的目标实例上,从而让这些实例具备与消息队列进行交互的能力。下面我们看源码: BindingServiceConfiguration的 作 用 是 完 成BindingService、InputBindingLifecycle、OutputBindingLifecycle等重要Bean的初始化及相关配置文件加载。BindingBeansRegistrar的作用是注册声明通道的接口类的BeanDefinition,从而获取这些接口类的实例,并使用这些实例进行消息的发送和接收,具体代码实现如下: registerBindingTargetBeanDefinitions方法会调用ReflectionUtils类完成扫描所有被注解@Input和@Output标注了的方法,然后注册BeanDefinition。下面是代码示例:

ROS:bag包内容提取——有时间戳的图片

通常在利用ros采集传感器数据时,我们会得到一个包含多个传感器数据的bag数据包,下面将会介绍从bag数据包提取有时间戳的图片。 系统版本:Ubuntu20.04 ROS版本:Noetic 先觉条件: 查看bag数据包中雷达点云数据和imu数据所对应的topic名称,通过下面这条指令实现。 rosbag info <xxxxxx.bag> #<xxxxxx.bag>指bag数据包的名称 需创建工程进行相关操作,依次执行以下指令。 mkdir -p ~/extrapicture/src cd ~/extrapicture/src catkin_make cd ~/extrapicture/src catkin_create_pkg image std_msgs rospy roscpp 创建了一个名为image的功能包,包含一个cmakelists和package.xml。 工程如下: image.h /* #include <ros/ros.h> #include <message_filters/subscriber.h> #include <message_filters/synchronizer.h> #include <message_filters/sync_policies/approximate_time.h> #include <sensor_msgs/Image.h> #include <sensor_msgs/Imu.h> #include <geometry_msgs/PoseStamped.h> #include <std_msgs/String.h> */ #include <opencv2/highgui/highgui.hpp> #include <cv_bridge/cv_bridge.h> #include <string> #include <fstream> #include "/opt/ros/noetic/include/ros/ros.h" #include "/opt/ros/noetic/include/message_filters/subscriber.h" #include "/opt/ros/noetic/include/message_filters/synchronizer.h" #include "/opt/ros/noetic/include/message_filters/sync_policies/approximate_time.h" #include "/opt/ros/noetic/include/sensor_msgs/Image.h" #include "/opt/ros/noetic/include/sensor_msgs/Imu.h" #include "/opt/ros/noetic/include/geometry_msgs/PoseStamped.h" #include "/opt/ros/noetic/include/std_msgs/String.h" using namespace std; // typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Imu, geometry_msgs::PoseStamped> MySyncPolicy; typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Imu> MySyncPolicy; class dataSynAcq{ public: //dataSynAcq( string image_dir, string imu_dir, string gt_dir ); dataSynAcq( string path ); ~dataSynAcq(); ros::NodeHandle nh; void CallBack( const sensor_msgs::ImageConstPtr &image, const sensor_msgs::ImuConstPtr &imu ); private: message_filters::Subscriber<sensor_msgs::Image> *image_sub_; message_filters::Subscriber<sensor_msgs::Imu> *imu_sub_; // message_filters::Subscriber<geometry_msgs::PoseStamped> *gt_sub_; message_filters::Synchronizer<MySyncPolicy> *sync_; string seq_; string image_dir_; string imu_dir_; // string gt_dir_; ofstream image_stamp; ofstream imu_file; //ofstream gt_file; }; image.

0基础学MySQL数据库—从小白到大牛(38)数据库备份与恢复

文章目录 前言物理备份与逻辑备份MySQLdump实现逻辑备份备份一个数据库备份全部数据库备份部分数据库备份部分表备份单表的部分数据排除某些表的备份只备份结构或只备份数据备份中包含存储过程、函数、事件mysqldump常用选项 MySQL命令恢复数据单库备份中恢复单库全量备份恢复从全量备份中恢复单库从单库备份中恢复单表 物理备份:直接复制整个数据库物理恢复:直接复制到数据库目录表的导入与导出表的导出表的导入 前言 本章使用的测试数据库为GreatSQL8.0.25版本 (Wed Aug 3 16:17:03 2022)[root@GreatSQL][(none)]>select version(); +-----------+ | version() | +-----------+ | 8.0.25-16 | +-----------+ 1 row in set (0.00 sec) 物理备份与逻辑备份 物理备份:备份数据文件,转储数据库物理文件到某一目录。物理备份恢复速度比较快,但占用空间比较大,MySQL中可以用xtrabackup工具来进行物理备份。 逻辑备份:对数据库对象利用工具进行导出工作,汇总入备份文件内。逻辑备份恢复速度慢,但占用空间小,更灵活。MySQL 中常用的逻辑备份工具为mysqldump。逻辑备份就是备份sql语句,在恢复的时候执行备份的sql语句实现数据库数据的重现。 MySQLdump实现逻辑备份 备份一个数据库 mysqldump –u 用户名称 –h 主机名称 –p密码 待备份的数据库名称[tbname, [tbname...]]> 备份文件名 称.sql 说明: 备份的文件并非一定要求后缀名为.sql,例如后缀名为.txt的文件也是可以的。 举例:使用root用户备份atguigu数据库: mysqldump -uroot -p GG>GG.sql #备份文件存储在当前目录下 mysqldump -uroot -p GG > /var/lib/mysql/GG.sql 备份全部数据库 若想用mysqldump备份整个实例,可以使用 --all-databases 或-A参数: mysqldump -uroot -pxxxxxx --all-databases > all_database.sql mysqldump -uroot -pxxxxxx -A > all_database.

使用-screen命令

在ubuntu下经常需要同时使用多个命令行窗口,例如一个用于编译,一个用于看代码,一个用于adb shell等等。 ubuntu自带的gnome-terminal终端程序,可以支持标签页,也能满足上面的需求,但无法同时显示多个标签页,除非同时打开多个终端程序,这样切换起来也比较麻烦。所以研究了一下screen命令。 screen命令在一个终端程序中,切割成多个不同的区域,不同的区域可以同时显示。但要用screen命令,首先需要理解一些概念。 1. 相关概念 region(区域):region就是分割出来的一块一块的物理区域,可类比电脑屏幕 window(会话):windows就是一个一个的命令行,可类比电脑上运行一个程序 一台电脑可以有多个屏幕(region),并且同时运行多个程序(window);每个屏幕(region)上可以分时显示多个不同的程序(window);一个程序(window)可以同时显示在一个或多个不同的屏幕(region)上。 2. 快捷键 所有的screen设置,都必须先按ctrl + a,然后再按对应的快捷键。下面列出了我常用的一些命令,其中 -> 表示按下ctrl + a后并松开后,需要按另外的键 帮助 ctrl + A -> ? 创建一个新的window ctrl + A -> c (小写c) 修改window名称(方便区分) ctrl + A -> A (大写A) 左右分屏(把当前区域region切割成左右两块) ctrl + A -> | 上下分屏(把当前区域region切割成上下两块) ctrl + A -> S (大写S) 列出所有window ctrl + A -> w (小写w) 在当前region显示某个window(每个window对应的数字可用ctrl + A -> w查看) ctrl + A -> 数字0-9 region间顺序切换

编译-glib交叉编译

glib是一个C语言函数库,它对很多系统调用进行了封装,提供了很多实用的功能,能极大地方便编程。 为了在产品上尝试使用glib,需要对glib进行交叉编译,使其能在ARM9上运行。 以下是版本信息: 开发平台:Linux ubuntu 3.8.0-35-generic #52~precise1-Ubuntu SMP PC gcc 版本 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ARM gcc version 4.1.2 zlib-1.2.8 libffi-3.2.1 glib-2.45.3 为了方便说明,先假设 1、zlib-1.2.8.tar.gz、libffi-3.2.1.tar.gz和glib-2.45.3.zip都已经解压到/home/user/build/目录下,分别是/home/user/build/zlib-1.2.8、/home/user/build/libffi-3.2.1和/home/user/build/glib-2.45.3。 2、CC是交叉编译器,根据自己的实际编译器而不同,这里CC最好时包含完整的路径。我这里是/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc 开始编译 1. 编译zlib,编译脚本如下: cd /home/user/build/zlib-1.2.8 CC=/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc \ ./configure --prefix=/home/user/build/zlib-1.2.8/install/arm/ make if [ $? == 0 ]; then make install else echo -e "\n\tmake fail\n" fi 执行成功之后,zlib就会安装在/home/user/build/zlib-1.2.8/install/arm/目录 2. 编译libffi,编译脚本如下: #!/bin/bash cd /home/user/build/libffi-3.2.1 ./configure --prefix=/home/huo/dbus/libffi-3.2.1/install/arm/ \ CC=/opt/freescale/usr/local/gcc-4.1.2-glibc-2.5-nptl-3/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-gcc \ --host=arm-none-linux-gnueabi make if [ $? == 0 ]; then make install else echo -e "

介绍-fs、ramdisk、ramfs、tmpfs、initramfs和rootfs

看了一些关于Linux根文件系统、initramfs的帖子和文档,这里写一下自己的理解。 1、文件系统fs 什么是文件系统,我自己的理解就是数据的组织结构。要理解一个概念,首先应该知道为什么会\提出这个东西,它是为了解决什么问题的。比如说一个文本文件,我们通常看到的可能是里面的一句“hello world”的内容,但是当我们需要保存或者读取这个文件的时候,就需要考虑这个文件的名字该怎么保存,文件的大小又该怎么保存,我怎么知道到哪里才是这个文件的结束等等。文件系统可以有序地把这些数据组织起来,这就是我理解的文件系统。 2、文件系统、块设备与ramdisk 文件系统是一个软件上面的概念,数据一般是保存在物理设备上的,如硬盘、Flash等块设备。我简单地理解为用户文件->文件系统->物理设备这样三层的结构。 文件系统的格式常见的有ext2、yaffs2等。至于ramdisk,就是用内存模拟了一个块设备,这个模拟的“块设备”是需要一个文件系统来组织数据的。我们创建一个ramdisk以后需要把它格式化为ext2或者其他文件系统格式,跟硬盘类似。ramdisk主要用于2.4版本的内核上,目前已经慢慢被淘汰。 3、ramfs和tmpfs 说到ramdisk,为什么它会被淘汰呢?是因为它会浪费内存、内存带宽以及CPU时间。Linux系统本身有一个缓冲的机制(disk caching mechanisms),它会把块设备的数据进行缓冲(其实就是复制到内存中),那么ramdisk也算是一个块设备,所以它所保存的数据也会被缓冲。换而言之,一份数据可能会同时存在于缓冲区以及ramdisk中(实际上都在内存中),这样会涉及到数据在缓冲区以及ramdisk之间的拷贝问题,所以才会存在浪费内存、内存带宽以及CPU时间的问题。 所以伟大的Linux又创造了ramfs。 刚才说到,文件系统需要把数据保存到对应的物理设备上,Linux称这个对应的物理设备叫做backing store。那么ramfs是没有backing store的,所以就不存在ramdisk的数据拷贝问题了。ramfs是基于Linux disk caching mechanisms,所以你也可以理解为用户文件->ramfs文件系统格式->Linux disk caching mechanisms这样三层的结构(这个说法并不正确,只是便于理解)。 有了ramfs以后怎么又蹦出来一个tmpfs呢? tmpfs跟ramfs其实很类似,但比ramfs多了两个特性,一是tmpfs有大小的限制;二是tmpfs可以把暂时不用的东西回写到swap分区。 ramfs是没有大小限制的,可以一直写直到内存被塞满。另外,由于没有backing store,一些不常用的数据不能回写,只能一直占用内存,内存管理系统无法对这部分的内存进行回收,导致内存有效使用率比较低。所以针对这些问题,才有了tmpfs的改进。 4、根文件系统rootfs 什么是Linux的rootfs,我的理解是rootfs=特定的文件夹(文件)+tmpfs+disk caching mechanisms这样三层的结构。把dev、etc、home等等这些Linux运行所必须的文件夹(文件、设备节点),按照tmpfs文件系统格式的要求组织好以后,保存在disk caching内存中的这一整个东西就是我理解的根文件系统。 5、rootfs和initramfs kernel运行时的rootfs是在内存中的,那么未运行前rootfs可能是保存在Flash、SCSI甚至是网络中的。如果要kernel适应所有的这些情况,那么kernel本身就需要集成很多的驱动。考虑一种情况,你的电脑启动的时候需要读取SCSI中的一副图片显示在屏幕上,但等半天都没有读取完,屏幕一片黑,这样不友好的启动过程肯定被产品经理杀死千百遍啊!所以为了简化kernel,同时提高启动的速度,于是有了initramfs。 那么initramfs又是个什么鬼?initramfs是一个cpio格式的包,可以类比为一个tar包。这里注意了,initramfs并不按照任何文件系统的格式组织数据! 刚才我把运行时的根文件系统理解为rootfs=特定的文件夹(dev、etc、home等)+tmpfs+disk caching mechanisms三个部分,那么initramfs可以理解为initramfs=特定的文件夹(文件),把这些文件夹按照cpio格式打包就是initramfs了,里面并不包含tmpfs文件系统的东西。作为对比,initramfs的前世initrd就是包含了文件系统的。所以可以理解为initrd=特定的文件夹(dev、etc、home等)+文件系统(ext2或其他)。所以initrd是需要加载到ramdisk中,而不是tmpfs。 编译kernel的时候,这个initramfs是以一个cpio包的形式被包裹到kernel的镜像中的。当kernel启动的时候,把initramfs解开,把里面的文件夹(文件)复制到一个tmpfs格式的分区中,那么就可以把这个分区作为根文件系统了!当然你可以事先在initramfs中放一副图片作为显示logo,这样就可以给用户一个友好的开机过程了。 以上全是个人理解,可能与实际会有偏差,仅供参考。 最后推荐几个文档: https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt http://wiki.sourcemage.org/HowTo%282f%29Initramfs.html IBM Developer http://blog.linux.org.tw/~jserv/archives/001954.html 特别是ramfs-rootfs-initramfs.txt,这个就是kernel中关于ramfs、tmpfs、initramfs和rootfs最最权威的说明了。

介绍-Linux capability机制

1. 权限 1)传统的Unix系统,从权限的角度可以把用户分为特权用户root(privileged user)和普通用户(unprivileged user)。通过这两种用户执行的进程,就是对应的privileged processes和unprivileged processes。 2)root进程拥有所有的权限。而普通用户进程则要进行权限的检查,这种检查一般是基于文件的UID、GID进行检查的。例如,普通用户进程要向串口ttyS0写一个字符,那么该进程就要write一个字符到文件(设备节点)/dev/ttyS0,此时,kernel就会检查进程的UID、GID是什么,文件ttyS0的User读写权限、Group读写权限和Other读写权限,匹配上以后才允许普通进程写数据到串口。 3)以上是一种基于文件读写执行(rwx)权限的机制,但有很多权限是不需要操作文件的,例如给某个进程发送信号、创建socket并绑定某个网卡等等,因此,从Linux 2.2开始引入了capability权限机制。capability机制相比文件权限检查更完善、更灵活。 4)capability把权限进行了拆分,可以把部分权限赋予给普通用户进程,而不需要切换到root。 2. capability 1)capability具体的权限,可以命令行查看 man capabilities 目前较新的kernel支持最多41种权限。 2)capability权限分类 Linux capabilities 分为进程 capabilities 和文件 capabilities。 进程 capabilities 对于进程来说,capabilities 是细分到线程的,即每个线程可以有自己的capabilities。 文件capabilities 对于文件(可执行文件)来说,capabilities 保存在文件的扩展属性security.capability中。 3)capability权限集 在进程capabilities下,又把权限分成了5个权限集合,分别是: Permitted This is a limiting superset for the effective capabilities that the thread may assume. It is also a limiting superset for the capabilities that may be added to the inheritable set by a thread that does not have the CAP_SETPCAP capability in its effective set.

Go语言位运算符|与、或、异或、左移、右移

第一个:& 按位与 运算规则:如果两数对应的二进制位都为 1,那么结果为 1, 否则结果为 0。 第二个:|按位或 运算规则:如果两数对应的二进制位有一个为 1,那么结果为 1, 否则结果为 0。 第三个:^ 按位异或 运算规则:如果两数对应的二进制位不同,那么结果为 1, 否则结果为 0。 第四个:<< 左移 运算规则:左移N位,就是乘以 2 的 N 次方。 第五个:>> 右移 运算规则:右移 N 位,就是除以 2 的 N 次方 举例子: package main import ( "fmt" ) func main() { var a = 15 // 0000 1111 var b = 7 // 0000 0111 var c = a & b // a & b = 0000 0111 = 7 var d = a | b // a | b = 0000 1111 = 15 var e = a ^ b // a ^ b = 0000 1000 = 8 var f = 128 << 3 // 128 乘以 2^3 = 1024 var g = 128 >> 3 // 128 除以 2^3 = 16 fmt.

MySQL——事务及事务日志篇

一、数据库事务概述 1.1、存储引擎支持情况 show engines;命令可以可以查看当前MySQL支持的存储引擎有哪些,以及这些存储引擎是否支持事务。 可以看出,在MySQL中,只有InnoDB存储引擎是支持事务的。 1.2、基本概念 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理的原则:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方 式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所做的所有修改,整个事务回滚( rollback )到最初状态。 举一个在讲解事务时最经典的例子: 银行转账:AA用户给BB用户转账100元,则在AA用户的账户余额中减100,BB用户的账户余额加100,如果没有事务控制的情况下,AA用户转账成功,这时服务器发生了故障,导致BB用户并没有收到这笔转账,这样就出现问题了。 # 案例:AA用户给BB用户转账100 update account set money = money - 100 where name = 'AA'; # 服务器宕机 update account set money = money + 100 where name = 'BB'; 1.3、事务的ACID特性 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚。即要么转账成功,要么转账失败,是不存在中间的状态。如果无法保证原子性会怎么样?就会出现数据不一致的情形,A账户减去100元,而B账户增加100元操作失败,系统将无故丢失100元。 一致性(Consistency) 根据定义,一致性是指事务执行前后,数据从一个合法性状态变换到另外一个合法性状态。这种状态是语义上的而不是语法上的,跟具体的业务有关。 那什么是合法的数据状态呢?满足预定的约束的状态就叫做合法的状态。通俗一点,这状态是由你自己来定义的(比如满足现实世界中的约束)。满足这个状态,数据就是一致的,不满足这个状态,数据就是不一致的!如果事务中的某个操作失败了,系统就会自动撤销当前正在执行的事务,返回到事务操作 之前的状态。 举例1:A账户有200元,转账300元出去,此时A账户余额为-100元。你自然就发现此时数据是不一致的,为什么呢?因为你定义了一个状态,余额这列必须>=0。 举例2:A账户有200元,转账50元给B账户,A账户的钱扣了,但是B账户因为各种意外,余额并没有增加。你也知道此时的数据是不一致的,为什么呢?因为你定义了一个状态,要求A+B的总余额必须不变。 举例3:在数据表中我们将姓名设置为唯一性约束,这时当事务进行提交或者事务发生回滚的时候,如果数据表的姓名不唯一,就破坏了事物的一致性要求。 隔离性(isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。 如果无法保证隔离性会怎么样?假设A账户有200元,B账户0元。A账户往B账户转账两次,每次金额为50 元,分别在两个事务中执行。如果无法保证隔离性,会出现下面的情形: UPDATE accounts SET money = money - 50 WHERE NAME = 'AA'; UPDATE accounts SET money = money + 50 WHERE NAME = 'BB'; 持久性(durability)

【Docker Desktop】Neo4j

1、下载neo4j并启动 docker run --rm --name testneo4j -p 7474:7474 -p 7687:7687 -d -v C:/Users/ASUS/Desktop/neo4j/data:/data -v C:/Users/ASUS/Desktop/neo4j/logs:/logs -v C:/Users/ASUS/Desktop/neo4j/import:/var/lib/neo4j/import -v C:/Users/ASUS/Desktop/neo4j/plugins:/plugins --env NEO4J_AUTH=neo4j/test neo4j:latest 桌面的neo4j文件夹会被自动创建7474是neo4j默认http通信端口,使得可以用浏览器访问可视化界面7687是neo4j默认用于Bolt协议的端口,Bolt协议是neo4j的应用层协议–env指定了NEO4J_AUTH环境变量,该环境变量用于设置登录账号和密码:分别为neo4j和test 2、浏览器访问 http://localhost:7474 3、创建一个node CREATE (ee:Person { name: "Emil", from: "Sweden", klout: 99 }) ee只是变量,可以为其他名称 4、查看刚创建的node MATCH (ee:Person) WHERE ee.name = "Emil" RETURN ee; 5、另外创建四个node,并定义关系 MATCH (ee:Person) WHERE ee.name = "Emil" CREATE (js:Person { name: "Johan", from: "Sweden", learn: "surfing" }), (ir:Person { name: "Ian", from: "England", title: "

BF(暴力求解算法)

BF(暴力求解算法) 即是暴力(BruteForce)算法,是普通的模式匹配算法,BF算法的思想就是将目标串T的第一个字符和主串的S的第一个字符进行匹配,若相等,则则继续匹配T串和S串的第二个字符,若不相等,则比较主串S的第二个字符和模式串T的第二个字符,依次比较下去,知道得到最后的匹配结构。BF算法也是一种蛮力算法。 算法思想: 普通模式匹配算法,其实现过程没有任何技巧,就是简单粗暴地拿一个串同另一个串中的字符一一比对,得到最终结果。 代码复杂度:O(n*m) 该算法最理想的时间复杂度 O(n),n 表示串 A 的长度,即第一次匹配就成功。 BF 算法最坏情况的时间复杂度为 O(n *m),n 为串 A 的长度,m 为串 B 的长度。例如,串 B 为 “0000000001”,而串 A 为 “01”,这种情况下,两个串每次匹配,都必须匹配至串 A 的最末尾才能判断匹配失败,因此运行了 n *m 次。 演示过程: 使用普通模式匹配算法判断串 A(“abcac”)是否为串 B(“ababcabacabab”)子串的判断过程如下: 1.首先,将模式串和主串对齐,依次进行匹配是否相等 B:ababcabcacbab A:abcac 2.若不相等,B串开始回溯,从第二个字符开始与A串的第一个字符开始匹配是否相等 B:ababcabcacbab A: abcac 3.若不相等,B串开始回溯,从第三个字符开始与A串的第一个字符开始匹配是否相等 B:ababcabcacbab A: abcac 4.两串的模式匹配失败,串 A 继续移动,一直移动至匹配的位置才匹配成功: B:ababcabcacbab A: abcac 由此,串 A 与串 B 以供经历了 6 次匹配的过程才成功,通过整个模式匹配的过程,证明了串 A 是串 B 的子串(串 B 是串 A 的主串)。 BF算法实现-C语言 #include <stdio.

【Linux】找不到ensss IP地址 或者连接不上ssh解决方法

Linux 找不到ensss IP地址 或者连接不上ssh解决方法 原因 虚拟机网络的问题导致,也可能由于电脑休眠导致虚拟机进入软锁状态 查看ip地址 一: ifconfig 二: id addr 解决方式一 依次输入下列代码: # service NetworkManager stop # service network restart 解决方式二 依次输入下列指令: # systemctl stop NetworkManager # systemctl restart network 终极方案 关闭虚拟机镜像,点击 编辑 点击虚拟机网络编辑器 点击虚拟机网络编辑然后出现下面弹窗,恢复虚拟机网络即可,最后重启下服务 重复 解决方法一或二的指令

C语言经典程序

1、输入一行字符统计单词个数 输入一行字符串,统计其中有多少单词,单词之间用空格符号隔开 #include<stdio.h> int main() { printf("请输入一行字符串:"); int i = 0, word = 0; char str[81]; gets_s(str); while (str[i] != '\0') { if (str[i] == ' ') { //跳过所有空白字符 for (i++; str[i] == ' '; i++); } else { word++; //跳过所有非空格,即一个单词 for (i++; str[i] != ' ' && str[i] != '\0'; i++); } } printf("字符串单词数量:%d", word); return 0; } 1、字符串以'\0'作为结束标志 2、for循环内的 第一部分的i++ 类似开关,使得下标能指向下一位元素进行判断 2、输出不重复三位数 - 有0、1、2、3、4共5个数字 能组成多少个互不相同且无重复数字的3位数?并输出这些数 #include<stdio.h> int main() { int i, j, k, count = 0; for (i = 1; i < 5; i++) { for (j = 0; j < 5; j++) { for (k = 0; k < 5; k++) { if (i !

Markdown语法如何添加按钮

Markdown语法如何添加按钮?我们知道在 Markdown 中,我们可以创建一些图片以及一些 Link。那么问题来了,我们在 Markdown 是否可以把它做成一个按钮那样的 look and feel 呢?我们知道在 TSVB 中的 Markdown 可以使用 CSS 来定制这些。我们可以通过 CSS 的定制来做一些调整从而达到我们想要的效果。 打开 Kibana。 我们在 Markdown 的编辑器中打入如下的两行: [Elastic](https://www.elastic.co/) [ELastic 中文博客社区](https://elasticstack.blog.csdn.net/) 那么在上面,我们可以看到有两个链接。我们点击鼠标的右键,它会弹出一个框来。我们选择 Inspect: 我们可以看见这两个链接是如何显示的。我们点击上图中的 Panel options。我们可以在 CSS 的编辑框中对这两个链接进行定制: p a {border-style: outset; text-align:center;margin-right:40%; margin-left:40%; text-decoration: none;} 我们把上面的 CSS 代码写入到 CSS 的编辑器中。 我们再重新查看一下我们之前创建的链接。 显然,之前的两个链接现在更像是两个按钮。我不是一个 CSS 的专家。剩下的留给你们把这两个按钮做的更加漂亮。 当我们点击上面的按钮时,它会带我我们去指定的网页。 在上面,我们使用一些网站的地址。在实际的物联网的应用中,我们可以直接绑定一些 REST API 的接口来对物联网里的设备进行控制。 以上就是我为大家带来的“Markdown语法如何添加按钮”,你学会了吗?

Fragment 的使用

Android 学习笔记 —— Fragment 的使用 FragmentFragment 的简单使用动态添加 Fragment在 Fragment 中模拟返回栈,返回上一个 FragmentFragment 和 Activity 之间进行通信使用限定符动态加载布局Fragment 的生命周期androidx.fragment.app.FragmentContainerViewonActivityCreated() 被弃用 Fragment Fragment 表示应用界面中可重复使用的一部分。Fragment 定义和管理自己的布局,具有自己的生命周期,并且可以处理自己的输入事件。Fragment 不能独立存在,而是必须由 Activity 或另一个 Fragment 托管。Fragment 的视图层次结构会成为宿主的视图层次结构的一部分,或附加到宿主的视图层次结构。 上面是官方对 Fragment 的介绍。其实 Fragment 和 Activity 很相似,但使用 Fragment 可以将一个完整的界面划分为离散的区块,然后嵌入到 Activity 中,从而将模块化和可重用性引入 Activity 的界面。说白了就是可以在不切换 Acitivty 的同时变更 UI 界面中某一区域的内容,Activity 适合放置全局元素,而 Fragment 更适合定义和管理单个屏幕或部分屏幕的界面。 Fragment 的简单使用 使用步骤: 编写 Fragment 的布局文件 fragment_left.xml 和 fragment_right.xml。 <!-- fragment_left.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button_left_fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Button" /> </LinearLayout> <!

仿记事本--含源码(java版)(基础功能版)

题目: 掌握常用组件的基本操作以及输入输出流的使用,并用相关知识设置一个仿记事本软件,能够实现新建、打开、保存和另存为等基本功能。 设计思路: 1.明确题目要求的功能:新建文件、打开文件、保存文件、另存为文件 2.了解记事本的操作:题目较为简单明了--仿记事本,因此我们便要大致了解记事本是什么样的,其基本模板便是左上角为功能区,有一个文本区,这个是最直观的表示。因此,我们也选择模仿这个布局。 3.通过该图片,来设置我们的页面布局:我们可以发现其功能都是以菜单形式展示出来,而我们所需要完成的功能都在文件这一菜单下,因此我们也采取菜单组件对其进行设计,我们创建四个菜单项itemNew、itemOpen、itemSave、itemSaveAs分别代表新建、打开、保存和另存为四个功能,之后建立一个菜单menu,将这些菜单项添加到菜单中,最后将菜单加入到菜单条menuBar中即可;除此我们通过创建JTextArea类的对象area来实现上图文本区的功能;最后对四个菜单项通过addActionListener()方法添加事件监听即可。以上就是对窗体基本的页面布局。 4.实现功能:通过使用记事本我们很容易发现一点,记事本是需要和本机文件进行交互的,即可视化选择文件及选择文件夹,在这里,我们便要使用Java提供的JFileChooser类,该类可以创建文件对话框,让我们能够在可视化界面对文件进行交互;文件对话框有三种可见方法,showDialog()、showSaveDialog()、showOpenDialog(),后面两个方法为保存和打开的可视化界面,那么我们在写打开和保存的时候也可以直接使用这两个方法,在实现新建和另存为时,我们需要自定义文件对话框,需要使用showDialog()方法,在该方法中,需要传递参数showDialog(Component a,String name);前面的参数为一个组件,通常使用this即可,后面的name表示我们定义的名字,我对其分别定义为“新建”和“另存为”来对应这两个功能。在实现了这个可视化操作之后,后面的就比较简单了,只需要通过IO流对其进行读写操作即可,在这里面我使用的是缓冲流读写,可以按行读取,较为方便。 知识储备: 该程序难度偏中低等,可以作为我们学习完窗体和IO流之后对我们的小测试,涉及到的知识点如下: 1.组件的常规操作:该问题中设计到的组件不多,所以可以多研究一下,怎么写能够使自己的布局思路更加清晰,用来锻炼自己的思维比价合适; 2.IO流的读写操作:该题目涉及到对文本的读取等操作,了解IO流的基本知识便可以,没有难度较大的知识点; 3.学会使用文本选择框:在文本选择框中存在比较多的方法,要熟悉这些方法的使用,能够对我们的代码做到全部理解。 代码: //主类 package Demo_24_shiyan; /** * @ClassName 主类 * @Description TODO * @Author 今夕河西 * @Date 2022-09-30 19:10 * @Version 1.0 **/ public class Main { public static void main(String[] args) { Txt_Text win = new Txt_Text(); win.setTitle("记事本"); } } //窗体事件类 package Demo_24_shiyan; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; /** * @ClassName 仿记事本 * @Description TODO:设计一个仿记事本软件,实现新建、打开、保存、另存为等基本功能 * @Author 今夕河西 * @Date 2022-09-30 19:08 * @Version 1.

aircrack-ng for windows的简单使用教程

由于在Windows环境下不能如Linux环境般直接调用无线网卡,所以需要使用其他工具将无线网卡载入,以便攻击工具能够正常使用。在无线攻击套装Aircrack-ng的Windows版本下内置了这样的工具,就是airserv-ng。 步骤1:打开CMD,通过cd命令进入到aircrack-ng for Windows版本所在目录,输入airserv-ng,可以看到如图所示的内容。 图 在CMD下运行airserv-ng 参数解释: * -p,指定监听的端口,即提供连接服务的端口,默认为666; * -d,载入无线网卡设备,需要驱动支持; * -c,指定启动工作频道,一般设置为预攻击AP的工作频道,默认为1; * -v,调试级别设定。 Name Description aircrack-ng 破解WEP以及WPA(字典攻击)密钥 airdecap-ng 通过已知密钥来解密WEP或WPA嗅探数据 airmon-ng 将网卡设定为监听模式 aireplay-ng 数据包注入工具(Linux和Windows使用CommView驱动程序) airodump-ng 数据包嗅探:将无线网络数据输送到PCAP或IVS文件并显示网络信息 airtun-ng 创建虚拟管道 airolib-ng 保存、管理ESSID密码列表 packetforge-ng 创建数据包注入用的加密包。 Tools 混合、转换工具 airbase-ng 软件模拟AP airdecloak-ng 消除pcap文件中的WEP加密 airdriver-ng 无线设备驱动管理工具 airolib-ng 保存、管理ESSID密码列表,计算对应的密钥 airserv-ng 允许不同的进程访问无线网卡 buddy-ng easside-ng的文件描述 easside-ng 和AP接入点通讯(无WEP) tkiptun-ng WPA/TKIP攻击 wesside-ng 自动破解WEP密钥 作为Windows下的破解,第一步就是使用airserv-ng来载入我们当前使用的无线网卡,为后续破解做准备,命令如下(注意:在命令中出现的引号一律使用英文下的引号输入): airserv-ng -d "|debug" 或者 airserv-ng -d "| {my adapter id}" 输入完成后airserv-ng会自动搜寻现有无线网卡,会有提示,选择正确的无线网卡直接输入y,此时airserv-ng就在正常载入驱动后,同时开始监听本地的666端口。换句话说,airserv-ng提供的是该无线网卡的网络服务,其他计算机上的用户也可以连接到这个端口来使用这块网卡 步骤2:现在可以使用airodump-ng来搜索当前无线环境了。注意,要另开启一个CMD,再输入如下命令: airodump-ng :666 这里在IP地址处输入为本机即,端口采用的是默认的666。