@Autowire注入了bean(A)在当前类,但其他类需要调用这个A,报null异常,使用get获取bean为解决方案 问题背景解决方案心得Lyric: 远远抛开一切 问题背景 在做项目时,我在一个类中自动注入了A,另一个想通过当前类调用这个A,却出现null,感觉讲不清楚,我还是写一下错误示例
1 bean:B自动注入bean:A
@Service public class B{ @Autowired public A a; } 2 想在另一个类C中调用A,但我注入的是bean:B
@Service public class C{ @Autowired B b; public void getA(){ if( b.a != null ){ System.out.println("success"); } } } 3 但是这个结果是a为空,并没有被调用过来,查阅了一些资料
在普通Java类中使用service或者dao就会报空指针异常,因为这个普通类不在Spring的管理下,所以不能使用Spring来注入虽然现在不是普通类,b确实已经注入到C里面了,但a是注入在b中,由spring管理,a不属于b的属性,使用并不能直接被调用 解决方案 1 使用get方式去直接取a这个对象来使用,不通过spring获取
@Service public class B{ @Autowired A a; public A getA(){ return a; } } @Service public class C{ @Autowired B b; public void getA(){ A a = b.
前言 我们在很多开发中使用到python,但是有时候需要一些简单的UI界面作为辅助,这个时候qtpy就是上场的时候了!
说实话,qtpy用起来不如qt C++舒服。。。。。。
软件实现 作为界面开发,我是使用C++下面的一贯风格,一个main.py,一个界面py文件即mainwindow.py,
main.py负责主程序的加载,mainwindow.py负责主界面的加载。
main.py中就是比较简单,如下:
#!/usr/bin/python import sys from PyQt5.QtWidgets import QApplication from mainWindow import MainWindow if __name__ == '__main__': app = QApplication(sys.argv) ui = MainWindow() ui.show() sys.exit(app.exec_()) 然后界面又是在mainWindow.py中写一个MainWindow界面类,如果有其他各种界面也是在该类中加载。代码如下:
from PyQt5.QtWidgets import QWidget, QPushButton, QHBoxLayout, \ QVBoxLayout, QGridLayout, QMainWindow,QLineEdit,QFileDialog, \ QLabel,QProgressBar,QMessageBox import os import sqlite3 class MainWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.resize(600, 200) self.setWindowTitle('sqlite数据库操作程序') hLayout = QHBoxLayout() #水平布局 lab_filePath = QLabel('数据库路劲') self.lineEdit_filePath = QLineEdit(self.databaseName) button_selectFile = QPushButton('选择文件') button_selectFile.
link:How to downgrade Ubuntu to a previous version
link:How to dual boot through USB HDD
public class TestOperat { public static void main(String[] args) { /* 算术运算符: + - * / % */ System.out.println(5 + 2); System.out.println(17 - 9); System.out.println(5 * 8); System.out.println(9 / 3); /* + : 当+号左右两端出现一个字符串的时候,那么它执行的 是字符串拼接动作。 */ int result = 50; System.out.println("最终结果是:" + result); System.out.println("最终结果是:" + (3 + 7) ); /* % : 取模,取余 该符号是对左右两个操作数做除法,只不过最终结果不是商而是余数 特殊: 1、余数正负号,只跟第一个被除数有关; 2、%符号的运算只在整数运算下才有意义; */ System.out.println( 8 % 5); System.out.println(-8 % 5); System.out.println(8 % -5); System.out.println(-8 % -5); System.
debug时总进不了程序,心烦意乱鼠标不知道点了个啥,再运行程序就报这个错了
本来打算看视频的我关掉平板开始搞这个
找了好多解决办法都不太行
最终如下操作猛如虎,成功解决!
定位到报错的位置
至此,这个错误可以理解为找不到.dll文件了
解决办法:
dlls = glob.glob(os.path.join(th_dll_path, ‘.dll’))
改为
dlls = glob.glob(os.path.join(“D:\anaconda3\Lib\site - packages\torch\lib”, '.dll’))
也就是把其中的相对路径改为绝对路径
over
耶!
介绍 nvm是一个node.js的版本管理器,全程“node version manager”。使用nvm可以通过一个简单的命令快速安装、切换node.js版本。
安装 linux系统直接脚本运行安装即可。
官方安装教程请见:https://github.com/nvm-sh/nvm#installing-and-updating
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash windows系统需要安装nvm-windows,官方地址:https://github.com/coreybutler/nvm-windows
建议下载setup版本的安装程序:
https://github.com/coreybutler/nvm-windows/releases
下载以后运行安装即可。如果本机已经安装了node.js,安装过程中会提示是否需要让nvm管理已经安装的node.js,建议选择允许,把node.js交给nvm管理。
使用 终端直接输入nvm会显示帮助信息:
Running version 1.1.9. Usage: nvm arch : Show if node is running in 32 or 64 bit mode. nvm current : Display active version. nvm install <version> [arch] : The version can be a specific version, "latest" for the latest current version, or "lts" for the most recent LTS version. Optionally specify whether to install the 32 or 64 bit version (defaults to system arch).
如图,Android Studio中的button的颜色无法自己设定。
解决方法:
打开src–>main–>res–>values–>themes.xml
中的
parent=“Theme.MaterialComponents.DayNight.DarkActionBar”
换成
parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge" 这个样子
这样就解决问题了。
一.序列化流和反序列流的概述 二.ObjectOutputStream:对象的序列化流(重点) package com.itheima.demo07SerializableStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; /* java.io.ObjectOutputStream:对象的序列化流 作用:把对象以流的方式写入到文件中保存(在客户端和服务器之间发送对象) 构造方法: ObjectOutputStream(OutputStream out) 参数传递字节输出流 特有的成员方法: void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 使用步骤: 1.创建ObjectOutputStream对象,构造方法中传递FileOutputStream对象 2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中 3.释放资源 */ public class Demo01ObjectOutputStream { public static void main(String[] args) throws IOException { //1.创建ObjectOutputStream对象,构造方法中传递FileOutputStream对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\person.txt")); //2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中 oos.writeObject(new Person("小美女",18)); //3.释放资源 oos.close(); } } package com.itheima.demo07SerializableStream; import java.io.Serializable; /* 使用序列化流写对象的时候,程序抛出了NotSerializableException:没有序列化异常 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。 Serializable被称之为标记型接口 类实现了Serializable接口,那么Serializable接口就会给类添加一个标记(序列号) 当我们进行序列化|反序列化的时候,会检查类上是否有这个标记 有:进行序列化和反序列化 没有:抛出NotSerializableException异常 */ public class Person implements Serializable{ private String name; private int age; public Person() { } public Person(String name, int age) { this.
麻烦点个赞 今天在学习过程中遇到了将字符串转为数组的问题,
以下是解决方案
如果数据格式正确(数据已经被放到数组里了)的话直接一行代码就能解决直接改变类型就可以,你的代数据如果直接长这个样子那就直接运行下面那一行代码
import numpy as np a=a.astype(float) 但是我们拿到数据往往不那么规则,比如这次我拿到的数据就是长这个样子
看起来有点像,但是如果你直接引用上面的代码你会发现报错,有不能够转换为float的,因为里面有空格首尾,中间都有。
所以我们的思路就是把格式改成第一种情况再按照第一种情况的解法解决
a=data.iloc[0].strip() #消去首尾空格 a=a.replace("\n","") #删除出现的换行符 a=a.replace(" ","") #图中间隔是三个个空格隔开的所以第一个是两个空格,既删掉两个保留一个(如果不是的话根据需要修改就可) a=a.split(" ") #把他们根据那保留的一个空格分开并装上”“的帽子 a=np.array(a) #转为数组 a=a.astype(float) 总结:
这只是一个简单的举例具体还要根据你自己的数据来定,但是思路相同,利用那几个函数变换成我们想要的形式,再解决问题。
传送门:Vue中 子组件向父组件传值 及 .sync 修饰符 详解
传送门:Vue状态管理器(vuex)详解及应用场景
传送门:Vue中 $ attrs、$ listeners 详解及使用
传送门:Vue中 provide、inject 详解及使用
Vue中 常见的组件通信方式可分为三类 父子通信 父向子传递数据是通过 props,子向父是通过 events($emit); 通过父链 / 子链也可以通信($parent / $children); ref 也可以访问组件实例; provide / inject; $attrs/$listeners; 兄弟通信 Bus; Vuex; 跨级通信 Bus; Vuex; provide / inject、 $attrs / $listeners、 1. 简介 Vue 组件中常见的有:父子组件通信、兄弟组件通信。而父子组件通信就很简单,父组件会通过 props 向下传数据给子组件,当子组件有事情要告诉父组件时会通过 $emit 事件告诉父组件。
今天就来说说,如果两个页面没有任何引入和被引入关系,该如何通信呢?
如果应用程序不需要类似 Vuex 这样的库来处理组件之间的数据通信,就可以考虑 Vue 中的事件总线 ,即 eventBus 来通信。
eventBus 又称为事件总线。在 Vue 中可使用 eventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件。但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的 Vuex 作为状态管理中心,将通知的概念上升到共享状态层次。
文章目录 环境介绍原理官方解释白话版: 实现一、创建数据库一、主库操作 从库配置常见错误处理从库启动主从查询状态出现异常情况1:(从库查看运行状态出现Slave_IO_Running: No)情况2:(从库查看运行状态出现Slave_SQL_Running: No)开始解决问题(从库操作)关于其他错误MySql常见错误码 mysql主从复制常用命令创建用户相关权限相关 End; 环境介绍 提示:为方便新手与演示,本人使用宝塔面板进行环境快速搭建(与使用命令行搭建无异,仅文件位置可能稍有不用,不影响开发)
主库开发环境:Linux+ContOS7+MySql8+php7(主)
从库A开发环境:Linux+Ubuntu 20.04.1 +MySql8+php7(从A)
从库B开发环境:Linux+Ubuntu 20.04.1 +MySql8+php7(从B)
服务器数量3台(服务器数量至少>=2台)
原理 官方解释 1)主库master将数据的改变记录到binlog二进制日志中,
2)从库slave会在一定时间间隔内对主库master中的二进制文件进行检测是否发生改变,
如果发现主库master二进制文件有改变则从库slave会开始I/OThread线程请求主库master二进制事件
3)同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存在从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。
白话版: 主库master有个binlog二进制日志用来记录主库master上的数据改变。从库slave有2线程,一个是I/O线程,一个是SQL线程。从库的I/O线程会在一定时间间隔内主动请求主库的binlog主库被请求后生成一个log dump线程用来给从库的I/O线程传binlog从库将得到的binlog存在自己本地的relay-log(中继日志)文件中从库SQL线程会读取relay-log(中继日志)文件,并将内容解析成sql语句在从库上重新执行一遍这就完成了主从复制的过程End 实现 情景:搭建一主多从
主库公网ip:39.103.299.01
从库公网ip:115.28.137.02
一、创建数据库 在主服务器上创建数据库,将创建好的数据库文件备份。
2.在从库上创建数据库,并将主库的数据被备份在从库上导入。(目的:保证主从2个数据库是完全一致)
不导入也可以,不过有时会因为在主库新建表格,从库并没有自动创建,此时插入数据从库数据库日志会报错,导致主从复制关系失效!
一、主库操作 使用root权限登录主库mysql
mysql -u root -p 主库创建mysql用户,可以将用户设置为所有人都能访问,也可以设置成指定从库ip访问。
2.1 创建所有人都能访问mysql用户并设置密码create user '用户名'@'%';
#创建用户rootslave并设置为设备都可登录 create user 'rootslave'@'%'; 2.2为新用户设置密码set password for '同户名'@'host'='新的密码';
这里的host只有3种分别为 %(所有ip)、localhost(本服务器)、指定的服务器ip(如158.652.30.145)
#将用户rootslave的密码设为qwe123 set password for 'rootslave'@'%'='qwe123'; 2.3位新创建的用户设置权限grant replication slave on *.* to '用户名'@'从服务ip(host)';
注意:我们不在这里设置同步的具体数据库名和数据库表,而是在mysql配置文件中进行设置,所以照这个命令敲即可!
背景 spring shedlock用于在分布式服务的情况下执行定时任务,例如定时删除数据库中的一些数据,做数据迁移等等操作。这项技术在项目的分布式服务中大量使用。
使用的主要原因有以下几点:
定时任务的业务需要,要在服务service正常运行的过程当中同时在背后执行一些操作,满足我们的业务需要,定时任务也就是schedule task必不可少。分布式服务的要求。试想下面一个场景: 随着业务增长,有一天单个服务service的压力过大,一个服务支撑不住了,我们要考虑部署多个服务来分散压力。这时问题就来了,之前的定时任务,在各个服务上全都会跑,做着同样的事情,并且还会造成一些并发问题。这必然不是我们想要的结果,这时我们就会发现,虽然有多个服务,但是我们只能让这样的定时任务执行一次. 这时就可以考虑通过数据库来控制任务。因为多个服务的数据库依然是同一个。 用法配置 以postgres为例,我们可以按如下方式使用shedlock
首先我们需要引入对应的依赖:
<!-- shed lock --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>${schedlock.version}</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>${schedlock.version}</version> </dependency> 然后我们需要创建一张shedlock需要用来存储scheduler lock信息的table
CREATE TABLE shedlock ( name VARCHAR(64), lock_until TIMESTAMP(3) NULL, locked_at TIMESTAMP(3) NULL, locked_by VARCHAR(255), PRIMARY KEY (name) ) 通常,我们以锁的名字作为表的主键即可.
然后我们需要配置LockProvider, 使得访问数据库的时候使用shedlock
@Configuration @EnableScheduling @EnableSchedulerLock(defaultLockAtMostFor = "30s") public class SchedulerConfiguration { @Bean public LockProvider lockProvider(final DataSource dataSource) { return new JdbcTemplateLockProvider(dataSource); } } 有了以上配置之后我们就可以创建task了.
一、使用 IDEA 打开项目 二、打开设置安装插件 MavenHelper 三、安装完后点开 pom 文件,发现左下角有新的按钮 四、点击按钮 UI 弹出页面,可以清晰的看见maven 的依赖和冲突,也可以看到依赖树
ApiPost下载与安装 ApiPost = PostMan + Swagger + Mock 后端、前端、测试同时在线编辑,内容实时同步
下载 1.官网地址:https://www.apipost.cn/
2.官网支持客户端下载及web版的,可根据自己的需求选择适合自己的使用方式,本文介绍的是windows64位版本的客户端
安装 1.根据个人习惯,我首先会在盘符下面新建apipost文件夹,然后将apipost可执行文件放到此文件夹下;
2.双击可执行文件,默认选择“仅为我安装”, 点击“下一步”
3.选择安装路径,默认安装在C盘下,不建议安装在C盘, 然后点击安装;
4.出现以下界面,说明安装成功了
3.18 字节跳动(本地生活) 一面60min (部门做Golang的) 0.自我介绍,聊简历项目
1.说一下TCP和UDP的区别
2.TCP如何保障可靠传输
3.项目中用了多进程,那就聊下多进程和多线程
4.进程的状态,创建的整个过程
5.进程的调度算法: 抢占式,非抢占式,优先级调度)
6.分析下抢占式调度和非抢占式调度
7.聊mysql的索引
8.口述快排,进行复杂度分析
9.场景题,给4亿个整型数字,和2G物理内存,找出其中不重复的数字(想到用散列与布容过滤器,但了解不多没有展开说,答的不好)
10.算法题
有序数组中的单一元素
https://leetcode-cn.com/problems/single-element-in-a-sorted-array/
3.17 阿里ICBU一面 (30min)
1.自我介绍,聊简历项目
2.聊聊http(从http1.0聊到http3.0)
3.聊下tcp和udp
4.redis底层的数据结构(就知道有序列表中的zipList和skipList,还有字符串sds)
5.redis备份数据(说了用AOF和RDB,期间提了下binlog,后面就突然问数据库了)
6.聊下对Mysql中的数据结构的理解(聊了索引部分的数据结构,B+Tree和hash索引)
7.对websocket的理解
8.websocket的长连接和http1.1之后的长连接,之间区别
9.tcp如何保障可靠传输
10.反问环节
3.18 ICBU二面(50min)
0.自我介绍,聊简历项目
1.觉得自己笔试题做怎么样,之前没有模拟过吗
2.为什么想从算法转到搞后端
3.想考虑做开源吗
4.了解哪些阿里开源中间件(我说了RocketMQ,Dubbo,EasyExcel),然后面试官让我挑一个讲讲对这个产品认识,解决了什么问题,看过源码没(答的不好)
5.浏览器访问一个域名的全过程
6.说下http和https的区别
7.https如何保证安全传输,怎么加密的,底层机制
8.聊下ca证书
9.聊下TCP/IP的三层网络协议(网络层-传输层-应用层),每一层都详细说下
10.应用层你说到了DNS,聊下对DNS协议设计的看法,DNS域名解析过程
11.说下根域名服务器在哪里
12.除了websocket可以推消息给客户端,还了解哪些?
13.TCP如何保障可靠传输
14.你对Web安全的理解(聊了下对SQL注入,XSS,DDOS的看法)
15.项目中用到的多进程分块预测是怎么实现的
16.项目上线情况
17.遇到过什么线上问题,怎么排查
18.项目中你认为的难点
19.后面如果还接触这个项目,你怎么去做
20.平时怎么学习的,后面有什么规划
21.反问环节
背景
现阶段公司会进行季度的安全巡检,扫描出来的 Java 相关漏洞,无论是远程代码执行、还是 JNDI 注入,基本都和 Java 的序列化机制有关。本文简单梳理了一下序列化机制相关知识,解释为什么这么多漏洞都和 Java 的序列化有关,以及后续怎么避免这些安全漏洞,减少版本升级工作量。同时能基于本文的知识,在看到序列化漏洞后,简单评估该漏洞对自身应用的影响
为什么需要序列化
序列化主要是提供了一种机制,方便数据在网络之间进行传输,或者独立于程序存储在本地磁盘。
序列化的使用场景很广,比如服务器收到请求参数,一种处理方式是一个个解析数据,自己构建处理数据。还有一种就是直接将数据反序列化为对象。当要把对象存储到缓存时,我们可以自己解析对象生成数据保存到缓存,取出时也自己处理数据转换为对象,也可以直接借助语言的序列化机制帮我们将对象序列化为数据存储起来,从缓存里获取数据后直接反序列化转为对象。在这些场景里,很明显序列化机制能极大改善我们的编程体验
Java 序列化基础知识简述
最简单模式: implements Serializable
我们可以只实现序列化接口,让 Java 序列化机制会帮我们处理其他的一切事情
基于 Serializable 接口简单定制
可以用 transient 指定不想序列化的数据,比如密码等敏感数据
可以定义自己的 writeObject() 和 readObject() 方法,来自定义部分序列化和反序列化流程。注意这两个方法是私有的,却会被 Java 序列化机制自行调用
基于 Externalizable 接口全面定制
Externalizable 接口提供了两个在序列化/反序列化时自动调用的方法: writeExternal() 和 readExternal()
Serializable 对象的反序列化完全从其存储的字节位里构建,没有调用构造器。而 Externalizable 对象反序列化时,会调用公共无参构造器,之后 readExternal() 才调用。所以实现这个接口要提供无参构造器
Externalizable 对象默认不存储自身的任何字段,因此 transient 关键字仅适用于 Serializable 对象
序列化版本号 serialVersionUID
不管那种模式都自行定义版本号 serialVersionUID
如果我们不自行定义 serialVersionUID ,JVM 会根据自有的算法帮我们生成一个,这个算法是基于序列化类的字段、JVM 版本等等,这样可能导致即使类文件不变,升级 JDK 小版本都会导致反序列化失败
另外,修改方法、transient 字段、静态字段都不影响版本号,这些都不是序列化内容,因此也不是序列化版本号生成的依据
JVM 生成的版本号可以通过 jdk/bin/serialver 命令获取,假设想知道某个类在某个 jvm 里的默认序列化版本号,可以用这个命令,来进行迁移改造
iTOP-i.MX8M mini 核心板采用四核 Cortex-A53 架构,单核 Cortex-M4,多达五个内核,主频高达 1.8GHz,2G DDR4内存,8G EMMC 存储。拥有先进的 14LPC FinFET 工艺,提供更快的速度和更高的电源效率。核心板采用邮票孔封装,坚固可靠,8 层 PCB 沉金设计,彻底解决电磁兼容,并通过苛刻的 EMI 测试,192PIN CPU 功能全部引出,应用于各个行业都能得心应手。产品通过电磁兼容、电磁辐射标准检测、安规检测、高低温坏境检测等,确保产品的可靠性。
7*24 小时长期稳定运行。10 年以上供货周期长,批量无忧。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于通用工业和物联网和应用。
支持音频: PDM 接口、5 路 SAI 接口、2 路 Speaker。
系统支持: Android9.0、Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9 系统。
编解码: H564、VP8 视频硬编码,H.264、H.265、VP8、VP9 视频硬解码,最大支持 1080P 60fps,并提供相关例程。
PMIC: 采用 PCA9450A 电源管理,是 NXP 全新研制配套 IMX8M 的电源管理芯片,有 6 个降压稳压器、5 个线性稳压器和 1 个负载开关,为整个系统的稳定运行提供了更可靠的保证。
核心板参数:
尺寸: 50mm*50mm
CPU :NXP i.MX8M Mini
主频: 四核 Cortex-A53 主频 1.6GHz,单核 Cortex-M4 主频 400MHz 架构 四核 Cortex-A53,单核 Cortex-M4
总体思路 以往部署servlet项目都是部署在tomcat上,并且有一个全局的web.xml配置实现的servlet和filter过滤器,在这里我们自定义一个web.properties来代替web.xml;除此之外,我们需要做的呀Request和Response来处理http请求和响应,也要自定义servlet来处理http请求的相应后端业务逻辑,servlet与url的映射关系我们配置在web.properties中。
1、环境准备 自定义Servlet servlet抽象类
public abstract class AbstractServlet { public void service(MyRequest request, MyResponse response) throws Exception { if ("GET".equals(request.getMethod())) { doGet(request, response); } else { doPost(request, response); } } public abstract void doGet(MyRequest request, MyResponse response) throws Exception; public abstract void doPost(MyRequest request, MyResponse response) throws Exception; } servlet实现类MyFirstServlet
public class MyFirstServlet extends AbstractServlet { @Override public void doGet(MyRequest request, MyResponse response) throws Exception { this.doPost(request, response); } @Override public void doPost(MyRequest request, MyResponse response) throws Exception { response.
防火墙状态及规则 1、查看防火墙状态:firewall-cmd --state
[root@localhost ~]# firewall-cmd --state running [root@localhost ~]# 2、查看防火墙:firewall-cmd --list-all
[root@localhost ~]# firewall-cmd --list-all public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: dhcpv6-client http ports: 999/tcp protocols: masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: rule family="ipv4" source address="10.45.148.240" accept rule family="ipv4" source address="10.45.152.0/24" accept rule family="ipv4" source address="10.45.149.59" accept rule family="ipv4" source address="10.72.55.99" accept rule family="ipv4" source address="10.45.148.44" accept rule family="ipv4" source address="10.45.149.2" accept rule family="
版本:Android11
前言: 最近TV开发中遇到这么一个需求,添加一键进入谷歌浏览器,并进入指定的网址中。最开始在PhoneWindowManager中进行添加,但是添加完成后发现存在问题。每次进入浏览器都会打开一个浏览器窗口,按下次数多了会变得异常卡顿,后续将按键响应的流程放在PhoneFallbackEventHandler中进行处理之后便能解决这个问题,觉得较为奇怪,便准备查看一遍按键事件的分发流程,以理清整个的逻辑。
按键处理流程: 首先从PhoneWindowManager开始,按键从遥控器按下之后,经过一系列底层向上的传递工作之后,会来到PhoneWindowManager的interceptKeyBeforeDispatching方法和interceptKeyBeforeQueueing方法,在这里可以对按键进行初步处理,例如音量键,Home键,都是在这里处理。代码较长,这里就不贴了,大家可以自行去查看源码。在PhoneWindowManager中如果没有处理按键事件,那么按键会传入到ViewRootImpl。
frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java 在ViewRootImpl有三个内部类用于处理按键事件,分别是:
ViewPreImeInputStage,EarlyPostImeInputStage,ViewPostImeInputStage
这三个内部类的区别是ViewPreImeInputStage会在界面有输入法,且事件尚未发送给输入法的时候调用,EarlyPostImeInputStage会在发送给输入法之后调用,而ViewPostImeInputStage则是发送给View处理,我们的需求中没有出现输入法的地方,所以我们直接来看ViewPostImeInputStage类:
frameworks\base\core\java\android\view\ViewRootImpl.java /** * Delivers post-ime input events to the view hierarchy. */ final class ViewPostImeInputStage extends InputStage { public ViewPostImeInputStage(InputStage next) { super(next); } @Override protected int onProcess(QueuedInputEvent q) { if (q.mEvent instanceof KeyEvent) { return processKeyEvent(q); } else { final int source = q.mEvent.getSource(); if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { return processPointerEvent(q); } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) !
标准有每家公司自定义的也有公认的,下面我们来说一下标准的pts的模型,这个是给我自己看的,朋友有哪里不理解的可以咨询我 471938592
1.iops 对于(R/W混合%=100/0,95/5,65/35,50/50,35/65,5/95,0/100)对于(数据块大小=1024KB、128KiB、64KiB、32KiB、16KiB、,8KB、4KB、0.5KB)组合
2.吞吐量 吐量测试旨在测量稳态下顺序读/写(100/0,0/100)时两种块大小(128KiB和1024KiB)下的测试SSD吞吐量(TP)
3.延迟 PTS延迟测试旨在使用100%预处理和测试ActiveRange AR=100或AR=75,测量3个块大小(8KiB、4KiB和0.5KiB)和3个读/写混合(100/0、65/35、0/100)下的测试SSD响应时间
4.饱和写测试 运行以下测试刺激,直到写入4倍用户容量、6小时或5轮 记录平均IOPS、最大值、5 9秒和平均延迟2.2.3可选工作负载:
2.2.3.1 RND 4KB RW100(又名读密集型)
2.2.3.2 RND 4KB RW0(又称写密集型)
2.2.3.3 RND 8KiB RW65(又名混合或OLTP)
2.2.3.4 序列号128KiB RW90(又名VOD)
2.2.3.5 SEQ 0.5KB RW50(又名元数据)
5.主机空闲恢复 1. 对设备进行初始清洗,然后
2. 应用RND 4KiB,直到达到稳定状态,然后
一个周期——包括RND 4KB写入5秒,然后是无主机写入5秒——重复360次,然后是执行1800秒的连续RND 4KB写入,然后执行 RND 4KB写入5秒,然后是10秒无主机写入重复360次,然后执行1800秒的连续RND 4KB写入,然后执行RND 4KB写入5秒,然后是15秒无主机写入重复360次,然后过执行1800秒的连续RND 4KB写入,然后执行RND 4KB写入5秒,然后是25秒无主机写入重复360次,然后是执行1800秒的连续RND 4KB写入,。。。。。。然后执行包括RND 4KB写入5秒,然后是50秒无主机写入重复360次,然后是执行1800秒的连续RND 4KB写入。共计10给轮回
6.交叉刺激恢复 交叉刺激恢复(XSR)旨在观察测试SSD如何处理从大数据块顺序写入到小数据块随机写入以及返回到大数据块顺序写入的转换。
首先对设备进行清洗,然后为1024 KiB,写入时间为8小时。RND 8 KiB写入的序列,持续6小时,然后8小时的序列1024 KiB写入。
还有两个 觉得太难 或者有时候没必要
当我们已经获取了远程系统的凭证(明文密码或 hash)时,可以直接通过3389远程登录进去收集信息、进行下一步的渗透,但是这样做的话会在系统上留下我们的操作记录,而且有可能邂逅管理员。大部分情况下,一个cmdshell 已经可以满足我们继续渗透的需求,所以不到万不得已的时候最好不要远程桌面连接(mstsc),而是通过远程执行命令的方式继续开展工作。本文整理了一些远程执行命令的姿势,测试环境如下:
远程系统:
IP:192.168.17.138
用户名:Administrator密码:!@#123QWE所属本地组:Administrators
用户名:test密码:!@#123QWE所属本地组:Administrators、Users
关于 LocalAccountTokenFilterPolicy 的说明 在 Windows Vista 以后的操作系统中,LocalAccountTokenFilterPolicy 的默认值为0,这种情况下内置账户Administrator 进行远程连接时会直接得到具有管理员凭证的令牌,而非 Administrator 的本地管理员账户进行远程连接(比如 ipc 连接、wmi 连接)时,会得到一个删除了管理员凭证的令牌。域用户不受此影响,也不在我们讨论的范围内。也就是说只有 Administrator 账号才能建立需要管理员权限的远程连接,其他本地管理员账户建立需要管理员权限的远程连接时则会提示权限不足。可以通过以下方法修改远程系统上LocalAccountTokenFilterPolicy 条目的值,使得非 Administrator 的本地管理员建立连接时也可以得到具有管理员凭证的令牌,即可正常通过各种方式远程执行命令。
修改 LocalAccountTokenFilterPolicy 为1:
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
恢复 LocalAccountTokenFilterPolicy 为0(删除后需要重启 explorer.exe 才能使修改生效)
reg delete HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /f
net use + at 常用命令
建立一个 ipc 连接
net use \\192.168.17.138\C$ "!@#123QWE" /u:"workgroup\Administrator"
拷贝文件到远程系统上
copy s.exe \\192.168.17.138\c$\RECYCLER\
查看远程主机当前时间
net time \\192.
将Python代码转化为可执行的程序 如何将一段Python代码转化为通过点击就能运行的程序。分为以下几个步骤:
1.1 安装所需要的Python库 在Python中,将代码转成可以执行的程序需要安装库pyinstaller。本人的运行环境是macOS ,打开终端然后输入(如果是Windows用户,打开Anaconda Prompt),然后输入如下代码:
(/usr/local/anaconda3) liuxiaowei@MacBookAir python_exe % pip install pyinstaller 如果网速慢或者安装报错,可以使用下面的代码:
(/usr/local/anaconda3) liuxiaowei@MacBookAir python_exe % pip install --index-url https://pypi.douban.com/simple pyinstaller 1.2 对代码进行打包 安装完pyinstaller库之后就可以对代码进行打包, 首先将Python代码保存为**.py**格式的文件,放到一个文件夹内。例如写一个如下代码的小程序:
import os os.mkdir(os.getcwd() + 'test_file') # 在当前文件夹下建立一个test_file文件夹 将此程序保存到指定文件夹,文件格式为.py。然后在Anaconda的环境下进入终端命令,如下图:
然后输入如下命令:
(/usr/local/anaconda3) liuxiaowei@MacBookAir python_exe % pyinstaller -F mkdir_code.py 程序运行之后,该文件中除了mkdir_code.py文件之外,又多了几个文件,打包好的程序就在dist文件夹中,如下图:
进入dist文件夹,然后双击这个dist文件夹里的**.exe**文件,就可以看到新增加一个文件夹。
++i和i++的区别 ++i和i++的区别++ii++ Code ++i和i++的区别 ++i ++i:操作符在变量之前,先进行自身运算(i+1的操作),再进行其他运算,也就是加法的运算。 i++ i++:操作符在变量之后,先做其他运算(这里不能执行i+1的操作)只能先做加法运算,再进行自身运算(i+1的操作)。 Code 如上图所述:
a=i++的值为1,(i++是先进行加法运算,再进行自身i+1,返回值是i)因为要先进行加法运算,已知i本身为1,所以返回值a=i=1,完成a=i=1以后,i自身再进行+1,所以这里i=2,但是a=i=1已经成功赋值了,所以这里的a不等于2,而等于1b=++i的值为3,(++i是自身i先+1,再进行加法运算,返回值是i+1)由前面可以知道此时的i已经等于2了,因为i自身先+1,所以此时的i=3,再进行加法运算,所以b=3所以a+b=4
Vue指令02——v-on指令和v-show的使用 v-on指令 格式1:v-on:事件=”方法“
格式2:@事件=”方法“
格式3:@事件=”方法(参数1,参数2)“ //把参数传到到方法中
格式4:@键盘事件 . 键盘的键名称=”方法“ //按下指定键才触发
作用:为元素绑定事件
v-on的实例(格式1-格式2) 效果:鼠标单击小明,增加”小妹“,鼠标移入div,出现弹窗。
<div id="app"> <!--鼠标移入事件,调用greens方法--> <div style="background-color:bisque; width:100px; height:100px" v-on:mouseover="greens">第一个div</div> <!---鼠标单击事件,调用changeName方法--> <h2 @click="changeName">{{name}}</h2> <div> <script> var ap1=new Vue({ el:"#app", //获取id为app的元素和它的子元素 data:{ //写数据的地方 name:"小明" } , methods:{ //写方法的地方 greens:function(){ //弹窗方法 alert("鼠标移入的div") }, changeName:function(){ //增加小妹的方法 this.name+="小妹" } } }) </script> v-on的实例(格式3-格式4) 效果:单击按钮把事件里的参数传到到方法中输出,在文本框里输入东西,只有按下回车键才弹出弹窗。
<div id="acc"> <button @click="ts('小明',6666)">按钮</button> <input type="text" @keyup.Enter="rm"> </div> <script> var info=new Vue({ el:"#acc", data:{ }, methods:{ ts:function(p1,p2){ console.log(p1); console.
目录 一、为什么要进行app逆向?
二、了解apk目录
三、JVM、DVM、ART虚拟机的区别
一、为什么要进行app逆向? 1.为什么要进行app逆向?
比如你看到别人写的某个程序能够做出某种漂亮的动画效果,通过反汇编、反编译和动态跟踪等方法分析出其动画效果的实现过程这种行为就是逆向工程。
2.什么是软件逆向?
软件逆向也叫逆向工程,英文名是reverse engineering,大意是根据已有的东西和结果,通过分析来推导出具体实现方法。
3.逆向工程的应用
辅助软件开发安全研究病毒分析漏洞挖掘。 二、了解apk目录 apk就是一个压缩包,运行在Android上的文件。如果我们打开apk压缩文件,apk基本目录是这样的:
assets目录:静态资源目录,一些图片和静态数据或者icon等等。不会被编译,可以直接用鼠标打开的;
lib目录:放一些依赖库,第三方库的,还有开发人员开发的,格式为so文件;
META-INF目录: 信息描述,apk签名(做验证)等用途;
res目录:工程的资源文件,会被编译。一些重要的资源文件会存放到该目录;
AndroidManifest文件:(需要反编译) 用来做组件查找。安卓程序启动的时候例如需要什么权限,什么页面等等比较重要;
classes.dex文件: 虚拟机执行的文件。
resources.arsc: 资源文件索引。
三、JVM、DVM、ART虚拟机的区别 了解:
JVM虚拟机运行的是.java文件编译后的.class文件。Dalvik虚拟机是在Android4.4之前使用的虚拟机,运行的是.dex文件。apk在打包过程中先将java通过javac编译成.class文件,然后dx将.class文件转成.dex文件供DVM虚拟机运行。ART虚拟机是Android5.0后使用的Android虚拟机。兼职Dalvik虚拟机的特性。 注意:
Xposed hook的是java代码,87版Xposed不支持5.0以上版本,89版本Xposed是安卓5.0-7.1
Nintechnet 是一款非常出色的Wordpress网站安全防护插件,从某种意义上来说,它的安全防护能力可以媲美wordfence这款安全防护插件。
一、 Nintechnet简介
Nintechnet 防火墙插件一共有2个版本,一共是免费的,一共是付费的,我们今天要讲的是付费版的操作!下面我简单的罗列一下免费版本和付费版本之前的区别:
Unix共享内存用于进程间通信:这个特性要求PHP是用–enable shmoo参数编译的。如果您的服务器不兼容(例如基本虚拟主机帐户),您仍然可以像往常一样安装和运行Nintechnet防火墙响应正文过滤器(Web过滤器)可在将HTML页面的输出发送到访问者浏览器之前对其进行扫描IP地址和AS号访问控制限速选项基于国家的访问控制(地理位置)URL访问控制用户输入访问控制机器人访问控制集中式日志记录,一次安装即可远程访问所有受Nintechnet保护的网站的防火墙日志Syslog日志记录(与Fail2Ban兼容)反垃圾邮件评论和用户注册表格 以上这11项功能,是免费版本所不具备的,只能在付费版本中进行使用。至于正版收费的价格,单一域名网站每年收费49美金,如果是2-5个域名使用,那么每个网站每年收39美金。同理,使用的网站数量越多,价格也越便宜,最便宜的版本是29美金每年,网站使用数量是100+起步!
二、Nintechnet 的安装和使用
Nintechnet 插件一共提供了11个菜单功能选项,我们逐个来看这些菜单功能,
Dashboard(仪表盘)
这个功能没什么特别好讲的,因为破解版安装之后,对应的验证令牌对应不上,所以就报错提醒了。
在“Statistics”中,是当前这个月所统计的阻止的安全威胁和遭受的安全威胁等级。
“License”就是付费版本的令牌验证的地方,当你购买正版的 Nintechnet 之后就会获得一个验证令牌,然后在License中输入该验证令牌即可激活付费版本的功能。
“About”指的就是该插件的相关版本和信息,没什么好讲的,略过。
Firewall Options(防火墙选项)
Firewall protection(防火墙保护功能):开启
Debugging mode(调试模式):禁用
Use shared memory(使用共享内存):禁用
HTTP error code to return(HTTP错误代码返回):页面错误返回代码,一般用403,也可以设置成404,406,500等报错代码
IP anonymization(IP匿名):禁用
Blocked user message(屏蔽用户所看到的页面信息):可以自己设置,有可以用插件默认的提示信息。
Firewall configuration(防火墙配置):这里强调的是防火墙配置规则的导入和导出功能(让你节省时间,一个网站设置好之后可以在其他网站上启用相同规则而不用重新配置规则)
Miscellaneous(其他杂项):自定义设置仪表盘小部件上显示的安全消息数量
Fire Policies(防火墙政策)
防火墙政策分为三个等级,分别是:Basic Policies、Intermediate Policies、Advanced Policies,一般的同学建议之要操作Basic Policies就可以了,有相关知识储备和技术基础的同学可以尝试操作后面两个等级的功能设置。下面我们来看具体的操作(因为截图所实在太麻烦了,同学们还是自己去看图操作,我这里就只用文字描述了)
HTTP / HTTPS:这里指的是Nintechnet安全管控的流量来源,建议http和https一起选择。
以上就是WordPress网站安全防护插件Nintechnet的全部内容。
Cookie是什么 cookie的中文翻译是曲奇,小甜饼的意思。cookie其实就是一些数据信息,类型为“小型文本文件”,存储于电脑上的文本文件中。
Cookie有什么用 我们想象一个场景,当我们打开一个网站时,如果这个网站我们曾经登录过,那么当我们再次打开网站时,发现就不需要再次登录了,而是直接进入了首页。例如bilibili,csdn等网站。
这是怎么做到的呢?其实就是游览器保存了我们的cookie,里面记录了一些信息,当然,这些cookie是服务器创建后返回给游览器的。游览器只进行了保存。下面展示bilibili网站保存的cookie。
Cookie的表示 一般情况下,cookie是以键值对进行表示的(key-value),例如name=jack,这个就表示cookie的名字是name,cookie携带的值是jack。
Cookie的组成 下面我自己写了一个简易Servlet来设置cookie,我们游览器抓包进行查看。然后进行分析
以下是cookie中常用属性的解释。
Name:这个是cookie的名字Value:这个是cooke的值Path:这个定义了Web站点上可以访问该Cookie的目录Expires:这个值表示cookie的过期时间,也就是有效值,cookie在这个值之前都有效。Size:这个表示cookie的大小 想要完全了解所有cookie属性,请参考百度知道:cookie
Cookie的HTTP传输 我们还是通过抓包进行查看。首先查看cookie在HTTP请求中是怎样进行表示的。
HTTP请求
我们在发送HTTP请求时,发现游览器将我们的cookie都进行了携带(注意:游览器只会携带在当前请求的url中包含了该cookie中path值的cookie),并且是以key:value的形式进行表示的。多个cookie用;进行隔开。
我们再来查看cookie在HTTP响应中是如何进行表示的。
HTTP响应
我在服务器设置了2个cookie,返回给游览器。通过抓包,我们发现在HTTP响应中, cookie的表示形式是,Set-Cookie:cookie的名字,cookie的值。如果有多个cookie,那么在HTTP响应中就使用多个Set-Cookie进行表示。
Cookie的生命周期 cookie有2种存储方式,一种是会话性,一种是持久性。
会话性:如果cookie为会话性,那么cookie仅会保存在客户端的内存中,当我们关闭客服端时cookie也就失效了持久性:如果cookie为持久性,那么cookie会保存在用户的硬盘中,直至生存期结束或者用户主动将其销毁。 cookie我们是可以进行设置的,我们可以人为设置cookie的有效时间,什么时候创建,什么时候销毁。
Cookie使用的常见方法 下面,我对java中Cookie对象的方法进行讲解
new Cookie(String name, String value):创建一个Cookie对象,必须传入cookie的名字和cookie的值getValue():得到cookie保存的值getName():获取cookie的名字setMaxAge(int expiry):设置cookie的有效期,默认为-1。这个如果设置负数,表示客服端关闭,cookie就会删除。0表示马上删除。正数表示有效时间,单位是秒。setPath(String uri):设置cookie的作用域 HttpServletRequest和HttpServletResponse对Cookie进行操作的常见方法
response.addCookie(Cookie cookie):将cookie给客户端进行保存resquest.getCookies():得到客服端传过来的所有cookie对象 Cookie应用实例 我们使用cookie来实现一个功能,就是当用户登录成功后,我们在下次登录时就自动填入用户名和密码。这个功能我们使用cookie和jsp页面来完成(用html页面也可以,只不过要使用javascript,有点麻烦,所以就使用jsp进行演示)
我们首先写一个简单的jsp页面,就是一个登录页面
JSP页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>登录</title> </head> <body> <form action="${pageContext.request.contextPath}/main" method="post"> 用户名:<input type="text" name="username" value="<%=request.getAttribute("username")%>"><br/> 密 码:<input type="password" name="password" value="<%=request.getAttribute("password")%>"><br/> <input type="submit" value="登录"> </form> </body> </html> 请求转发页面,我们是通过访问Servlet转发到jsp页面的,而不是直接访问。
文章目录 前言一、为什么需要地图初始化?二、多视图几何基础1.对极约束示意图2.H矩阵求解原理3.哪个奇异向量是最优解?3.求解基础矩阵F4.SVD5.单目投影恢复3D点 三、 卡方检验1.为什么要引用卡方检验?2.卡方分布假设检验步骤?3.ORB-SLAM2中的卡方检测剔除外点策略 四、单目SFM地图初始化1.为什么要归一化?2.具体归一化操作3.检查位姿的有效性 五、 双目地图初始化:稀疏立体匹配1.双目相机2.稀疏立体匹配原理3.亚像素插值 前言 迎浏览我的SLAM专栏,包括slam安装运行、代码注释、原理详解,一起加油淦穿SLAM。
一、为什么需要地图初始化? 在ORB-SLAM2中初始化和使用的传感器类型有关,其中单目相机模式初始化相对复杂,需要运行一段时间才能成功初始化。而双目相机、
RGB-D相机模式下比较简单,一般从第一帧开始就可以完成初始化。
为什么不同传感器类型初始化差别这么大呢?
我们从最简单的RGB-D相机初始化来说,因为该相机可以直接输出RGB图像和对应的深度图像,所以每个像素点对应的深度值是确定的,也
就是说,我在第一帧提取了特征点后,特征点对应的三维点在空间的绝对坐标是可以计算出来的(需要用到内参)。
对于双目相机来说,也可以通过第一帧左右目图像立体匹配来得到特征点对应的三维点在空间的绝对坐标。因为第一帧的三维点是作为地图
来实现跟踪的,所以这些三维点我们也称为地图点。所以理论来说,双目相机、RGB-D相机在第一帧就可以完成初始化。
而对于单目相机来说,仅仅有第一帧无法得到三维点,想要初始化,需要像双目相机那样去进行立体匹配。
二、多视图几何基础 1.对极约束示意图 2.H矩阵求解原理 等式左边两项分别用A, X表示,则有:
AX = 0
一对点提供两个约束等式,单应矩阵H总共有9个元素,8个自由度(尺度等价性),所以需要4对点提供8个约束方程就可以求解。
3.哪个奇异向量是最优解? 为什么VT的第9个奇异向量就是最优解?
Ah=0 对应的代价函数
最优解是导数为0
问题就转换为求ATA的最小特征值向量
可见 的特征向量就是 的特征向量。因此求解得到V 之后取出最后一行奇异值向量作为f的最优值,然后整理成3维矩阵形式。(其实其他行的奇异值向量也是一个解,但是不是最优解)
3.求解基础矩阵F 推导F矩阵约束方程
4.SVD SVD分解结果
假设我们使用8对点求解,A 是 8x9 矩阵,分解后
U 是左奇异向量,它是一个8x8的 正交矩阵,
V 是右奇异向量,是一个 9x9 的正交矩阵, 是V的转置
D是一个8 x 9 对角矩阵,除了对角线其他元素均为0,对角线元素称为奇异值,一般来说奇异值是按照从大到小的顺序降序排列。因为每个
奇异值都是一个残差项,因此最后一个奇异值最小,其含义就是最优的残差。因此其对应的奇异值向量就是最优值,即最优解。
VT中的每个列向量对应着D中的每个奇异值,最小二乘最优解就是VT对应的第9个列向量,也就是基础矩阵F的元素。这里我们先记做
Fpre,因为这个还不是最终的F。
F矩阵秩为2
基础矩阵 F 有个很重要的性质,就是秩为2,可以进一步约束求解准确的F
上面的方法使用 对应的第9个列向量构造的Fpre 秩通常不为2,我们可以继续进行SVD分解。
其最小奇异值人为置为0,这样F矩阵秩为2
此时的F就是最终得到的基础矩阵。
Apollo配置加载以及改动动态加载 实现 使用@ApolloConfigChangeListener+RefreshScope实现动态加载。
@ApolloConfigChangeListener注解,基于事件监听。使用该注解将会自动注册ConfigChangeListener,监听到Apollo的配置修改。
RefreshScope实现spring刷新配置。
代码 @Component public class ApolloRefreshListener { @Resource private RefreshScope refreshScope; @Resource private XxxProperties xxxProperties; // value是配置的命名空间,interestedKeyPrefixes是配置的前缀名 @ApolloConfigChangeListener(value = "xxx.yml", interestedKeyPrefixes = {"xxx."}) private void cacheRefresh(ConfigChangeEvent changeEvent) { // 刷新配置类,重新获取配置数据 refreshScope.refresh("xxxProperties"); // 接下来可以开始做业务,对一些对象开始修改 } } 额外 yaml配置集合
object: map: {"key":"value","key1":"value1"} list: ["str1","str2"] spring加载
@Data @Configuration @ConfigurationProperties(prefix = "object") public class ObjectProperties { private Map<String, String> map; private List<String> list; }
在pycharm运行程序报错,ModuleNotFoundError: No module named ‘pytest’
搜了一下,原来是命名的问题,py文件命名为test_xxx.py,应该是test_开头的文件会调用pytest模块启动,然后文件缺乏某些语句或参数导致的。
解决方案:
将文件名改为test1_xx.py就可以正常运行了。
最近有很多朋友私信问我软考考试多少分才算通过呢?刚好在这里看到了相关问题,就跟大家详细说说软考考多少分才能拿到证书!
首先我们需要知道软考一共是有27个考试资格设置的,分为初、中、高三个级别。
其中,初级和中级需要参加两门科目的考试,而高级需要参加三门科目的考试,具体内容如下:
不管是初级还是中级或者是高级,每一科考试满分都是75分,按照国家相关政策规定,各科目合格标准需要达到总分的60%,也就是说软考每一科考试都要有45分才算合格。
所以,不管你是考软考哪个级别的考试,每科考试必须要达到45分才算合格,才能拿到软考证书。
下面是一些关于软考分数的相关问题,在这里也做一个解答:
1.如果我这一次考试只有一科没有达到45分,那下次考的时候还需要考其他科目吗?
答:当然是需要考的。软考相关政策规定,每个级别资格考试的各科目均及格才算合格,且单科及格的成绩不予保留,不能转到下次考试时使用。
2.软考每年的合格分数线都是固定的吗?
答:软考每年的合格分数线并不是固定的,但一般合格分数线都在45分左右,只有极少数情况下合格分数线才有变化。
3.软考论文成绩可以申请复查吗?
答:一般来说,软考论文成绩是可以申请复查的,但是流程比较复杂。根据往年软考申请成绩复核的结果来看,不会有太大改变。注意:部分地区可能不支持成绩复核,但有些地区可以申请,所以具体要咨询当地的软考办,看是否能申请软考论文成绩复议,如果可以的话需要了解清楚具体的流程再进行申请。
好啦,大概就这些内容了,如果大家还有其他的关于软考分数的问题可以留言哦,看到了会进行解答
解决 webstorm nodejs 在使用 require 的时候出现下划曲线,没有代码提示的问题 问题 如图,在 webstorm 中写 nodejs 脚本的时候, require 出现下划曲线提示,并且没有代码提示
解决办法 如果你的系统中已经安装了 nodejs 和 npm
打开设置,Languages & Frameworks -> Nodejs 将 Coding assistance for Node.js 勾选上即可
不需要往: JavaScript -> Libraries 添加 nodejs
结果 下划曲线没有了,代码也有提示了
我白嫖过的一些云厂商:
云厂商学生优惠新人优惠腾讯云学生特惠,1核2G5M宽带,仅需9元/1个月星星海SA2云服务器,1核2G首年99元(我目前用的)新客户无门槛代金券,价值高达2860元代金券云产品限时秒杀,爆款1核2G云服务器,首年99元阿里云精选云服务器1核2G 新人仅需87元/年百度云1核2G 学生身份 9 元/1个月华为云精选云服务器2折起七牛云对象存储服务每月10GB免费空间 (用做云存储)青云https://www.qingcloud.com 以上是答主我从学生时代到打工人薅过最便宜的云服务器,建议大家有学生身份或者新用户身份的都去试试。
在配置服务器环境的时候,需要下载很多东西,比如你要安装jdk,你可以使用yum命令;也可以使用ftp工具把预先下载的.gz 压缩包上传到服务器,然后解压安装。
1、配置jdk 有两种安装方法,我使用的是第二种安装方式。
yum安装 查看可用版本:
yum -y list java [root@VM-8-8-centos software]# yum -y list java* Loaded plugins: fastestmirror, langpacks Determining fastest mirrors Available Packages java-1.6.0-openjdk.x86_64 1:1.6.0.41-1.13.13.1.el7_3 os java-1.6.0-openjdk-demo.x86_64 1:1.6.0.41-1.13.13.1.el7_3 os java-1.6.0-openjdk-devel.x86_64 1:1.6.0.41-1.13.13.1.el7_3 os java-1.6.0-openjdk-javadoc.x86_64 1:1.6.0.41-1.13.13.1.el7_3 os java-1.6.0-openjdk-src.x86_64 1:1.6.0.41-1.13.13.1.el7_3 os java-1.7.0-openjdk.x86_64 1:1.7.0.261-2.6.22.2.el7_8 updates java-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.261-2.6.22.2.el7_8 updates java-1.7.0-openjdk-demo.x86_64 1:1.7.0.261-2.6.22.2.el7_8 updates java-1.7.0-openjdk-devel.x86_64 1:1.7.0.261-2.6.22.2.el7_8 updates java-1.7.0-openjdk-headless.x86_64 1:1.7.0.261-2.6.22.2.el7_8 updates java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.261-2.6.22.2.el7_8 updates 选择你要的版本:
yum install -y java-1.
内部直接或者间接调用了terminate函数或者abort函数,terminate函数内部也是默认调用了abort函数。 C++异常处理之terminate函数 C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决不了,再传给其上一级,由其上一级处理。如此逐级上传,直到最高一级还无法处理的话,运行系统会自动调用系统函数terminate,
学会使用terminate函数有助于异常处理
一 当一个异常产生的时候调用terminate函数,代码:
[cpp] view plaincopyprint?
#include <iostream> #include <exception> using namespace std; void on_terminate(){ cout<<"terninate function called!"<<endl; cin.get(); } int main(void){ set_terminate(on_terminate); throw exception(); cout<<"terminate function not called!"<<endl; cin.get(); return 0; } terminate被调用的情况:
1 当发送一个异常,并且构造函数产生异常
2 当发送一个异常,或者析构函数产生异常
3 一个静态对象的构造或者析构发送一个异常
4 以atexit注册的函数发生异常的时候
5 自定义一个异常,但是实际上没有异常产生的时候
6 调用缺省的unexcepted()函数时候
例子说话:
[cpp] view plaincopyprint?
#include <iostream> #include <exception> using namespace std; void on_terminate(){ cout<<"terminate function called!"<<endl; cin.get(); } class custom_exception{ custom_exception(){ } custom_exception(const custom_exception& excep){ throw exception(); } }; void case_1(){ try{ throw custom_exception(); } catch(.
一、算法思路:
本节主要为最近公共祖先,算法利用的为递归的方式,总体思路就是先从根节点出发,然后判断根节点的子节点是否包含需要寻找最近公共祖先的左右节点,如果包含的话则往下一层继续寻找,具体的思路可以分成如下几步:
先判断根节点是否为空,如果为空的话即返回空 在判断根结点是否为左右节点的其中一个,如果是,那么这个根节点就必为最近公共祖先 如果不满足1,2说明最近公共祖先在根节点的左右子树中,因此分别递归遍历根节点的左右子树
Treenode left=lowestCommonAncestor(root.left,p,q);
Treenode right=lowestCommonAncestor(root.right,p,q); 如果左右子树都不为空,说明待求的左右节点分别分布在左右子树中,因此这个节点就是最近的公共祖先
如果左右子树都为空,说明不存在最近公共祖先,所以要返回空
如果左子树或右子树为空,那么说明待求的左右节点包含在左子树或者右子树中,因此往左/右子树搜索即可 *参考链接:https://www.cnblogs.com/diShuiZhiYi/p/14465770.html
二、代码
/* * 本节主要为最近公共祖先,算法利用的为递归的方式,总体思路就是先从根节点出发,然后 * 判断根节点的子节点是否包含需要寻找最近公共祖先的左右节点,如果包含的话则往下一层继续寻找 * 具体的思路可以分成如下几步: * 1) 先判断根节点是否为空,如果为空的话即返回空 * 2) 在判断根结点是否为左右节点的其中一个,如果是,那么这个根节点就必为最近公共祖先 * 3) 如果不满足1,2说明最近公共祖先在根节点的左右子树中,因此分别递归遍历根节点的左右子树 * Treenode left=lowestCommonAncestor(root.left,p,q); * Treenode right=lowestCommonAncestor(root.right,p,q); * 4) 如果左右子树都不为空,说明待求的左右节点分别分布在左右子树中,因此这个节点就是最近的公共祖先 * 如果左右子树都为空,说明不存在最近公共祖先,所以要返回空 * 如果左子树或右子树为空,那么说明待求的左右节点包含在左子树或者右子树中,因此往左/右子树搜索即可 * *参考链接:https://www.cnblogs.com/diShuiZhiYi/p/14465770.html * */ public class _最近公共祖先 { static class TreeNode{ int val; TreeNode left; TreeNode right; TreeNode(int x) {val=x;} }; static TreeNode lowestCommonAncestor(TreeNode root,TreeNode left,TreeNode right) { if(root==null) return null; if(root==left||root==right) return root; TreeNode left1=lowestCommonAncestor(root.
1.问题的算例:就是问题参数的具体化。通俗来说,就是给参数赋值。
2.benchmark:就是求解问题算例的一个基准。比如获得的价值为7,这个最优解可以看成是该算例的一个Benchmark。
Benchmark概念的引出——只是为了方便我们对算法的效果进行一个对比。比如说小明同学选了第1个物品和第2个物品,获得的价值为1+4=5,那么小明就可以用他的解决方案和别人的benchmark进行对比。比如与最优的benchmark为7比较的话,显然小明的解质量是更差的,因为所获得的价值比较低。
以0-1背包问题为例,其实解就是0-1的全排列。
3.全排列函数
it.product(range(2), repeat=ins.N)——是生成N位的01全排列。
import itertools as it s = list(it.product(range(2), repeat=5)) print(s) # 输出结果 [(0, 0, 0, 0, 0), (0, 0, 0, 0, 1), (0, 0, 0, 1, 0), (0, 0, 0, 1, 1), (0, 0, 1, 0, 0), (0, 0, 1, 0, 1), (0, 0, 1, 1, 0), (0, 0, 1, 1, 1), (0, 1, 0, 0, 0), (0, 1, 0, 0, 1), (0, 1, 0, 1, 0), (0, 1, 0, 1, 1), (0, 1, 1, 0, 0), (0, 1, 1, 0, 1), (0, 1, 1, 1, 0), (0, 1, 1, 1, 1), (1, 0, 0, 0, 0), (1, 0, 0, 0, 1), (1, 0, 0, 1, 0), (1, 0, 0, 1, 1), (1, 0, 1, 0, 0), (1, 0, 1, 0, 1), (1, 0, 1, 1, 0), (1, 0, 1, 1, 1), (1, 1, 0, 0, 0), (1, 1, 0, 0, 1), (1, 1, 0, 1, 0), (1, 1, 0, 1, 1), (1, 1, 1, 0, 0), (1, 1, 1, 0, 1), (1, 1, 1, 1, 0), (1, 1, 1, 1, 1)] 4.
思路如下: 1、制作模板(建议写静态HTML,样式会好看些):按照导出的格式弄一个word文件,然后通过转换工具转成HTML,但是一般转换的会有一些问题,需要删除一些样式字体等
推荐一个在线转换(百度随便搜一下):在线WORD转HTMLhttps://cn.office-converter.com/Word-to-HTML-Converter
在样式中添加字体样式(重要),这是不乱码的关键一步
<style type="text/css"> body { font-family: "simsun"; } </style> 2、准备字体:simsun.tcc,在windows目录也有拷一个就行:C:\Windows\Fonts
3、在项目中导入相关的依赖,主要是Freemarker、itextpdf
<properties> <flying-saucer-pdf.version>9.1.16</flying-saucer-pdf.version> <itextpdf.version>5.5.13</itextpdf.version> </properties> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>${flying-saucer-pdf.version}</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>${itextpdf.version}</version> </dependency> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>${itextpdf.version}</version> </dependency>> 此处为核心:maven打包会压缩字体,需要排除一下
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>2.7</version> <configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>ttc</nonFilteredFileExtension> <nonFilteredFileExtension>html</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> <dependencies> <dependency> <groupId>org.apache.maven.shared</groupId> <artifactId>maven-filtering</artifactId> <version>1.3</version> </dependency> </dependencies> </plugin> 下面贴一下核心代码: 渲染模板、渲染PDF
package com.yx.exportpdfdemo.utils; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.
笔记的出发点:摘录了些自己觉得使用的建议。
类和接口 摘抄些关于类的设计的建议
类和成员变量的可访问性最小,通过public,protect,private控制。这也支持了java封装的特性。建议暴露公有类中的成员变量的访问方法而不是直接暴露成员变量减少类的可变性,因为他们不容易出错和更加安全。减少类的可变性的方法:不提供改变对象状态的方法;使用final保证类不被扩展;所有的域设置成final;确保可变的组件要互拆访问。组合优于继承 枚举类 阅读前的理解:使用枚举可以面的这些好处
枚举类可以用来代替静态变量来定义一些魔法值或者字符串清晰的定义业务的可选范围复用性好提供遍历枚举值的方法 int枚举模式的不足:
没有类型安全校验。比如商品上架状态为1,商品的商品类型为1,都可以用传的参数为int的接口中遍历一个业务场景下int的范围,不方便 书中介绍的优点:
类型安全校验,接口的参数定义成枚举型,可以类型安全校验。比如商品上架状态为1,商品的商品类型为1,都可以用传的参数为int的接口中。但是用枚举类就不能随意传。枚举中可以抽象方法,每个枚举中的都定义自己的实现。每个枚举都有个oridinal方法,它返回它在枚举中的位置,从0开始。因为它会随枚举对象的位置而变化,所以不能用它进行业务判断。 方法 自己可以想到的一些建议:
方法的职能要单一,名称要驼峰命名方法的参数不要太多 书中的建议:
方法的开头处,校验参数的有效性,防止程序计算过程中发生出乎意料的异常慎用重载,特别是当重载方法的参数列表长度一样,且重载的参数间存在继承关系。比如说下面的方法 public void a (List arg){ } public void a (Collection arg){ } 返回0长度的数组或者集合,而不是返回null。理由:调用方可能会忘记处理null值的返回,空集合对内存和性能的消耗很少。为方法编写注释。注释包含的部分:方法为什么要这么设计的理由,而不是对代码的简单称述,调用方法的前置条件(往往是受检的参数),可能的副作用比如:使用的es的查询接口,那么它的副作用是不能查询到实时的数据 通用设计 摘要一些代码书写方面的建议
将局部变量的作用域最小化,实践方式,在第一次用到它的地方进行声明。可以提升代码的可读性和可维护性使用for-each循环替代for循环,for循环需要引用索引取值,使用不慎可能会报数组越界的问题。for-each使用方法更加简洁,且性能不差如果需要精确的答案,请避免使用float和double,可以使用BigDecimal。需注意创建bigdecimal对象时传入double类型的数据也是不行的,如BigDecimal bigDecimal = new BigDecimal(0.01);这样构建出来的对象也是不准确的。如果有其他类型更合适,尽量避免使用字符串。数值,请使用数字型。若是“是”“否”这种可以使用布尔类型当心字符串连接的性能,特别是在for循环中拼接字符串,可以考虑使用stringBuilder代替通过接口引用对象,这样更灵活接口优于反射,反射机制设计的初衷是为基于组件的应用设计的,它会比普通的方法调用慢上几倍甚至几十倍。比如不要使用BeanUtils.copyProperties构建对象,会比较慢,首次构造的时间会在百毫秒级别。接受普遍的命名惯例。包名:小写,每个部分用句号分开;类名:驼峰,首字母大写;方法名:驼峰,首字母小写;变量名:驼峰,首字母小写;常量:所有字母大写,每个单词用下划线分开
1. @Deprecated 注解 @Deprecated: 用于表示某个程序元素(类,方法等)已过时如果使用 Deprecated 去修饰一个类,表示这个类已经过时了,但过时不代表不能用了,即不推荐使用,仍然可以使用 public class Deprecated_ { public static void main(String[] args) { A a = new A(); System.out.println(a.n1); a.hi(); } } @Deprecated class A { @Deprecated public int n1 = 10; @Deprecated public void hi() { System.out.println("hello 兮动人!"); } } 可以看到被 @Deprecated 修饰后,使用的时候就会有个横线划掉的标注,但依然可以正常输出
2. @Deprecated 的说明 用于表示某个程序元素(类,方法等)已过时可以修饰方法,类、字段、包、参数等查看源码
@Deprecated的作用可以做到新旧版本的兼容和过渡
抓包常用工具:
fiddler:windows平台最受欢迎抓包工具、免费、易用
charles:Mac平台下最佳抓包工具,易于使用,收费软件,可以一直使用
wireShark:老牌抓包工具,跨平台,功能齐全、强大
tcpdump:命令行程序,适用于手机系统和后台系统
身为互联网人,无论在平时开发还是在测试过程中,我们都不可避免的会涉及到网络安全性,如何监测网络请求,从而最大程度的保证数据的安全,需要我们了解并掌握抓包的技巧。那么何谓抓包呢?抓包就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等一系列操作,来进行检查网络是否安全。同时经常被黑客用来对数据进行截取,利用一些抓包软件可以很轻松的获得到你没有加密的一些数据,经过分析,然后会对你的行为进行攻击。所以,抓包对于我们维护信息的安全非常关键。
《Fiddler》 简介:Fiddler是运行于windows系统上的程序,用来处理HTTP,HTTPS协议。在我们工作中常见的主要是对我们移动端开发完成后,进行调试或者测试的时候,需要检查服务端与客户端的数据交互有没有实现,以及是否正确,我们会使用一些虚拟数据,假数据,设定的场景,来对我们的软件进行操作,就需要用到Fiddler抓包工具。
处理HTTP协议: 1.首先需要注意的是我们的移动端app必须保证和Fiddler的主机处于同一网络下
2.Fiddler选择开启远程连接,确认Fiddler代理主机的IP地址和端口号
进入Tools-->Options-->Connections-->勾选Allow remote computers to connect
默认监听的端口号8888()
3.在移动端设置网络代理为Fiddler主机,即Fiddler代理主机IP和端口号
选中网络对应的无线连接名称长按-->修改网络-->高级选项-->代理手动--填写代理IP地址和端口--保存
4.访问HTTP协议的网络地址
处理HTTPS协议: 1.首先保证移动端和Fiddler的主机为同一网络,并且能够抓取到HTTP协议
2.Fiddler开启抓取HTTPS协议
进入Tools-->Options-->HTTPS-->勾选Capture HTTPS CONNECTS-->勾选Decrypt HTTPS traffic --> 勾选 Ignore server certificate errors
3.移动端卸载配置证书
4.访问HTTPS协议的网络地址
《Charles》 简介:Charles是运行于Mac系统的抓包截取工具,设置代理服务器,处理网络请求,来实现网络封包的截取和分析。不过由于Mac系统限制,是一款收费软件,可以免费使用30天,过期后,每次使用时长仅仅在30分钟之内。总的算下来的话,对用户还是比较友好的,就算不付费,也还是可以使用较为完整的功能。
HTTP: 1.设置 Proxy -> MacOS X Proxy,打开抓包
2.设置浏览器的代理(网络设置里设置), localhost:8888 (charles默认8888,可修改);
3.浏览器使用了代理管理插件的就新建一个代理服务器,localhost:8888
HTTPS: 1.安装SSL证书:help -> SSL proxying -> install charles root certification
2.安装完会自动跳到系统的钥匙串管理界面,并见到charles的证书,此时双击他并在信任里选择“信任”
3.设置proxy -> SSL proxy setting 第一个tab(SSL proxying)新增规则:'host:*; port: 443'
【k8s主机重启后服务异常】 主要表现:
主机上相关k8s相关组件均未启动,使用kubectl命令报错(The connection to the server localhost:6443 was refused - did you specify the right host or port?)
重启docker与kubelet服务,启动k8s相关组件服务
[root@master01 opt]# systemctl restart docker [root@master01 opt]# systemctl restart kubelet [root@master01 opt]# docker ps [root@master01 opt]# docker ps -a [root@master01 opt]# docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) # 部分组件有依赖性,执行后部分组件未启动,可重复执行该命令,此处启动顺序需要再研究一下 [root@master01 opt]# ss -utnlp | grep 6443 # 查看端口是否启动 [root@master01 opt]# kubectl get pods -n kube-system # 查看相关组件是否正常执行 [root@master01 opt]# kubectl get pods -n kubernetes-dashboard # 查看你dashboard是否正常执行,未安装可不执行 # 以上命令需要在所有节点上执行 相关组件状态
实验拓扑 查看R4的bgp路由表,发现到达10.10.10.10网段有两条路径,优选了下一跳为R2的路径。(R3上配置了next-hop-local,使其向R4通告路由的下一跳为自身ip地址。)
1.优选Preferred-Value属性值最大的路由。 通过在R4上修改R3通告路由的Preferred-value值,使其Preferred-value值大于R2通告的路由的Preferred-value值,从而使得R4去往10.10.10.10优选下一跳为R3的路径。
bgp 200 peer 3.3.3.3 preferred-value 100 表示对邻居3.3.3.3发来的BGP路由,都将其Preferred-value值改为100
由以上结果可知,R4优选Preferred-value值更大的下一跳为3.3.3.3(R3)的路由
2.优选Local_Preference属性值最大的路由。 在R4上对R3发过来的路由进行local-Preference值进行修改,使其大于从R2接收的路由
ip ip ip-prefix ww index 10 permit 10.10.10.10 32 route-policy loc permit node 10 if-match ip-prefix ww apply local-preference 200 bgp 200 peer 3.3.3.3 route-policy loc import 由以下结果可知R4优选local-Preference值更大的下一跳为3.3.3.3(R3)的路由
3.本地始发的BGP路由优于从其他对等体学习到的路由,本地始发的路由优先级:优选手动聚合>自动聚合>network>import>从对等体学到的。 在R4上network 10.10.10.10进BGP,可见最后R4优选本地产生到10.10.10.10的路由,而不是从对等体学来的,从而验证本地始发的BGP路由优于从其他对等体学习到的路由。
在R4上创建10.10.1.1 /24、10.10.2.1/24的静态路由,并引入进BGP,在进行手动聚合
ip route-static 10.10.2.0 255.255.255.0 NULL0 ip route-static 10.10.1.0 255.255.255.0 NULL0 bgp 200 import-route static summary automatic 自动聚合后,按照自然网段聚合出10.0.0.0/8的网络。
在R4上手动聚合后,判断BGP路由优选手动聚合还是自动聚合。
bgp 200 aggregate 10.0.0.0 255.
一、for循环语句
1.在java中一般用在次数确定情况下。如果要进行重复性指令执行,可以用for循环。基本语法如下所示:
for(初始化表达式;循环条件;操作表达式){ c1:执行语句 ...... } 上面这个语法语句中for关键字后面包括了三个内容,初始化表达式、循环条件、操作表达式,它们用分号(;)分隔,在大括号里面有个执行语句为循环体。这个for循环语句是怎么执行的呢?
分4步走:
第一步:首先执行的是初始化表达式;
第二步:执行循环条件,看判断条件满不满足,如果满足条件,再执行c1的语句,如果当条件不满足,就退出for循环 ;
第三步:执行c1的语句 ;
第四步:执行操作表达式,然后重复执行第二步 ;
2.使用for循环求1-10的整数和的值。
代码如下所示:
int sum = 0; for(int i = 1; i <= 10; i++){ sum += i; } System.out.println("1-10整数和的值为" + sum); 输出的结果是:
1-10整数和的值为55 从上面代码我们可以看出,定义一个int类型变量sum来保存1-10整数和的值,然后看for循环,初始化表达式定义了一个int类型变量i为1,执行循环条件,看满不满足这个条件,i的值为1,条件i<=10所以是满足条件的,执行sum+=i相当于(sum=sum+i),再执行i++,又回到这个循环条件,再去判断满不满足这个条件,如果满足条件就继续执行,直到不满足条件就退出这个for循环,打印1-10整数和的值为55。
二、for循环的嵌套
1.什么是for循环的嵌套呢?
循环语句中又出现循环,我们就叫它for循环的嵌套。
例如:下面这个小案例来具体分析for循环的嵌套
for (int i = 0 ; i < 2 ; i++ ){ //外层循环 for (int j = 0; j < 2 ; j++ ){//内层循环 System.out.println("i的值为:" + i + "
这么一个简单的问题,在网上愣是找不到一个拿来即用的方法,这里记录一下:
文字换行且靠左 <view style="text-align: left"> <text>第一行</text> <text>\n第二行</text> </view> 换行直接用“\n”。很暴力
一行文字靠上,一行文字靠下 在一个子空间中,摆放两行文字
<view style="display: flex; flex-direction: column; height: 100px; text-align: left"> <text>第一行</text> <text style="margin-bottom: 0%">\n第二行</text> </view> 为了效果演示,我限制了父元素的高度为100px。布局需要是display: flex;且布局的主轴为垂直方向,起点在上沿flex-direction: column;最后设置需要靠下的文字的外下边距为0,这样他就靠下了margin-bottom: 0% PS:这个css样式应该通用,不限制在uni-app。
一、先去官方下载 如出现VMware提示此主机支持Intel VT-x,但Intel VT-x处于禁用状态怎么解决
解决路径: http://www.xitongcheng.com/jiaocheng/xtazjc_article_38955.html
二、下载到网盘 三,打开虚拟机vmware 选择桥梁网络
点‘完成’ 即可
选择自定义安装
选择中文
点开始安装
等完成,点退出
中标麒麟设置SSH: 因为是linux系统,用命令更方便。点击图标如下:
点击头像
点击‘更改密码’
进行身份验证,点击‘身份验证’
输入新密码{我的新密码是123456},点击更改密码
关闭所有窗口,点击网络状态图标
点击连接信息
至此中标麒麟的SSH已设置完成,可以去连接了
Appium 自动化多线程
1.模拟器多开
2.将模拟器通过adb命令连接到server
夜神模拟器第一个模拟器默认端口 60001
第二个 60025
第n 个 60025(累加1)
连接:adb connect 127.0.0.1:端口号
查看当前:adb devices
3.启动多个appium
对应连接上模拟器
默认端口号为4723
新建累加4 例如第二个设为4727
4.前置代码
需要注意的地方:
因为模拟器情况下deviceName没有实际意义,随便填都行,所以需要加上udid来唯一区分用下面的target相关的代码才能同步运行,之前没有用这个就是先第一个再后一个。 import threading import time from appium import webdriver desired_caps1 = {"platformName": "Android", # 平台名称 "platformVersion": "7", # 系统版本号 "deviceName": "127.0.0.1:62001", # 设备名称。如果是真机,一般在'设置->关于手机->设备名称'里查看 "appPackage": "com.android.chrome", # apk的包名 "appActivity": "com.google.android.apps.chrome.Main", # activity 名称 "udid": "127.0.0.1:62001" } desired_caps2 = {"platformName": "Android", # 平台名称 "platformVersion": "7", # 系统版本号 "deviceName": "
AQS(AbstractQueuedSynchronizer)是JUC里非常重要的类,像可重入锁ReentrantLock和CountDownLatch等底层都是有AQS来实现的。由于AQS底层结构比较复杂,如果直接讲源码的话大家可能看的一头雾水,这篇文章就从ReentrantLock的加锁和解锁入手,来一步步解析AQS的源码和底层工作原理。
首先说一下AQS的基本结构,其中维护了一个双向链表,链表中每个节点都包含一个线程,其结构示意图如下:
AQS结构示意图 链表中的节点Node有如下几个重要的属性:
/** 共享模式下等待的标记 */ static final Node SHARED = new Node(); /** 独占模式下等待的标记 */ static final Node EXCLUSIVE = null; //下面四个属性都是该节点线程的等待状态 /** 表示当前节点的线程已被取消*/ static final int CANCELLED = 1; /** 表示当前线程的下一个线程需要被唤醒 */ static final int SIGNAL = -1; /** 表示当前线程在条件等待队列中 */ static final int CONDITION = -2; /** 表示下一个acquireShared需要无条件的传播*/ static final int PROPAGATE = -3; /** 等待状态 */ volatile int waitStatus; /** * 链接到当前节点/线程所依赖的前驱节点 * 当前线程用它来检查等待状态。在入队分配 * 仅在出队时出列(为了GC)。 此外,当 * 头节点永远不会被取消,一个节点成为头节点 * 仅仅是成功获取到锁的结果,一个被取消的线程永远也不会获取到锁,线程只取消自身 * 而不涉及其他节点 */ volatile Node prev; /** * 当前节点的后继节点,当前线程释放的才被唤起,在入队时分配,在绕过被取消的前驱节点 * 时调整,在出队列的时候取消(为了GC) * 如果一个节点的next为空,我们可以从尾部扫描它的prev,双重检查 * 被取消节点的next设置为指向节点本身而不是null,为了isOnSyncQueue更容易操作 */ volatile Node next; /** * 当前节点包含的线程,初始化后使用,使用后失效 */ volatile Thread thread; /** * 链接到下一个节点的等待条件 */ Node nextWaiter; 首先是加锁的过程 ReentrantLock使用lock()函数加锁,我们来分析下其实现: //ReentrantLock的lock方法是调用的同步队列内部类sync的lock方法 public void lock() { sync.
今天不知道怎么回事,移动硬盘插到台式机上,设备和驱动器突然就没有读出来,以前都能读出来的,但是右下角硬盘的设备标志显示出来了。
插到另一台电脑上又可以读出来。
不放弃的反复试了几次还是一样。
网上描述的也跟我的情况不一样,台式机很多资料,完全不考虑重装系统!!!!
不放弃的自己摸索了一下,竟然弄好了... ....
方法:
1、点击硬盘的设备标志- >'打开设备和打印机'
2、找到你的硬盘设备,然后右击,删除设备(设备名字应该能确定吧???)
3、拔出硬盘,重新插一下, 就显示出来了。
XSS–伪装管理员登录后台 文章目录 XSS--伪装管理员登录后台一.XSS注入原理二.XSS危害二.XSS分类三.Cookie是什么四.XSS获取cookie 一.XSS注入原理 XSS 攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为 XSS,XSS 是一种在 web 应用中的计算 机安全漏洞,它允许恶意 web 用户将代码植入到 web 网站里面,供给其它用户 访问,当用户访问到有恶意代码的网页就会产生 xss 攻击
XSS是因为用户输入的内容被浏览器当作了前端代码进行 执行。
<script>alert(/XSS/)</script> <script>console.log(1);</script> <a href=javascript:alert(1)> <a href='javascript:alert(1)'>aa</a> 二.XSS危害 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力盗窃企业重要的具有商业价值的资料非法转账强制发送电子邮件(钓鱼)网站挂马控制受害者机器(肉鸡)向其它网站发起攻击 二.XSS分类 反射型xss:不会永久存储用户的数据,仅发生在用户的一次访问之后存储型xss:攻击代码被持久化保存在服务器上。DOM型xss 三.Cookie是什么 什么是cookie?
指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)
COOKIE:
客户端将用户名密码等信息给服务器,服务器返回用户身份对应的cookie给客户端,
之后两人的身份认定,就靠cookie来进行。
简单地说,当用户使用浏览器访问一个支持Cookie的网站的时候,
用户会提供包括用户名在内的个人信息并且提交至服务器,服务器回传给用户这段个人信息的加密版本,
这些信息并不存放在HTTP响应体(Response Body)中,而存放于HTTP响应头(Response Header)
四.XSS获取cookie 怎么验证XSS?
一般是想办法让浏览器弹窗(alert) 最经典的弹窗语句:<script>alert(1)</script>
一般检测XSS是否存在,就是在正常页面传参然后构建参数让他弹窗就是存在XSS了
利用XSS平台用于收取cookie,账号等信息推荐网站https://xs.sb/xss.php?do=login注册后先创建项目:
目录
1 什么是闭包
1.1 JS中的闭包
原理分析
1.2 JAVA中的闭包
1.3 c++中的闭包
2 闭包的应用场景
2.1 应用场景1 代码模块化
2.2 应用场景2 在内存中保持变量数据一直不丢失!
3 最后
1 什么是闭包 闭包的英文对应的是Closure,如果要单纯的讨论这个概念的话就要提到和图灵机起名的大名鼎鼎的lambda演算(lamdba calculus)。尽管lamdba的概念并不是本文的重点,但是闭包概念的目的便是支持lamdba的实现。如果你单独地在百度对进行搜索闭包的话,你会发现大部分都是js相关的内容,主要是js本身就只用闭包的这个概念。但是闭包并不仅限于js,而是一个通用的概念。借用wiki中有点抽象的定义来说的话,闭包就是:
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。
简单来说就是当一个方法引用了方法局部变量外的变量时,它就是一个闭包。而如果根据这个定义继续延展的话,就可以得到另外的一种描述方法:
闭包是由函数和与其相关的引用环境(方法外变量)组合而成的实体。
通俗点就是:一个函数返回了一个函数对象,而这个返回的函数对象引用了外部函数的私有变量/局部变量,这样就形成了一个闭包。
1.1 JS中的闭包 涉及到以下JS知识点:
函数的执行上下文环境(Execution context of function)
变量对象(Variable object)
活动对象(Active object)
作用域(scope)
作用域链(scope chain)
那么我们首先来看一段JS代码
//函数定义 function outerTest() { var num = 0; function innerTest() { ++num console.log(num); } return innerTest; } //调用 var fn1 = outerTest(); fn1(); fn1(); fn1(); 运行结果
在本教程中,我们将向您展示如何在Ubuntu 18.04上安装Git。 我们还将安装并配置其必要条件。 Git是一个分布式版本控制程序,您可以在开发软件时使用它监视代码的变化(版本)。 Git提供了恢复到前一阶段,多个工作流程,邻居分支以及其他许多功能的功能。 这使Git成为最好的版本控制系统之一,这也是许多软件开发人员使用Git的原因。
我建议使用最小的Ubuntu服务器设置作为本教程的基础,可以是虚拟或根服务器映像,使用Ubuntu 18.04 LTS Bionic Beaver最小化安装,或者使用我们的最小服务器教程安装 服务器从零开始。
在Ubuntu 18.04上安装Git
步骤1.首先,通过运行以下命令确保您的系统和apt包列表完全更新:
apt-get update -y
apt-get upgrade -y
第2步。在Ubuntu 18.04上安装Git。
现在让我们安装git:
apt install git
您可以使用以下命令来检查已安装的git版本:
$ git --version
git version 2.15.1
第3步。在Ubuntu 18.04上配置Git。
安装后您可能想要做的第一件事是在Git中配置自己的名称和电子邮件地址,以便您提交的更改包含正确的信息。 您可以通过使用以下命令来完成此操作:
linuxidc@linuxidc:~$ git config --global user.name "linuxidc"
linuxidc@linuxidc:~$ git config --global user.email "root@linuxidc.net"
接下来,我们将通过查看.gitconfig来验证配置更改:
linuxidc@linuxidc:~$ git config --list
user.name=linuxidc
user.email=root@linuxidc.net
有关更多信息和命令行选项,可以使用-help标签:
git --help
linuxidc@linuxidc:~$ git --help
用法:git [--version] [--help] [-C <path>] [-c <键名>=<值>]
黑马程序员并发编程笔记(一)–进程的概念
黑马程序员并发编程笔记(二)–java线程基本操作和理解
java并发编程笔记(三)–管程(一)
java并发编程笔记(三)–管程(二)
java并发编程笔记(三)–管程(三)
java并发编程笔记(三)–管程(四)
java并发编程笔记(三)–管程(五)
java并发编程笔记(四)–JMM内存模型
java并发编程笔记(五)–共享模型之无锁
java并发编程笔记(六)–共享模型之不可变
java并发编程笔记(七)–juc工具类的使用共享模型之不可变
信息系统项目管理师好不好考是取决于个人的,有的人认为很简单,复习一两个月就过了;有的人认为很难,考了几次才过,这个真的是因人而异的。
就拿我来说,自己就备考了4个月才通过了考试,而身边的朋友只备考了两个月就拿到证书了,当然还有更多的朋友是没有通过考试的。
这张图片是重庆市的软考通过率分析表,可以看到信息系统项目管理师的通过率只有15%,通过率还是很低的,这也说明了信息系统项目管理师考试还是有一定难度的。虽然信息系统项目管理师的通过率比较低,但它相对于软考高级其他科目来说,属于简单的了,毕竟它是偏管理方向的科目,需要记忆的东西较多,只要好好复习备考,那么信息系统项目管理师证书一定能拿到手的。
好啦,肯定会有小伙伴问:那么你是如何通过信息系统项目管理师的?
当然了,下面就是我的备考经验分享了
1、教材
先上强迫症患者的截图
基本上我给自己制定的就是2天一章节,一个月左右时间会将教材给啃完。因为我是考过PMP和集成的,很大一部分概念是有冲突的,所以学习规划的会比较快,小白的话建议可以将时间线拉长,还有前三章的时候可以加个任务,梳理整理十五至尊图,达到可以背诵默写的地步。
2、论文
我在论文的部分花了最大的心思了,从最基础的简介开始,定好方向在做细分的,首先我也是看了很多人写好的现成的论文做参考的,基本都是很八股文的,代入ITTO来写的。所以我的学习计划也是根据这个来制定的,一个板块一个板块来。
论文的时间,我一样是控制在一个月左右的,没错,我每天就是在啃论文,没办法,实在是难呀。
3、巩固
复习阶段的时间,我是控制在半个月左右的
复习阶段我会根据以往重点考点来结合着复习,这个复习也是案例分析的常见问题,因为我集成也是按照网络上扒的重点考点资料来复习的,感觉效果还不错,所以高项我也加了进去。
考试题型拆解
1、选择题
我给自己安排就是上午的选择题部分。上午的选择题有30分的信息化和信息系统的知识点、部分专业理论,同时还会有不少专业术语,这部分是要攻克的,科班出身可以不担心专业术语的问题。另外的部分就是关于政策、新趋势、新技术的通用理论了,这部分内容还是比较好理解的,可以通过思维导图去记忆,这里的考试内容是属于好得分,掌握ITTO,基本没什么问题。
2、案例题
案例题及计算题的联系,看过很多学长学姐的备考心得,一直在强调的ITTO,说案例题也是这个套路,找问题、分析问题并解决问题这个思路,首先就是确认考题是哪个领域,在按照ITTO过程去答题。看案例有无涉及哪个领域的过程去实施的,实施过程中有无用上ITTO,很关键的O有没有做好,在做补充。总结下来基本上套路就是这样。
计算题没什么好说的,网上有关于计算题的总结,多做多套用,就会了的,计算题很多都是换汤不换药的。
3、论文
论文的时间我安排得比较长,最让人恐惧的就是论文了。为了论文,我每天还专门练字30分钟呢。搜集到的信息呢就说,论文的内容还是有套路的,八股文,核心思路就是考察你如何运用相关知识去对项目进行管理。没做过项目的,可以报班按照老师知道的思路或者模板去写,代入思考,过程中用到了哪些工具,应该输出什么,写多了就会有感觉的。
前言 本篇写的内容是C语言中的分支和循环语句。
分支语句ifelse语句、switch语句
循环语句while循环、for循环、do while循环
语句 C语言中由一个分号;隔开的就是一条语句。比如:
分支语句 ifelse语句 if语句的语法结构是:
if (表达式)
语句 ;
if (表达式)
语句 1;
else
语句2 ;
//多分支 if (表达式1)
语句 1;
else if (表达式2)
语句2 ;
else
语句3 ;
注:在C语言中非0就是真,if后面圆括号中的表达式是非0,语句就能执行。
例:如下图一,创建一个age变量,当我令age=10时,if语句后面的表达式不成立,也就是假所以不执行。当我令age=20时,如下图二,打印成年。
图一
图二 图三
现在在else后面再加上一条,如果是未成年,不能谈恋爱。注意,当if或者else后面默认只能控制一条语句,所以这里要执行两条语句就要加上大括号。
多分支语句结构例:
如下图一,令18-26岁之间的为青年,可以看到当我让age=40时,不在区间内却还是打印了青年。这个代码语法上没有错误,但是逻辑上有误。age=40时,if表达式中的age=40,然后18<=40,所以;条件成立,成立为真,就是1,然后18<=age就为1,而后1<26,所以条件成立,又是1,所以这个地方会打印青年。 正确的方式是age >= 18 && age < 26 ;或者不写age >= 18。
图一
图二
switch语句 swith语句也是一种分支语句,常常用于多分支的情况。
swith语句的结构是:
switch(整形表达式
{
语句项;
}
语句项是什么呢?
是一些case语句:
case 整型常量表达式:
语句;
例:输入1-7的数字,分别代表对应的星期。那用ifelse语句会比较麻烦,那我们就得有不一样的语法格式,这里运用的就是swith语句。
如下图一,运用switch语句写出,可以看到当我输入1的时候,输出了星期一,但是也继续输出到星期天的值。是因为case 1语句执行完,没有阻止语句停下来,语句会一直执行,直到把case语句执行完。当输入2,是什么结果。结果如下图2,可以看到当输入2的时候,语句从case 2进去,跳过case 1。switch后面的表达式结果是几,就会从case 几进去。
官方帮助文档: https://docs.docker.com/reference/
帮助命令 docker version # 显示docker版本信息 docker info # 显示docker系统系统信息,镜像以及容器数量等信息 docker 命令 --help # 帮助命令 镜像命令 docker images 查看本地的所有镜像
# docker images 查看本地的所有镜像 [root@izuf6akcgealirj602cmxsz /]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 3 months ago 13.3kB # 命令参数含义 REPOSITORY # 镜像仓库源 TAG # 镜像的标签,版本 IMAGE ID # 镜像的ID,唯一表示 CREATED # 镜像的创建时间 SIZE # 镜像的大小 # 可选项 -a, --all # 列出所有镜像 -q, --quiet # 只显示镜像ID docker search 查找镜像
结构体的初始化 方法一方法二 方法一 定义结构体变量,然后对结构体中的元素逐一进行初始化。
方法二 如果结构体中的变量很多的时候,我们可以采用“构造函数”的方法来对结构体进行初始化
构造函数是一种用来初始化结构体的一种函数直接定义在结构体中 构造函数不需要写返回值类型,而且函数名和结构体名相同
struct Student { int students; char name; Student( ) { students = 2; name = "222"; } } #define INIT_SIZE 10 #include<stdio.h> #include<stdlib.h> //malloc在这个文件里 typedef struct Sqlist{ int* list; int length; int size; Sqlist() //构造函数 { list = (int*)malloc(INIT_SIZE*(sizeof(int))); //在构造函数里为线性表动态分配十个单位长度 length = 0; //初始长度为0 size = INIT_SIZE; //初始容量为INIT_SIZE } }Sqlist; int main() { Sqlist L; printf("初始长度是:%d,初始容量是%d",L.length,L.size); system("pause"); return 0; }
文章目录 什么是inode?inode的内容(inode是一个结构体)block区和inode区的理解inode编号硬链接软连接 什么是inode? 理解inode,要从文件储存说起。
文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。
操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。
文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
inode的内容(inode是一个结构体) 我们可以通过stat指令查看一个文件的inode信息
inode中的内容:
文件的字节数,块数文件拥有者的User ID文件的Group ID文件的读、写、执行权限文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次 变动的时间,atime指文件上一次打开的时间。链接数,即有多少文件名指向这个inode文件数据block的位置inode编号(对应数组的下标) block区和inode区的理解 硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区(block区),存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。inode区是以数组的形式存储的,对应的数组下标就是inode编码,每个元素就是一个结构体(结构体内容在上面已说),inode结构体中会有一个指针,指向block区也就是存放的文件内容。
我们可以通过指令df查看每个硬盘分区的inode总数和已经使用的数量.
inode编号 inode编号是很重要的,当系统在找一个文件时,步骤如下:
1.通过文件名先找到文件的inode编号
2.通过inode编号找到文件inode信息
3.通过inode信息中的block指针找到文件内容。
我们可以通过ls -i查看文件的inode编号
硬链接 一般情况下,文件名和inode号码是”一一对应”关系,每个inode号码对应一个文件名。但是Unix/Linux系统允许,多个文件名指向同一个inode号码。这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为”硬链接”(hard link)。可以使用ln指令添加硬链接。
通过硬链接创建出来的文件的inode编号是一样的,
注意:
1.硬链接相当于一个副本,不会占用实际空间
2.删除一个硬链接,不会影响其他的inode
3.不允许给目录创建硬链接。
4. 硬链接只有在同一个文件系统中才能创建。
软连接 除了硬链接以外,还有一种特殊情况。
文件A和文件B的inode号码虽然不一样,但是文件A的内容是文件B的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的”软链接”(soft link)或者”符号链接(symbolic link)。
这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:”No such file or directory”。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode”链接数”不会因此发生变化。ln -s命令可以创建软链接。
对应图解:
简单粗暴的书写 使用WinHTTP实现文件下载,支持HTTPS。
支持保存文件路径,支持下载文件命名。
添加UrlEncode和UrlDecode(非标准规范,仅便于解析后获取文件名称)。
无暂停或继续下载
Usage: ProjectName.exe [Url] [drive:\path\filename]
#include <windows.h> #include <winhttp.h> #include <stdio.h> #include <iostream> #pragma comment(lib, "winhttp.lib") //https://blog.csdn.net/c914620529/article/details/73503708 //ANSI对应char,UTF-8对应char类型,Unicode(UTF-16)对应wchar_t //ANSI字符串的英文使用一个字节,中文使用两个字节 //Unicode字符串的英文与中文都使用两个字节 //UTF8字符串的英文使用一个字节,中文使用三个字节 //ANSI-->Unicode std::wstring StringToWString(const std::string& str) { int num = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); wchar_t* wide = new wchar_t[num]; MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wide, num); std::wstring wstr = wide; delete[] wide; return wstr; } //Unicode-->ANSI std::string WStringToString(const std::wstring& wszString) { int num = WideCharToMultiByte(CP_ACP, 0, wszString.
一.第一种通过navicat连接 1.相信大家都有的Navicat,小海豚等数据库图形化工具
没有的话下一个(可以免费使用14天的!)
链接:https://pan.baidu.com/s/1QG3QI-ArEJxS4--XjtZZ6g 提取码:ju45
2.新建的MySQL的连接
这样就连接成功了
二.第二种通过在mysql的bin目录下 进行数据库连接。 1.在mysql的bin目录下输入mysql -h localhost -u root -p
输入密码这样就连接成功了。 三.第三种通过MySQL自带的工具进行数据库连接。 1.打开MySQL 8.0 Command Line Client 2.打开后输入密码就可以使用了。
文章目录 CubeMX使用FreeRTOS编程指南一、开发前言1.1 软件准备1.2 开启FreeRTOS 二、配置界面三、系统设置2.1 调度内核设置2.2 内存管理设置2.3 钩子函数配置2.5 任务运行追踪配置2.6 协程配置2.7 软件定时器配置2.8 中断优先级配置 三、内核裁剪四、创建任务与队列4.1 CubeMX 下任务创建与配置4.2 CubeMX 下队列的创建与配置 五、创建定时器和信号量5.1 CubeMX下定时器的创建和配置5.2 CubeMX下信号量的创建和配置 六、创建互斥量6.1 CubeMX下互斥量的创建和配置 七、创建事件标志组7.1 CubeMX下事件的创建和配置 八、用户常量九、任务通知十、系统内核配置 CubeMX使用FreeRTOS编程指南 一、开发前言 1.1 软件准备 STM32CubeMX 代码生成软件
MDK 集成代码开发环境
1.2 开启FreeRTOS 新建一个 CubeMX 工程,在配置好时钟后,点击 Middleware -> 选择 FreeRTOS -> 下拉框选择 V2 版本 CMSIS
到此在 CubeMX 中就已经开启 FreeRTOS 系统了,下面分享 FreeRTOS 的配置:
二、配置界面 开启 FreeRTOS 之后,可以看到配置项主要分为以下几个部分
这几个部分的主要功能如下表:
配置项功能Tasks and Queues任务与队列,用于配置任务体以及消息队列;Timers and Semaphores软件定时器与信号量,用于配置内核对象 (软件定时器和信号量);Mutexes互斥量,用于配置内核对象(互斥量)Events事件,配置内核对象(事件)FreeRTOS Heap Usage查看用户任务和系统任务的堆占用Config Parameters系统的参数配置Include Parameters系统的功能裁剪Advanced SettingsCubeMX 生成代码预配置项User Constants用户常量定义 以上各个功能分的很清晰,我们需要配置什么功能就去对应的选项下进行配置,下面根据各个配置项进行详细配置介绍
https://blog.51cto.com/dadloveu/737268
https://www.cnblogs.com/Jing-Wang/p/10848960.html
https://blog.csdn.net/Doudou_Mylove/article/details/90038845
https://www.cnblogs.com/lasdaybg/p/12311085.html
wechat https://mirrors.aliyun.com/deepin/pool/non-free/d/deepin.com.wechat/
VTP VTP(VLAN Trunk Protocol)提供了一种用于在交换机上管理 VLAN 的方法,该协议使得我们可以在一个或者几个中央点(Server)上创建、修改和删除 VLAN,VLAN 信息通过Trunk链路自动扩散到其他交换机,任何参与 VTP 的交换都可以接受这些修改,所有交换机保持相同的 VLAN 信息。
VTP 被组织成管理域(VTP Domain),相同域中的交换机能共享 VLAN 信息。根据交换机在 VTP 域中的作用不同,VTP 可以分为以下 3 种模式。
服务器模式(Server):在 VTP 服务器上能创建、修改和删除 VLAN,同时这些信息会通告给域中的其他的交换机。在默认情况下,交换机是服务器模式。每个 VTP 域必须至少有一台服务器,域中的 VTP 服务器可以有多台。客户机模式(Llient):VTP 客户机上不允许创建、修改和删除 VLAN,但它会监听来自其他交换机的 VTP 通告并更改自己的 VLAN 信息。接收到的 VTP 信息也会在 Trunk 链路上向其他交换机转发,因此这种交换机还能充当 VTP 中继。透明模式(Transparent):这种模式的交换机不参与 VTP。可以在这种模式的交换机创建、修改和删除 VLAN,但是这些 VLAN 信息并不会通告给其他交换机,它也不接受其他交换机的 VTP 通告而更新自己的 VLAN 信息。然而需要注意的是,它会通过 Trunk 链路转发接收到的 VTP 通告,从而充当 了 VTP 中继的角色,因此完全可以把该交换机看成是透明的。 VTP 通告是以组播帧的方式发送的,VTP 通告中有一个字段称为修订号(Revision),初始值为 0.只要在 VTP Server上创建、修改和删除 VLAN,通告的 Revision 就增加 1,通告中还包含了 VLAN 的变化信息。需要注意的是:高 Revision的通告会覆盖低 Revision 的通告,而不管发送者是 Server 还是 Client。交换机只打官腔比本地在哪保存的Resivison号更高的通告;如果交换机收到比自己的 Resivison 号更低的通告,会用自己的 VLAN 信息反向覆盖。
简介 sqlx 是 rust 中的一个数据库访问工具。具有以下特点:
异步:原生就支持异步,在并发性高的场合能够得到更好的支持编译时检查查询:sqlx可以在 cargo build 的时候检查执行sql和响应值多数据库支持:PostgresSQL,MySql,SqlLite,MSSql,MariaDB多运行时支持:支持主流 rust 运行时。async-std,tokio,actix,native-tls,rustls内置连接池,支持查询缓存 不足 sqlx 不是 orm 框架
实践 本例将使用 sqlx 访问 postgressql 数据库,实现简单的增删改查功能
数据库 数据库采用 postgreSQL,初始建表语句如下:
-- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS "public"."course"; CREATE TABLE "public"."course" ( "id" int8 NOT NULL, "teacher_id" int4 NOT NULL, "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, "time" date DEFAULT now() ) ; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO "
一文总结initramfs的使用 文章目录 一文总结initramfs的使用一、开篇二、定制initramfs(2-1)使用busybox构建rootfs(2-2)完善rootfs(2-3)将rootfs链接进linux内核(2-4)启动测试 三、总结 一、开篇 在linux内核中,initramfs是一种执行早期用户空间程序的机制。常用于:在挂载真正根文件系统之前加载一些必须的设备驱动程序,也可以作为根文件系统的“跳板”。
在一些实际嵌入式系统应用中,可以通过initramfs执行一些脚本程序切换到对应设备下的文件系统,这一点在实际开发中很是有用,也使动态选择根文件系统成为可能。
二、定制initramfs 关于定制initramfs,有两种方法:
(1)创建一个cpio格式的档案文件,其中包含所需的所有文件。
(2)指定一系列目录和文件。然后将这些目录和文件链接进内核。
本文主要分享第二种方法来定制initramfs
(2-1)使用busybox构建rootfs 如上图所示,对busybox配置操作是:
选择将busybox进行静态构建。设置交叉编译工具链的路径。设置rootfs的安装目录。 当配置完成后,退出busybox图形配置界面,执行make编译构建busybox。然后再使用make install安装rootfs。随后将生成rootfs文件系统目录和busybox的运行本体程序。
(2-2)完善rootfs (2-2-1)在rootfs目录下创建etc、dev、home、mnt、proc、root、sys、tmp、var与linux文件系统相关的目录。完成后如下图所示:
(2-2-1)在etc目录下创建inittab文件,文件内容如下:
#/etc/inittab ::sysinit:/etc/init.d/rcS console::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a (2-2-2)在etc目录下创建fstab文件,文件内容如下:
proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 none /dev/pts devpts default 0 0 tmpfs /dev/shm tmpfs defaults 0 0 (2-2-3)在etc目录下创建子目录init.d并在该目录下创建rcS文件,文件内容如下:
#!/bin/sh LD_PRELOAD= PATH=/sbin:/bin:/usr/sbin:/usr/bin runlevel=S prevlevel=N umask 022 export PATH LD_PRELOAD runlevel prevlevel [ -d "
写在前面 由于昨天写的文章 Vue 源码之Vue视图更新原理【一】与今天的内容代码有些相关联,所以开头先进行简单的回顾阐述,也方便对内容进行完整的阅读。
Vue 视图更新原理 Vue 的视图更新原理主要涉及的是响应式相关API Object.defineProperty 的使用,它的作用是为对象的某个属性对外提供 get、set 方法,从而实现外部对该属性的读和写操作时能够被内部监听,实现后续的同步视图更新功能
一、实现响应式的核心API:Object.defineProperty Object.defineProperty的用法介绍:MDN-Object.defineProperty,下面是模拟 Vue data 值的更新对API接口进行初步了解
// 模拟 Vue 中的 data const data = {} // 对外不可见的内部变量 let _myName = 'Yimwu' // 响应式监听 data 中的 name Object.defineProperty(data, "name", { // 使用 data.name 时 get 方法被调用,返回内部存储变量值 get: () => { console.log('get') return _myName }, // 使用 data.name = xxx 修改变量时,set 方法被调用,设置内部存储变量值 set: (newVal) => { console.log('set') _myName = newVal } }) console.
1、查看pringboot自带的日志框架 新建一个springboot 工程,查看依赖树
通过查看依赖树可以发现,springboot自带被loggong管理的log4j 、logback等日志相关的依赖。为了不影响测试结果,手动排除掉龙宫依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> 2、spring集成log4j2 springboot集成log4j2 与spring集成的步骤一样,
先排除掉springboot自带的日志依赖,然后引入log42依赖
<!-- 添加log4j2依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> 日志配置可以通过application.properties后者yaml文件进行配置
#日志级别 logging.level.com.li=info #日志输出格式 打印到控制台 logging.pattern.console=%d{yyyy-MM-dd} [%level] -%m%n #将日志输出到文件 springbootlog为生成的文件名 logging.file.path=D:/test/springbootlog 同时也可以在resource目录下新建 log4j2.xml配置文件进行配置。如果xml与properties同时存在,日志级别和格式以xml配置的为准。
如果对log的功能要求比较复杂,则使用xml方式进行配置。
xml配置与spring继承log4j2的写法一样,可以参考spring集成log4j2的xml示例
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <!-- 配置控制台输出 --> <Console name="consoleAppender" > </Console> </Appenders> <!-- 配置logger --> <Loggers> <Root level="info"> <AppenderRef ref="consoleAppender"/> </Root> </Loggers> </Configuration> 案例 package com.bjpowernode.springbootlog; import org.
区间dp 1.石子合并 题目描述 设有 N 堆石子排成一排,其编号为 1,2,3,…,N。
每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N 堆石子合并成为一堆。
每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同。
例如有 4 堆石子分别为 1 3 5 2, 我们可以先合并 1、2 堆,代价为 4,得到 4 5 2, 又合并 1,2 堆,代价为 9,得到 9 2 ,再合并得到 11,总代价为 4+9+11=24;
如果第二步是先合并 2,3 堆,则代价为 7,得到 4 7,最后一次合并代价为 11,总代价为 4+7+11=22。
问题是:找出一种合理的方法,使总的代价最小,输出最小代价。
输入格式
第一行一个数 N 表示石子的堆数 N。
第二行 N 个数,表示每堆石子的质量(均不超过 1000)。
输出格式
输出一个整数,表示最小代价。
数据范围
1≤N≤300
输入样例:
4
1 3 5 2
输出样例:
22
解题思路 划分的依据是i到j之间的点k,k的取值是(i,j-1),因为把[i,j]合并为一个,所以至少有两堆石子也就是将(i,k),(k+1,j)合并,合并(i,k)的代价是f[i,k],合并(k+1,j)的代价是f[k+1,j],将(i,k),(k+1,j)合并的代价是从i到j石子的重量,可以用前缀和提前求出s,那么i~j石子合并的代价就是s[j]-s[i-1],所以状态转移方程是f[i][j]]=f[i][k]+f[k+1][j]+s[j]-s[i-1]
代码实现 #include<iostream> #include<cstring> using namespace std; const int N=310; int s[N],f[N][N]; int main() { int n; cin>>n; memset(f,0x3f,sizeof(f));//记得初始化 for(int i=1;i<=n;i++){ cin>>s[i]; f[i][i]=0; //初始化 } for(int i=1;i<=n;i++) s[i]+=s[i-1]; for(int len=2;len<=n;len++){//区间长度一共n堆石子,当n取一的时候就是一堆,不用合并 for(int l=1;l+len-1<=n;l++){//l~k,k~r-1//区间左端点 int r=l+len-1;//区间右端点 for(int k=l;k<r;k++){//k在区间左右端点之间 f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]); } } } cout<<f[1][n]<<endl; return 0; } 2.
这技能我早就get了,但是今天要用发现忘了!所以我就只好写下来了。
首先!
我们肯定知道markdown添加图片的语法
 既然是要传到网上, 所以肯定不能用本地地址,你得用网图。你不值得为了一个配图再去特意弄个图床(你愿意这么搞我也没办法。所以最简单的就是直接在你仓库里放图就可以啦。
图片放进仓库里然后地址如下:
gitee:https://gitee.com/用户名/仓库名/raw/分支/图片文件地址/图片名
github:https://github.com/用户名/仓库名/raw/分支/图片文件地址/图片名
建议只用github,从昨天开始大量人员发现自己gitee仓库的外链图片被屏蔽了,直接改成了gitee的图标。2022.3.27
且慢!(尔康手
不要傻傻的复制上边的就去找你的仓库名图片名,告诉你更便捷的方法。
如果你提前上传图片了,那你打开你的图片看一下地址
你只需要复制地址,把blob改成raw就行啦。如果你没有上传图片,那你打开仓库地址,只需要补上你的图片名就可以啦。
我是萝莉安,我终于要做程序媛了
线性回归 题目和数据 题目:使用ex1data1.txt中给出的两个变量,分别设为x,y,来预测卡车利润(y)的收益值。
在数据集,第一列表示城市人数(x),第二列该城市的卡车利润(y)
数据集:
6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166
5.7107,3.2522
14.164,15.505
5.734,3.1551
8.4084,7.2258
5.6407,0.71618
5.3794,3.5129
6.3654,5.3048
5.1301,0.56077
6.4296,3.6518
7.0708,5.3893
6.1891,3.1386
20.27,21.767
5.4901,4.263
6.3261,5.1875
5.5649,3.0825
18.945,22.638
12.828,13.501
10.957,7.0467
13.176,14.692
22.203,24.147
5.2524,-1.22
6.5894,5.9966
9.2482,12.134
5.8918,1.8495
8.2111,6.5426
7.9334,4.5623
8.0959,4.1164
5.6063,3.3928
12.836,10.117
6.3534,5.4974
5.4069,0.55657
6.8825,3.9115
11.708,5.3854
5.7737,2.4406
7.8247,6.7318
7.0931,1.0463
5.0702,5.1337
5.8014,1.844
11.7,8.0043
5.5416,1.0179
7.5402,6.7504
5.3077,1.8396
7.4239,4.2885
7.6031,4.9981
6.3328,1.4233
6.3589,-1.4211
6.2742,2.4756
5.6397,4.6042
9.3102,3.9624
9.4536,5.4141
8.8254,5.1694
5.1793,-0.74279
21.279,17.929
14.908,12.054
第1关:Series数据选择 import pandas as pd import numpy as np arr = input() dates = pd.date_range('20190101', periods=25) # 生成时间序列 df = pd.Series(eval(arr),index=dates) #完成编程要求,并输出结果 #********** Begin **********# df[pd.to_datetime('2019-01-29')]=320 a = df['2019-01-04'::] print(a[a>100]) #********** End ********** 第2关:DataFrame数据选择方法 import pandas as pd def demo(raw_data,origin): df = pd.DataFrame(raw_data,index=origin) #转换成编程要求所示DataFrame, 并输出 #********** Begin **********# print(df.loc[['Florida','Washington'],'deaths':].T) #********** End **********# return
orb3-编译网上教程很多,写一下自己安装编译过程中踩的坑,一个半星期,终于可以跑demo了。
1.出现如下问题,或者在Build target g2o时 卡住。
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:375:CMakeFiles/ORB_SLAM3.dir/src/MLPnPsolver.cpp.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:76:CMakeFiles/ORB_SLAM3.dir/src/Tracking.cc.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:245:CMakeFiles/ORB_SLAM3.dir/src/Frame.cc.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:102:CMakeFiles/ORB_SLAM3.dir/src/LoopClosing.cc.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:323:CMakeFiles/ORB_SLAM3.dir/src/G2oTypes.cc.o] 错误 1
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:232:CMakeFiles/ORB_SLAM3.dir/src/Optimizer.cc.o] 错误 1
make[1]: *** [CMakeFiles/Makefile2:390:CMakeFiles/ORB_SLAM3.dir/all] 错误 2
make: *** [Makefile:84:all] 错误 2
make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:375:CMakeFiles/ORB_SLAM3.dir/src/MLPnPsolver.cpp.o] 错误 1 make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:76:CMakeFiles/ORB_SLAM3.dir/src/Tracking.cc.o] 错误 1 make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:245:CMakeFiles/ORB_SLAM3.dir/src/Frame.cc.o] 错误 1 make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:102:CMakeFiles/ORB_SLAM3.dir/src/LoopClosing.cc.o] 错误 1 make[2]: *** [CMakeFiles/ORB_SLAM3.dir/build.make:323:CMakeFiles/ORB_SLAM3.dir/src/G2oTypes.cc.o] 错误 1 make[2]: *** [CMakeFiles/ORB_SLAM3.
0 Flashback Data Archive 12c - Using Flashback Data Archive
19c - Using Flashback Time Travel
1 概览 闪回查询和闪回版本查询
ORA-01555
2 配置闪回数据归档 创建或指定一个或多个表空间用于FBDA保留历史数据
指派一个FBDA作为数据库的默认FBDA
指派一个用户账户作为FBDA管理员,授予它FLASHBACK ARCHIVE ADMINISTER系统权限
授予FBDA权限给适合的用户账号
授予FLASHBACK和SELECT权限给合适的FBDA表用户
为FBDA用户授予DBMS_FLASHBACK存储过程EXECUTE权限
创建保存FDA的表空间
create tablespace fda_tbs1 datafile size 10G autoextend off; 创建FDA
create flashback archive fda1 tablespace fda_tbs1 quota 100M retention 1 year; 变更基表以启用归档并将其分配到一个闪回归档
alter table hr.employees flashback archive fda1; 3 工作原理 4 使用场景 - 使用闪回数据归档访问历史数据 创建默认FDA
create flashback archive default fda tablespace fda_tbs1 quota 100M retention 5 year; 执行默认FDA
小白都能看懂的 Spring 源码揭秘之Spring MVC 前言Spring MVC 请求流程Spring MVC 两大阶段初始化HttpServletBean#init()FrameworkServlet#initServletBeanFrameworkServlet#initWebApplicationContextDispatchServlet#onRefreshSpring MVC 九大组件MultipartResolverLocaleResolverThemeResolverHandlerMappingHandlerAdapterHandlerExceptionResolverRequestToViewNameTranslatorViewResolverFlashMapManager 处理请求DispatcherServlet#doDispatchDispatcherServlet#getHandlerAbstractHandlerMapping#getHandlerAbstractHandlerMethodMapping#getHandlerInternalAbstractHandlerMethodMapping#lookupHandlerMethodAbstractHandlerMethodMapping 的初始化AbstractHandlerMethodMapping#initHandlerMethodsAbstractHandlerMethodMapping#detectHandlerMethodsAbstractHandlerMethodMapping#register 总结 前言 对于 Web 应用程序而言,我们从浏览器发起一个请求,请求经过一系列的分发和处理,最终会进入到我们指定的方法之中,这一系列的的具体流程到底是怎么样的呢?
Spring MVC 请求流程 记得在初入职场的时候,面试前经常会背一背 Spring MVC 流程,印象最深的就是一个请求最先会经过 DispatcherServlet 进行分发处理,DispatcherServlet 就是我们 Spring MVC 的入口类,下面就是一个请求的大致流转流程(图片参考自 Spring In Action):
一个请求过来之后会到达 DispatcherServlet,但是 DispatcherServlet 也并不知道这个请求要去哪里。DispatcherServlet 收到请求之后会去查询处理器映射(HandlerMapping),从而根据浏览器发送过来的 URL 解析出请求最终应该调用哪个控制器。到达对应控制器(Controller)之后,会完成一些逻辑处理,而且在处理完成之后会生成一些返回信息,也就是 Model,然后还需要选择对应的视图名。将模型(Model)和视图(View)传递给对应的视图解析器(View Resolver),视图解析器会将模型和视图进行结合。模型和视图结合之后就会得到一个完整的视图,最终将视图返回前端。 上面就是一个传统的完整的 Spring MVC 流程,为什么要说这是传统的流程呢?因为这个流程是用于前后端没有分离的时候,后台直接返回页面给浏览器进行渲染,而现在大部分应用都是前后端分离,后台直接生成一个 Json 字符串就直接返回前端,不需要经过视图解析器进行处理,也就是说前后端分离之后,流程就简化成了 1-2-3-4-7(其中第四步返回的一般是 Json 格式数据)。
Spring MVC 两大阶段 Spring MVC主要可以分为两大过程,一是初始化,二就是处理请求。初始化的过程主要就是将我们定义好的 RequestMapping 映射路径和 Controller 中的方法进行一一映射存储,这样当收到请求之后就可以处理请求调用对应的方法,从而响应请求。
初始化 初始化过程的入口方法是 DispatchServlet 的 init() 方法,而实际上 DispatchServlet 中并没有这个方法,所以我们就继续寻找父类,会发现 init 方法在其父类(FrameworkServlet)的父类 HttpServletBean 中。
由于使用的PHP库解析xls格式文件有问题,而将xls格式转换为xlsx格式就可以解析,考虑到xls文件有很多,需要使用批量转换文件的方法,本文介绍两种方法。
目录 方法1:Python pandas库方法2:VBA批量转换 方法1:Python pandas库 使用Python pandas库的to_excel方法来另存为xlsx格式。
考虑到Excel文件一般有多个工作表,需要都读出来然后保存。下面直接给出代码:
import glob import os import time import pandas as pd class excelConvert(): def __init__(self): self.path = os.getcwd() # 当前工作路径 xlsxdirname = "xlsx" xlsxpath = os.path.join(self.path, xlsxdirname) if not os.path.exists(xlsxpath): print(f"创建文件夹: {xlsxdirname}") os.makedirs(xlsxpath) self.xlsxpath = xlsxpath def batch_convert(self): xls_files = glob.glob(self.path + "/*.xls") if len(xls_files) != 0: print('当前目录下的xls格式文件:') for file in xls_files: print(os.path.basename(file)) fname, _ = os.path.splitext(file) basename = os.path.basename(fname) xlsxpathname = os.
OHIF
OHIF,全称为Open Health Imaging Foundation,致力于创造一个平台,使得大家可以:使用最少的资源开发出创新的软件;使用开源组件开发产品化软件;科研成果可以高效转化为临床工具。
作为示例,OHIF开发了两个前端软件,分别是OHIF-viewer和LesionTracker。这两个软件都是基于Cornerstone开发的,都遵循MIT协议,允许商用。其中,前者是一个通用的纯网页版医学影像浏览前端;后者则面向病灶(肿瘤)随访提供了更加专业的工具组件。
OHIF Viewer包含了日常放射影像浏览与测量的各项基础功能。
教程
详解
反正暴力不拿offer的,复习举一反三的迭代遍历,对于树,一定要有对局部节点和整体树的思考。有空复习莫里斯遍历 struct TreeNode { /* data */ int val; TreeNode* left; TreeNode* right; }; //前序的模拟有两种,1.先存左子树然后弹出找右子树 2.往栈里放的时候就先放右 再放左 按栈顶弹出左右 //前序 中 左 右 vector<int> preOrderIterationBTree(TreeNode* head){ vector<int> res; stack<TreeNode*> s; TreeNode* node = head; //s.push(head); while(node!=nullptr || !s.empty()){ //栈不为空且节点不null,栈里存放所有左子树节点 while(node!=nullptr){ res.push_back(node->val);//记录操作 s.push(node); node = node->left; } //左节点存放完毕,取出栈顶节点,回到上一个中节点, node = s.top(); s.pop(); node = node->right; } return res; } // 中 左 右输出, 先压右 再压左 那么栈输出就是 左 右 输出 vector<int> preOrderIterationBTree2(TreeNode* head){ vector<int> res; stack<TreeNode*> s; TreeNode* node = head; s.
文章目录 129、求根节点到叶节点数字之和508、出现次数最多的子树元素和面试题0412求和路径 129、求根节点到叶节点数字之和 给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。
每条从根节点到叶节点的路径都代表一个数字:
例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。 计算从根节点到叶节点生成的 所有数字之和 。
叶节点 是指没有子节点的节点。
示例1:
输入:root = [1,2,3] 输出:25 解释: 从根到叶子节点路径 1->2 代表数字 12 从根到叶子节点路径 1->3 代表数字 13 因此,数字总和 = 12 + 13 = 25 示例2:
输入:root = [4,9,0,5,1] 输出:1026 解释: 从根到叶子节点路径 4->9->5 代表数字 495 从根到叶子节点路径 4->9->1 代表数字 491 从根到叶子节点路径 4->0 代表数字 40 因此,数字总和 = 495 + 491 + 40 = 1026 思路:
对于 I S O / I E C 7816 ISO/IEC\quad 7816 ISO/IEC7816协议的介绍我直接将维基百科和 I S O ISO ISO组织的该协议的标准文档中的介绍复制了过来:
维基百科:ISO/IEC 7816 is an international standard related to electronic identification cards with contacts, especially smart cards, and more recently, contactless mobile devices, managed jointly by the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC).It is edited by the Joint technical committee (JTC) 1 / Sub-Committee (SC) 17, Cards and personal identification.
SpringBoot实现用户定制的定时任务(动态定时任务) 文章目录 SpringBoot实现用户定制的定时任务(动态定时任务)情景实现实体类CronService层:接口CronService以及其实现类CronServiceImpl定时任务管理器CronManageTask 情景 我们知道SpringBoot能使用@Scheduled注解来进行定时任务的控制,该注解需要配合Cron表达式以及在启动类上添加@EnableScheduling注解才能使用。
不过我们现在的假定情景并不是程序员设定的定时任务,而是用户可以在我们的网页上定制定时任务,前端将该任务的信息发送到后端后,后端可以将此任务存入数据库并在规定的时间内执行。例如用户可以设定定时任务的执行时间段,执行时刻等,并可以随时新增、删除和改变定时任务。
接下来我们来使用SpringBoot实现这个假定情景
实现 实体类Cron 我们需要创建实体类Cron代表定时任务,这里假设Cron有如下属性:执行时刻、任务标题、任务开始的日期、任务截止日期,以及存入数据库所需要的几个基本属性:id(作为主键)、创建时间、更新时间、状态status
我们用一个BaseEntity来保存基本属性,Cron将继承BaseEntity,使用MyBatisPlus作为ORM框架,Cron的代码如下:
@Data @EqualsAndHashCode(callSuper = true) public class Cron extends BaseEntity { private static final long serialVersionUID = 1L; @NotNull(message = "执行时刻不能为空") private LocalTime executeTime; @NotBlank(message = "标题不能为空") private String title; @NotNull(message = "截止日期不能为空") private LocalDate deadTime; @NotNull(message = "开始日期不能为空") private LocalDate startTime; } 这里需要注意的是lombok的@Data注解相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。
其中,@EqualsAndHashCode注解会生成equals(Object other) 和 hashCode()方法。我们重写了equals(Object other) 和 hashCode()方法,就是为了在两个对象的属性相同时equals能返回true,认为它们两个相同。但@EqualsAndHashCode默认仅使用该类中定义的属性且不会调用父类的equals(Object other) 和 hashCode()方法。这是什么意思呢?仅使用该类中的属性,也就是如果该类的两个对象属性相同,即使这两个对象对应父类的属性不同,equals也会认为它们两个对象相同,从而返回true。默认的实现中不使用父类的属性,将会导致问题,比如,有多个类有相同的部分属性,恰好id(数据库主键)在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。所以我们在使用@Data时同时需要加上@EqualsAndHashCode(callSuper=true)注解来解决这一问题,加上(callSuper=true),其生成的equals(Object other) 和 hashCode()方法将调用父类的方法,也就是会考虑父类的属性。
参考 module ‘tensorflow‘ has no attribute ‘get_default_graph‘ - 云+社区 - 腾讯云
module 'tensorflow' has no attribute 'get_default_graph' 当我使用keras和tensorflow做深度学习的时候,python3.6报了这个错误,这个问题源自于keras和TensorFlow的版本过高导致模块不存在或者已经更改不再兼容
解决办法,降级TensorFlow和keras
pip uninstall tensorflow # 卸载tf pip uninstall keras # 卸载keras 安装1.2.0的tf 和 2.0.9的keras
pip install tensorflow==1.2.0 pip install keras==2.0.9
最近在做腾讯云一键部署EKS容器的事情,公司的所有微服务都放到腾讯云上管理,并且把所有的操作通过一键部署的形式实现.因为公司是做Saas服务, 所以不同的租户, 通过应用进行隔离, 也就是每个租户一套系统.所有的原来通过控制台用手点击的操作,全都通过代码实现. 今天用这套程序测试了一下效率,中途遇到的问题,在此总结一下.
首先整理一下多租户实现的思路
每个租户给分配一个租户id,所有的腾讯云资源都基于这个租户id,比如,租户id是p218, 那么租户的数据库实例取名为p210-mysql, 类似的还有p218-redis, p218-rabbitmq, p218-net, p218-subnet,等等.
调接口的流程大概如下:
首先查用户的网络和子网, 存到一个上下文变量,然后查用户的redis实例, mq实例, 都存到上下文变量, 然后查数据库实例,这里需要提前配置好mysql的root用户名密码, 然后组装sql文件, 上传到腾讯的COS, 拿到cos的地址后, 数据库进行数据初始化, 然后再创建数据库用户, 给数据库用户赋权. 把用户的用户名,密码等也存到上下文变量里. 接下来就是创建容器的EKS集群, 创建完之后, 调接口开通EKS的外网,并且添加白名单ip, 开通之后, 拿到kubectl的config文件, 用来创建k8s容器负载. 接下来就创建负载, 创建svc, 创建ingress, 域名解析.
调用K8S的接口总结
k8s的接口其实是kubectl直接可以调用,相当于我们本地生产一个kubectl的客户端.这个步骤需要的就是集群的config文件.因为是java代码,所以需要有统一的java调用的sdk.
首先上k8s的文档地址: 因为都是英文文档, 所有看的时候,还挺不错的
Kubernetes API Reference Docs
腾讯云接口调用总结
腾讯云的接口还是有很完善的文档的,这个小伙伴们倒是不用担心,只要按照文档来就可以,而且, 不管是腾讯还是阿里, 都会提供给开发者一个调用工具, 这个使用好,一般就没问题.
具体代码,可以访问 https://www.inbai.net/article/124.html 查找,会相继把一键部署代码贴出来
本来想多写一点的,腾讯云EKS一键部署k8s容器总结确实有很多内容, 因为一边调试,一边部署,也着实花了一些时间,下次上代码, 通过整套一键部署代码,10多个微服务都直接在容器里运行,给大家用代码讲讲.
KMP是一个字符串匹配算法,对于原本的暴力朴素做法进行了优化,使得时间复杂度大大降低,它的名字是取三个发明人的名字缩写。
一、KMP算法基本概念与核心思想 基本概念:
① s[ ]是 模式串:较长字符串,② p[ ]是 模板串,较短字符串。③ “非平凡前缀”:指 除了最后一个字符以外,一个字符串的 全部头部组合(前面连续的部分)④ “非平凡后缀”:指 除了第一个字符以外,一个字符串的 全部尾部组合。(后面均简称为 前/后缀)⑤ “部分匹配值”:前缀和后缀 的 最长共有元素 的 长度。⑥ next[ ]是“部分匹配值表”,即next数组,它存储的是每一个下标对应的“部分匹配值”,是KMP算法的核心。 核心思想:
在每次失配时,不是把p串往后移一位,而是把p串往后移动至下一次可以和前面部分匹配的位置,
这样就可以 跳过大多数的失配步骤。
每次p串移动的步数通过查找next[ ]数组确定的。
二、next数组的含义 含义:next[ j ] 表示p[ 1, j ]串中前缀和后缀相同的最大长度(部分匹配值),
即:p[ 1, next[ j ] ] = p[ j - next[ j ] + 1, j ](前后缀相同,两者都达到最大)
举个例子,例如:
为了对next数组有更清晰的认知,我们手动模拟一下next数组
假设 模板串 p = “abcab”,
则对于next[1]:前缀集合为空,后缀集合为空,next[1] = 0;
next[2]:前缀集合 { “a” },后缀集合 { “b” },两集合中无匹配字符串,next[2] = 0;
安全方向人才招聘 文章目录 安全方向人才招聘前言安全人员基本技能web安全工程师web安全研发工程师安全运维工程师安全测试工程师Windows逆向工程师Android安全工程师系统研发工程师安全产品运营员风控安全工程师安全服务工程师(乙方)技术支持工程师(乙方) 前言 21世纪是信息化时代,我们的生活越来越离不开网络,但是与此同时,网页篡改、计算机病毒、系统非法入侵、数据泄密、网站欺骗、服务瘫痪、漏洞非法利用等信息安全事件时有发生,网络安全越来越被重视。但是由于我国网络安全起步晚,所以现在网络安全工程师十分紧缺。
根据职友集的数据显示,当前市场上需求量较大的几类网络安全岗位,如安全运维、渗透测试、等保测评等,平均薪资水平都在10k左右。
随着经验和水平的不断增长,网络安全工程师可以胜任更高阶的安全架构、安全管理岗位,薪资更是可达30k。
网络安全工程师的工作还有以下几个优点:
1、职业寿命长:网络工程师工作的重点在于对企业信息化建设和维护,其中包含技术及管理等方面的工作,工作相对稳定,随着项目经验的不断增长和对行业背景的深入了解,会越老越吃香。
2、发展空间大:在企业内部,网络工程师基本处于“双高”地位,即地位高、待遇高。就业面广,一专多能,实践经验适用于各个领域。
3、增值潜力大:掌握企业核心网络架构、安全技术,具有不可替代的竞争优势。职业价值随着自身经验的丰富以及项目运作的成熟,升值空间一路看涨。
最后一点说一下国家政策方面:
2015年7月的通过的《国家安全法》和2016年12月,国家互联网信息办公室发布《国家网络空间安全战略》都明确的规定了,国家建设网络于信息安全保障体系的建设,提升网络与信息保护能力等方面,也能比较清楚的明白国家对网络安全的重视程度。
现在参加网络安全培训还来得及吗?
现在专门来做网络安全的人才还是很稀缺,所以现在学习网络安全肯定是来的及的。只需要你自己选择好正确的方法以及合适的方式,一定可以学会的。
安全人员基本技能 了解行业发展,目前大公司的产品和业务;熟悉GTD时间管理方式;能独立安装Windows/Ubuntu系统和虚拟机;客户端与服务器通信过程;浏览器插件与使用技巧(Firebug);突破网络限制,建立自己的私有网络(VPN,Wireshark);针对每种语言的开发工具(Sublime,Ulipad等),git的使用技巧;Office编辑与格式注意(标题、封面、页眉、页码、字体等);英语水平良好,能阅读各种英文技术文档。 web安全工程师 熟悉主流的Web安全技术,包括SQL注入、XSS、CSRF、一句话木马等安全风险;熟悉国内外主流安全产品和工具,如:Nessus、Nmap、AWVS、Burp、Appscan等;熟悉windows、linux平台渗透测试、后门分析、加固;至少掌握一门编程语言C/C++/Perl/Python/PHP/Go/Java等;熟悉渗透测试的步骤、方法、流程,具有Web安全实战经验;熟悉常见安全攻防技术,对网络安全、系统安全、应用安全有深入的理解和自己的认识;对Web安全整体有深刻理解,具备代码审计和独立漏洞挖掘能力;具有较强的团队意识,高度的责任感,文档、方案能力优秀者优先。 web安全研发工程师 能熟练应用一门或几门以下的技术:PHP/Python/Shell/JavaScript/Ajax,熟练把握LNMP开发;熟悉MYSQL数据库开发、配置、维护、性能优化;优秀的数据库设计和优化能力,至少精通一种数据库应用,mysql、redis、mongodb加分;熟悉Linux下的开发,熟悉网络开发,具备一定的系统调优能力;了解常见安全攻击和漏洞及系统化的防护方案;必须拥有良好的职业道德,责任心,团队合作精神,代码风格; 大访问量网站建设或数据库建设经验优先。 安全运维工程师 熟悉主流的Web安全技术,包括SQL注入、XSS、CSRF等OWASP TOP 10安全风险;
熟悉Linux/Windows下系统和软件的安全配置与加固;
熟悉常见的安全产品及原理,例如IDS、IPS、防火墙等;
掌握常见系统、应用的日志分析方法;
熟练掌握C/PHP/Perl/Python/Shell等1或多种语言;
具有安全事件挖掘、调查取证经验;
网络基础扎实,熟悉TCP/IP协议,二层转发和三层路由的原理,动态路由协议,常用的应用层协议;
较好的文档撰写能力、语言表达和与沟通能力。
安全测试工程师 熟悉常见安全攻防技术和安全漏洞,熟练使用常用渗透测试工具;熟悉PC客户端软件、手机客户端(Android、iOS)软件的测试流程和方法;熟悉常见的代码审计或白盒测试工具;熟练使用C/C++/PHP/Java/JavaScript/Python一到两种;具有良好的技术文档撰写能力,具有良好的沟通能力及协调能力;良好的职业道德,责任心,团队合作精神。 Windows逆向工程师 熟悉x86/x64系列汇编语言、c/c++语言,能熟练读懂汇编代码;有较好的逆向功底,熟练使用IDA、Windbg、Ollydbg、Immunity
Debugger、Bindiff等分析工具以及Metasploit等渗透测试工具;至少掌握一门编程语言,包括C/C++/python/ruby/perl/javascript;熟悉浏览器、office、adobe以及flash等软件内部工作原理以及相应软件漏洞分析与利用技术优先;
5…熟悉操作系统的相关安全机制,掌握绕过漏洞缓解措施的基本方法;熟悉windows系统安全,掌握windows核心编程优先;熟悉漏洞挖掘和分析相关技术、工具以及平台,如Fuzzing测试,补丁比较、符号执行技术等。能够流畅的阅读漏洞方面的英文资料,具备较强的漏洞学习和理解能力;熟悉技术文档的写作、PPT制作、具备基本的工作汇报能力;学习能力强、富有团队精神、有责任心和进取能力;written by: coolsmurfs Android安全工程师 熟悉Android开发环境,能够较为熟练的开发Android程序;了解ARM、Smali汇编语言;熟悉IDA、Gdb等调试分析工具;有Android漏洞挖掘、漏洞利用经验优先;最好熟悉Android/Linux底层框架,熟悉系统的工作原理和细节;最好能够深入研究Android系统底层,分析漏洞和潜在风险;最好能够跟踪国内外的Android安全动态,分享Android安全的最新技术。 系统研发工程师 熟练掌握Linux/Unix或Windows平台的各种开发技能;熟悉常用算法和数据结构,熟悉网络编程、多线程编程技术 ;熟悉Linux下的开发,网络安全、Linux系统安全;了解常见的应用层安全工具开发、了解APP安全;具备一定的系统调优能力,具有良好的分析和解决问题能力 ;善于学习和运用新知识, 对业界安全动态较为敏感;具有良好的沟通表达能力和团队协作能力。 安全产品运营员 有安全类产品设计或运营经验者优先;对网络安全相关知识有一定了解;能够对各项有效资源进行整合,善于协调跨部门合作,优秀的沟通技巧;对数据敏感,善于数据统计分析,逻辑清晰;高度的责任心和合作精神,良好的文字表达能力;工作积极、善于学习、细致耐心、勇于接受挑战。 风控安全工程师 熟悉Python/Java/PHP中的一种开发语言;熟悉 Linux 系统以及 服务器端开发经验;熟悉分布式系统部署与开发;对数据有亲切感,主动性强,细心,思维敏捷;有安全相关系统研发经验者优先;有很强的逻辑分析能力,对发现和思考问题充满乐趣;有反作弊、安全、数据分析专业领域经验优先。 安全服务工程师(乙方) 有较强学习能力,能快速学习新的技术;熟悉风险评估、应急响应、渗透测试、安全加固等安全服务;熟悉常见黑客攻防方法;掌握一门编程语言;具有良好的语言表达能力、文档组织能力。write by:sec_qiaoy 技术支持工程师(乙方) 精通TCP/IP协议,熟悉网络交换原理和各类路由协议,可熟练调试路由交换设备。熟悉常见操作系统和数据库。熟悉公司各类安全产品特性与配置,完成产品部署上线。熟悉集成类项目管理,稳步推进项目开展。熟悉招投标流程,可独立完成标书制作与产品演示。良好的沟通能力。Write by:hblf
web渗透学习路线 文章目录 *web渗透学习路线*前言一、web渗透测试是什么?二、web渗透步骤1.前期工作2.中期提高3.后期打牢 总结 前言 本文整理的学习路线,清晰明了,重点分明,能快速上手实践,相信想学的同学们都能轻松学完。都是干货啦,先收藏⭐再看吧。本文偏基础能让萌新们快速摸到渗透测试的门道,少走弯路,也能让正在学习的小伙伴们查漏补缺,也欢迎大佬们在评论区指正错误~
这里附上我之前学习的路线图
一、web渗透测试是什么? Web渗透测试分为白盒测试和黑盒测试,白盒测试是指目标网站的源码等信息的情况下对其渗透,相当于代码分析审计。而黑盒测试则是在对该网站系统信息不知情的情况下渗透,以下所说的Web渗透就是黑盒渗透。
二、web渗透步骤 Web渗透分为以下几个步骤,信息收集,漏洞扫描,漏洞利用,提权,内网渗透,留后门,清理痕迹。一般的渗透思路就是看是否有注入漏洞,然后注入得到后台管理员账号密码,登录后台,上传小马,再通过小马上传大马,提权,内网转发,进行内网渗透,扫描内网c段存活主机及开放端口,看其主机有无可利用漏洞(nessus)端口(nmap)对应服务及可能存在的漏洞,对其利用(msf)拿下内网,留下后门,清理痕迹。或者看是否有上传文件的地方,上传一句话木马,再用菜刀链接,拿到数据库并可执行cmd命令,可继续上大马…思路很多,很多时候成不成功可能就是一个思路的问题,技术可以不高,思路一定得骚。
1.前期工作 html+css+js
前端三要素 html、css、js是被浏览器解析的代码,是构成静态页面的基础。也是前端漏洞如xss、csrf的基础。
重点了解html和js
能力要求:能够写出简单表单,能够通过js获取DOM元素,控制DOM树即可。
apache+php
推荐使用phpstudy来进行傻瓜式安装,可以少走很多弯路。通过apache+php体会一下网站后端的工作,客户端浏览器通过请求apache服务器上的php脚本,php执行后生成的html页面返回给浏览器进行解析。
重点了解php
能力要求:了解基本网站原理,了解php基本语法,开发简单动态页面
mysql
之前已经安装的phpstudy可以轻易的安装mysql。mysql是一款典型的关系型数据库,一般来说,大部分网站都会带有数据库进行数据存储。
重点了解sql语句
能力要求: 能够用sql语句实现增删改查,并且能用php+mysql开发一个增删改查的管理系统(如学生管理系统)
python
虽然 “php是最好的语言”,但它主要还是应用在服务端做网站开发,我们搞安全经常需要写一些脚本或工具来进行诸如密码爆破、目录扫描、攻击自动化等操作,需要一个方便且趁手的编程语言,这里我推荐python
重点学习requests、BeautifulSoup、re这三个库
能力要求: 了解python基础语法,能够用python爬取网站上的信息(requests+BeautifulSoup+re)
burpsuite
web安全的工具很多,但我觉得必备的渗透工具还得是它
重点学习Proxy、Repeater、Intruder三个模块,分别用于抓包放包、重放包、爆破
初步使用即可,在中期的漏洞学习中去逐渐熟练它
能力要求: 能够用burpsuite抓包改包、爆破用户名密码
2.中期提高 此时我们对网站已经不再陌生,能够自己动手完成一个简单站点。但我们写出来的代码真的安全吗?进入中期,我们便要开始着眼经典漏洞的学习。
一个漏洞的学习,要搞明白三点(每学完一个漏洞就问自己这三个问题):
如何利用这个漏洞进行恶意操作? 为什么会产生这个漏洞? 如何修复这个漏洞? SQL注入
(1) 了解产生sql注入的原理
(2) Union注入
(3) POST类型注入
(4) 万能用户
(5) 盲注
能力要求: 能够手工注入出任意表的数据,熟悉三种盲注的手法,能够通过sql注入实现任意文件读取和任意文件写入,能够自己编写一个不含sql注入的查询功能
文件上传
(1) 了解原理
(2) 会编写一句话木马
(3) 会用cmd命令吧一句话木马与图片结合
(4) 利用一句话木马getshell
能力要求: 会写php的webshell,明白webshell的原理,熟悉常见的文件上传绕过方法(如过后缀检测、过文件头检测、过MIME类型检测),能够自己编写一个不含漏洞的上传功能
文件包含
解压MySQL安装包并找到对应路径,如下图
配置mysql的环境变量,创建MYSQL_HOME,并且在Path添加上%MYSQL_HOME%\bin;
配置my.ini. 并把my.ini放到bin目录下(1.如果放在MySQL-5.6.50-winx64 目录下,在下面执行net start mysql时可能无法启动MYSQL服务,不会自动生成data)
以管理员身份进入命令行(可在WIN+R输入cmd),输入"G:"进入盘,再输入“cd G:\programFiles\mysql-5.6.50-winx64\bin”
目录下输入命令:mysqld --initialize-insecure (生成无密码的root用户) 后,在MySQL-5.6.50-winx64 目录下就会出现data文件
启动MySQL服务,命令:net start mysql
设置密码 mysqladmin -u root password 密码
8.修改密码方法如下 :接着输入mysql -uroot -p 由于之前登陆过,直接输入刚才设置密码(登录root第一次是免密码的直接回车进入到) MYSQL>
接着输入:update mysql.user set authentication_string=password(‘你想输入的密码’) where user=‘root’ and Host =‘localhost’; 然后接着再输入: flush privileges;
输入命令show databases; 查看数据表
输入 \q; 退出MySQL
关闭MySQL服务,命令:net stop mysql
写于2022.02.25 此时python最新版本为3.10.2 自学python,安装配置环境的流程记录,以便查阅。互相学习。
1.准备 (1)python的安装包
这个直接上python的官网下载最新版就行
python官网
(2)vscode的安装包
到微软的官方网站下载
vscode下载位置
2.安装python (1)安装
第一次安装的话,如果安装程序推荐的路径自己不太容易找到的话,建议使用自定义安装,往后要安装其他版本的python解释器的话,也安装在同一个位置,这样比较好找。
例如C:\Program Files\Python\Python39
C:\Program Files\Python\Python310 因为,为vscod添加python解释器可能需要指定python.exe文件的位置,而这个文件就在python的安装文件夹里。
开始安装界面
在1号位置的选框,不想手动添加环境变量记得勾选上。
选择install Now的话可以跳到安装vscode处
上面的install launcher for all users是由于我已经安装过了,所以大不了勾,第一次安装要勾上。不然就不能使用py命令
这里我选择手动添加环境变量,就不勾选1号选框了,同时选择自定义安装:customize installation
2和3是必勾选的
2号是安装第三方库用的,3号是tkinter模块有些python的标准库里的模块需要它的支持。
4号和其他的框无所谓,我也不知道有什么用
下面灰色的那两个选框是和py命令有关的,第一次安装时勾上,后面安装其他版本python时就不用勾了。
然后next
第一次安装python要把第3个勾选上,不然python自带的IDLE不好找
不需要IDLE就不需要勾选
其他的按图上勾即可,我也才学不久最后两个选框的功能不是太清楚
然后点击install等待进度条完成即可
(2)添加环境变量
win11中打开设置,点击系统,下滑到底部,点击关于
选择‘‘高级系统设置’’
点击‘’高级‘’选项卡,然后点击‘’环境变量‘’
在弹出的窗口里,系统变量那里找到‘path’这个变量,单击它,然后选择编辑
这里安装的每个版本的python都要添加两句,例如我的是3.10版本:
C:\Program Files\Python310
C:\Program Files\Python310\Scripts
这个''C:\Program Files\Python310"是你安装的python的文件夹路径
然后点确定保存
回到桌面,在任务栏鼠标对着微软的徽标(开始按钮)单击右键,打开‘运行’选项。输入cmd打开命令窗口。
win10的话,可以直接鼠标对着桌面空白处,按住shift单击鼠标右键,打开‘’在此处打开powershell窗口‘’,来打开命令窗口
英文输入法下,输入python并回车,窗口上出现python和对应版本号,那么便安装成功了
如果不是第一次安装python
就在窗口输入py -0 ,窗口会输出当前电脑已有的python版本,查看是否有刚刚安装的对应版本。
有些电脑不显示,暂时没找到解决方法
3.安装vscode 这个相对比较简单,把能勾的都勾上,不断下一步,安装即可
安装位置看自己喜欢的
4.配置vscode 打开vscode后,先到点到拓展选项
第一次启动是英文界面,可以先在搜索框输入Chinese,安装中文包,安装好后重启
然后在搜索框搜索python,安装第一个
安装完成后页面会有些变化,那个页面不用去在意。由于我已经安装过了,所以不会出现那个界面
接下来按ctrl+shift+P,在弹出的命令面板里输入
python:select interpreter
Ubuntu系统 配置docker tcp访问 网上大部分配置方法为直接修改/lib/systemd/system/docker.service文件,本人试了没有效果,最后参考官网的方式:https://docs.docker.com/engine/install/linux-postinstall/#configure-where-the-docker-daemon-listens-for-connections
使用systemctl直接编辑docker.service的配置:
sudo EDITOR=vim systemctl edit docker.service 不会用 systemctl edit,上面的命令为使用vim编辑器编辑。
在里面贴上如下内容:
[Service] ExecStart= ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 重新加载系统服务配置文件(包含刚刚修改的文件)
systemctl daemon-reload 重启docker服务
systemctl restart docker 使用如下命令查看tcp访问端口是否开启
sudo netstat -lntp | grep dockerd 执行下面命令可以利用tcp连接看到docker版本信息
curl dgx.server.ustb-ai3d.cn:2375/version 上面的官网链接还介绍了配置daemon.json实现tcp连接的方法。
部署图(deploymentdiagram,配置图)是用来显示系统中软件和硬件的物理架构。从部署图中,您可以了解到软件和硬件组件之间的物理关系以及处理节点的组件分布情况。使用部署图可以显示运行时系统的结构,同时还传达构成应用程序的硬件和软件元素的配置和部署方式。
部署图它阐述了在实际应用中软件和它的运行环境的关系,并且描述了软件部署在硬件上的具体方式。
部署图中的主要元素包括节点与节点之间的关联关系。此外,部署图中也可以使用注解和约束。
节点,node节点是存在与运行时的代表计算机资源的物理元素,可以是硬件也可以是运行其上的软件系统。
这里
构件(Artifact)
构件是软件开发过程中的产物,包括过程模型(比如用例图、设计图等等)、源代码、可执行程序、设计文档、测试报告、需求原型、用户手册等等。
构件表示如下,带有关键字«artifact»和文档图标:
部署图的基本元素是节点node,节点一般出现在通信流程图中,或者链式结构中。
节点可以理解位逻辑或现实中的block。一个程序模块,或者一台PC。
硬件,软件构件,组建间的关系图,分布图。
例如在 多核处理器上 部署操作系统OS,和数据处理组建
也或者
或者是 节点间的连接情况
ESP8266的网页web交互界面 arduino的菜单库
https://github.com/neu-rah/ArduinoMenu 自带生成html界面
https://github.com/Hieromon/PageBuilder star很多的esp固件
https://github.com/arendst/Tasmota ESP UI
https://github.com/s00500/ESPUI 方法:
通过html上的JavaScript脚本向服务器put或pose实现交互 ESP8266做web服务器 https://swf.com.tw/?p=905
按照图中的结构将网页文件放在data文件夹中,然后在arduino中上传到spiffs
void rootRouter() { File file = SPIFFS.open("/index.htm", "r");//fs以data作为根目录,里面的index.htm的地址就是/index.htm,如果由文件夹image,里面的图片地址就是/image/xxx.png server.streamFile(file, "text/html"); file.close(); } void setup() { ......//连接wifi server.on("/index.htm", rootRouter);//如果访问的网址是http://192.168.124.8/index.htm时,url是/index.htm,给回调函数rootRouter处理 } 但是这样有个弊端,就是每个url都需要写一个回调函数,比如html里面还有调用了图片,浏览器就会向esp8266更具url请求这个图片,但是esp8266没有写这个图片的url处理函数,所以就会显示不出来
改进方法 String getContentType(String filename){ //通过url的结尾包含哪些字符,判断是什么格式 if(server.hasArg("download")) return "application/octet-stream"; else if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".png")) return "image/png"; else if(filename.endsWith(".gif")) return "image/gif"; else if(filename.endsWith(".jpg")) return "
二者的特性 方法类型:接口只能有抽象方法。抽象类可以有抽象方法和非抽象方法。从Java 8 开始,抽象类可以有默认(default)方法和静态方法。Final变量:接口中的变量默认是final的。抽象类可能包含非final的变量。变量类型:抽象类可以有final、非final、静态、非静态类型的变量。接口只能有静态类型的变量和final类型的变量。实现: 抽象类可以实现接口,接口不能实现抽象类。关键字:一个是implement,一个是extend。多实现:接口只能extend另一个接口。抽象类既可以implement,又可以extend。数据成员访问性:接口的数据成员是public的。抽象类可以有public private protected等等。 如何选择 应该用抽象类的场景通常包含以下特点:
想要在相关的的类之间共享一些代码希望实现抽象类的子类们有大量相同的属性希望声明非静态的或者非final的属性。这类属性通常是一个对象的,可能被修改的状态。 应该用接口的场景通常包含以下特点:
希望不相干的类去实现一些相同的方法(比如各种各样的类都想实现序列化方法)你想利用多继承特性
方法1、 主要有以下几种方法:
1、新购买的打印机都会有自带的驱动软件安装光盘,如果你电脑上有光驱的话,直接安装上就可以了;如果没有光驱那就到所购买的打印机品牌官网上去找对应型号的驱动下载安装上,再把打印机USB数据线连接到电脑上就可以了,系统会自动检测到打印机,然后选择自动添加,点几个下一步就能完成了;
2、如果是一台旧打印机,首先到品牌官方网站上找驱动程序下载安装,如果官网上已经没有这个型号的驱动了,那就找一些第三方的网站去下载,不过这里比较危险的是很多网站都是为了推广或者赚钱,而自带一些其他软件的安装程序,甚至是带病毒,很可能到最后你真正想要的驱动没下载下来,倒是下载安装了一堆没用的软件,最倒霉的是可能带病毒使你的电脑系统出问题甚至崩溃,所以这里不建议在没有专业人员指导的情况下自己搜索下载驱动程序,如果真要自己找,那也一定注意安装过程中的一些陷阱,在安装时一定每一步都检查是否有隐藏的勾选项,把不需要的软件全部把勾去掉,直至安装完成的最后一步;
3、使用驱动软件:先把打印机USB数据线连接到电脑上,然后找到一个比较靠谱的驱动软件,比如xx精灵、xx人生之类的,让它自动检测一下,就会找到你的打印机,直接选择安装就可以比较安全的完成驱动的安装了,除非你的打印机是非常小众的品牌和型号,要不都是会比较容易成功的;
4、添加网络打印机:在办公环境中,很多时候是几个人或者几十个人共用一台打印机的,这个时候添加打印机就和上述的方法有些不同了,首先网络打印机有两种情况,一是打印机连接在一台电脑上,然后共享出来供其他人连接打印,二是网络打印机是通过网线连接到局域网内供大家一起使用;这个需要详细介绍,下一篇文章再讲;
5、手动添加打印机:这是在系统无法自动添加成功的情况下选择的方法,这里也放到下一篇文章和第四种添加网络打印机的方法一起介绍;
共享打印机 1、首先是这台打印机已经成功安装到了一台电脑上,能够正常打印,然后需要我们把这台打印机进行共享设置,具体的共享方法这里就不讲了,我会另写文章介绍,设置好共享后,在另外一台需要连接这台打印机的电脑上进行以下操作:
打开控制面板,找到并选择“设备和打印机”,在弹出的对话框里点击“添加打印机”,然后点击“添加网络、无线或Bluetooth打印机(W)”就会弹出另一个对话框,对话框中会搜索网络中的打印机,这时我之前文章中提到过的更改计算机名的作用就体现出来了,打印机连接的电脑更改过计算机名的话,就可以一目了然的找到它共享出来的打印机了,直接双击这个打印机就可以进行添加了,不过这一步之前你需要先下载安装好打印机的驱动程序在新的电脑上,这里就只能到官网或者第三方网站下载安装了,使用驱动软件安装是行不通的;如果在对话框中没有找到你需要的打印机,也可以点击“我需要的打印机不在列表中(R)”选择“浏览打印机”点击下一步,就会出现网络中的所有电脑,找到打印机连接的计算机名双击,再双击打印机(有的电脑可能需要输入用户名称和开机密码),点下一步直至完成就可以了;
2、打印机通过网线连接进局域网的情况下,也有两种情况,没有固定IP地址,和有固定IP地址,添加打印机的步骤如下:
没有固定IP地址:打开“设备和打印机”,点击“添加打印机” 然后点击“添加网络、无线或Bluetooth打印机(W)”在对话框中找到搜索到的打印机型号,双击然后下一步至完成即可,前提依然是先安装好驱动程序;
有固定IP地址:方法一是和没有固定IP地址一样,不过搜索到的打印机显示后缀有IP地址(上面的图中有);方法二是打开“设备和打印机”,点击“添加打印机”选择“添加本地打印机(L)”在选择打印机端口项里面选择“创建新端口”端口类型选择“standard TCP/IP
Port”点击下一步,在“主机名或IP地址(A)”框里输入打印机的IP地址点击下一步,然后找到你已经安装好的打印机型号双击添加完成即可;如果你有打印机的驱动文件,也可以点击浏览,找到这个文件进行添加打印机,效果是一样的。
最后再补充一个手动添加打印机的方法:
点击屏幕左下角开始菜单,或者到控制面板里找到并选择“设备和打印机”,在弹出的对话框里点击“添加打印机”, 选择“添加本地打印机(L)”在“使用现有端口(U)”项后面选择USB的端口,点下一步,就会出现已经连接到这台电脑的打印机型号,选择后点下一步,自动安装即可,如果你有打印机的驱动文件,可以选择“从磁盘安装”找到你的驱动文件进行安装。
以上就是正常情况下的添加打印机的全部方法了。
参考链接 :
电脑如何添加打印机的方法(2)
https://www.jianshu.com/p/e84c982e09da
电脑如何添加打印机的方法(1) :
https://www.jianshu.com/p/fbfcf82721a0
题目来源:
题库 - AcWing
目录
DFS和BFS模板题目:迷宫类
机器人的运动范围
字母
迷宫
红与黑
棋盘问题
马走日
全球变暖
DFS综合类
乘积最大(提高课)
单词接龙(提高课)
取石子游戏(dfs数学推理)
机器人的运动范围
BFS:
class Solution { public: int get_sum(pair<int, int> p) { int s = 0; while (p.first) { s += p.first % 10; p.first /= 10; } while (p.second) { s += p.second % 10; p.second /= 10; } return s; } int movingCount(int threshold, int rows, int cols) { if (!rows || !
---nginx安装步骤,不详述,请查看nginx系列篇,安装。---nginx安装教程
1.下载nginx_upstream_check_module模块 nginx_upstream_check_module-master.zip
[root@localhost /home ]#wget https://codeload.github.com/yaoweibin/nginx_upstream_check_module/zip/master 2.解压 将nginx_upstream_check_module-master.zip解压到/usr/local
3.进入nginx源码目录 [root@localhost nginx-1.16.1]# 备注:如果是已安装已启动nginx,请先停止nginx服务。
4.打补丁 [root@localhost nginx-1.16.1]#patch -p1 < /usr/local/nginx_upstream_check_module-master/check_1.14.0+.patch 这里要留意,找寻与nginx版本配套的补丁。我当前安装的nginx是1.16.1,因此补丁为check_1.14.0+.patch
如果patch命令不存在,请先安装此命令。
5.重新配置模块 #配置---加了健康检查模块 [root@localhost nginx-1.16.1]#./configure --prefix=/usr/local/nginx-1.16.1-use --with-pcre=/usr/local/pcre-8.36 --with-zlib=/usr/local/zlib-1.2.8 --with-http_stub_status_module --with-openssl=/usr/bin/openssl --add-module=/usr/local/nginx_upstream_check_module-master #编译并安装nginx [root@localhost nginx-1.16.1]#make && make install #查看配置是否成功 [root@localhost nginx-1.16.1]#/usr/local/nginx-1.16.1-use/sbin/nginx -V nginx version: nginx/1.16.1 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) configure arguments: --prefix=/usr/local/nginx-1.16.1-use --with-pcre=/usr/local/pcre-8.36 --with-zlib=/usr/local/zlib-1.2.8 --with-http_stub_status_module --with-openssl=/usr/bin/openssl --add-module=/usr/local/nginx_upstream_check_module-master 6.修改nginx配置文件 upstream lunxun{ ip_hash; server localhost:9595; server localhost:9696; #对name这个负载均衡条目中的所有节点,每个3秒检测一次,请求2次正常则标记 realserver状态为up, #如果检测 5 次都失败,则标记 realserver的状态为down,超时时间为1秒 check interval=3000 rise=2 fall=5 timeout=1000 type=http; } #检查状态,可在浏览器访问http://xxxx/nstatus location /nstatus { check_status; access_log off; #allow IP; #deny all; } 生效 nginx_upstream_check_module模块,nginx -s reload
1、–os-shell原理 使用udf提权获取webshell,也是通过into outfile向服务器写入两个文件,一个是可以直接执行系统命令,一个是进行上传文件。
–os-shell的执行条件:
dbms为mysql,网站必须是root权限攻击者需要知道网站的绝对路径magic_quotes_gpc = off,php主动转移功能关闭 2、环境介绍 phpstudy+sqlmap
3、探测网站根目录 python3 sqlmap.py -u "127.0.0.1/sqli-labs-master/Less-1/?id=1" --sql-shell select @@datadir 通过数据库位置,我们能简单判断
1.这是一个phpstudy搭建的站点
2.可以尝试phpstudy默认目录
3.尝试构造路径:D:\phpStudy\PHPTutorial\WWW\sqli-labs-master
常见找绝对路径方法:
1.网页报错信息
2.Phpinfo,探针
3.数据库查询,暴力破解
4、查看secure_file_priv= 的值是否为空 当secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下当secure_file_priv的值没有具体值时,表示不对mysqld 的导入|导出做限制
5、测试方法功能是否关闭 magic_quotes_gpc = off,php主动转移功能关闭
6、测试 python3 sqlmap.py -u 127.0.0.1/sqli-labs-master/Less-1/?id=1 --os-shell 选择网站语言
输入网站根目录
此时我们在本地可以发现上传了两个文件:
浏览起访问tmpueaad.php上传木马文件:a.php
蚁剑成功连接:
Go Moudles 前言 一、go111 module与goproxy配置二、初始化项目三、在GoLand 中设置开启Go Modules四、直接创建使用Go Moudles的project五、引入依赖六、其它补充说明 前言 首先,明白什么是go moudles:
简单点说,go moudles就是golang的包依赖管理。
在之前,依赖管理一直使go语言被诟病,go语言从1.11开始支持使用go moudles,从1.13开始强推go moudles。
因此,使用go moudles的前提为go语言版本为1.13及以上。
Go Modules 可以提升使用其他开发者代码,即添加依赖项(模块、包)时的体验,同时让代码的正确性、安全性得到保障。并且 Go Modules 可以使用 GOPROXY 环境变量来解决中国大陆无法使用 go get 的问题。
一、go111 module与goproxy配置 1、Windows下,使用powershell来进行操作。
powershell的打开方式,可以是:
1)win + R
2)输入:powershell
就可以见到如下界面:
2、可以通过 “go env” 来查看自己的相关配置:
3、关于“ GO111MODULE ”
GO111MODULE 是一个开关,通过它可以开启或关闭 go mod 模式。
它有三个可选值:off、on、auto:
1)GO111MODULE=off禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
2)GO111MODULE=on启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
3)GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。
我们在使用go moudles时,要确保“GO111MODULE=on”。所以,我们可以通过上一步的参数信息来进行观察:
上图表明,“GO111MODULE已经符合要求,就接着跳转到下一步。
否则,我们要先对它进行设置:
go env -w GO111MODULE=on
4、设置“Goproxy”
下依赖可能会遇到被墙的问题,可以通过设置代理 GOPROXY:
设置代理:
go env GOPROXY=下面代理的其中一个:
背景介绍 在一些培训或者交流时候,希望可以留下视频后期观看,产生了视频录制需求。同时在存储时,希望可以占用本地磁盘较小的空间,并且可以看清楚视频中的字体。经过实践,选取录屏软件与转码软件,大约1小时视频转码后在300M以内。下面对软件使用做简单介绍
### 软件介绍
录屏软件使用开源的OBS,官网地址与快速下载地址为
Open Broadcaster Software | OBS
https://github.91chi.fun/https://github.com//BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-n5.0-latest-win64-gpl-5.0.zip
转码软件使用开源的ffmpeg,官网地址与快速下载地址为
FFmpeg
https://cdn-fastly.obsproject.com/downloads/OBS-Studio-27.2.3-Full-Installer-x64.exe
OBS使用介绍 安装完OBS后选择设置
设置视频参数如下,注意分辨率设置要与当前电脑一致,否则界面录制不全。
设置输出属性如下,硬件编码指使用gpu编码,软编码指使用cpu编码
然后在场景位置增加一个场景,比如“桌面录制”,添加来源为“音频输入采集”,“显示器采集”
选择完成后,中间界面可以看到屏幕预览信息,如果此时报错,一般为系统显示设置问题,可以进行百度
音频输入采集后,“混音器”部分会有“麦克风输入”与“桌面音频输出”,如果不想收集麦克风声音,需要点击输入的"小喇叭"图标静音,输出其他同理
如果要录制一个窗口,可以新建场景,选择窗口采集,窗口采集时,右键预览位置,可以设置窗口居中或者拉伸状态
注意,如果录制窗口,这个窗口可以后置,但不能最小化,最小化后无法捕捉窗口状态。
ffmpeg使用介绍 使用obs录制完成后,视频文件比较大,为了方便存储,通过转码方式降低视频质量与视频大小
ffmpeg下载完成后,解压到本地文件夹,可以看到bin目录下有ffmpeg.exe程序
接下来配置环境变量
右键此电脑-->高级系统设置-->高级-->环境变量-->系统变量-->Path-->编辑-->新增,填入上面路径
新建一个cmd窗口,输入ffmpeg -version,表示安装成功
接下来cmd中输入以下命令,即可实现转码
建议:使用intel集成显卡,修改分辨率,一般是1080 720 480,-1表示等比例缩放
ffmpeg -i "E:\项目\xxx.mp4" -vf scale=-1:720 -vcodec h264_qsv -preset slow -r 15 -x264opts keyint=75 -vcodec h264_qsv -preset slow -b:v 600k -f mp4 "E:\项目\xxx-720P.mp4"
最近接待客户的时候遇到一个做程控交换的工程师,对于信锐采用PoE系统为AP供电的方式表示很感兴趣,还特别举例以前电话线给固定电话供电时每条线路的作用等等,下面小编给大家讲讲PoE系统和802.3af(PoE)、802.3at(PoE+)、802.3bt(PoE++)三种标准。
PoE的系统构成及供电特性参数一个完整的PoE系统包括供电端设备(PSE,PowerSourcingEquipment)和受电端设备(PD,PowerDevice)两部分。信锐POE交换机就是PSE设备,无线AP或者物联网LoRa网关就是PD设备。两者基于IEEE802.3af标准建立有关受电端设备PD的连接情况、设备类型、功耗级别等方面的信息联系,并以此为根据PSE通过以太网向PD供电。
标准的五类网线有四对双绞线,IEEE802.3af允许两种线序供电方法:一种是在4、5、7、8线对上传输电流,并且规定,4、5为正极,7、8为负极。另一种供电是在1、2、3、6线上传输电源,极性较为任意,1、2为正极,3、6为负极或是1、2为负极,3、6为正极。信锐POE交换机采用第二种供电线序,信锐无线AP或者物联网LoRa网关两种供电线序都支持。
IEEE802.3af的工作过程: 1、检测:一开始PSE在为受电设备供电前,先输出一个低电压检测受电设备(PD)是否符合IEEE802.3af标准。
2、分级:当PSE检测到符合要求后,会将输出电压进一步提高,来对受电设备进行分级,如果受电设备此时没有回应分级确认电流,PSE默认将受电设备规为0级,为其提供15.4W的输出功率。
3、供电:经过确认分级后,PSE会向受电设备输出48V的直流电,并确认受电设备不超过15.4W的功率要求。
4、维护:更新实时功率,进行断路检测和单端口过载检测,当受电设备超载或短路后,PSE停止为其供电,再次进入检测阶段。
IEEE802.3af主要供电参数: 直流电压在44~57V之间,典型值为48V。典型工作电流为10~350mA,典型的输出功率:15.4W。超载检测电流为350~500mA。在空载条件下,最大需要电流为5mA。为PD设备提供3.84~12.95W四个Class等级的电功率请求。
IEEE802.3af的分级参数: Class0设备需要的最高工作功率为0~12.95W;
Class1设备需要的最高工作功率为0~3.84W;
Class2设备需要的工作功率介于3.85W~6.49W;
Class3设备的功率范围则介于6.5~12.95W。
为什么会有IEEE802.3at标准? 由于IEEE802.3af标准使受电设备(PD)上的PoE功耗被限制为12.95W,这就限制了以太网电缆供电的应用范围。为了克服PoE对功率预算的限制,推出新标准:IEEE802.3at(也称为PoE+),它将功率要求高于12.95W的设备定义为Class4,可将功率水平扩展到25W或更高。
IEEE802.3at与802.3af相比,802.3at可输出2倍以上的电力,每个端口的输出功率可在30W以上。受电设备PD可以最大到29.95W,PSE将为其提供30W以上的直流电源。PD以Class4分级的电流响应,告诉PSE是否能够为其提供802.3at规定的较高功率。
IEEE802.3at(PoE+)主要供电参数: 直流电压在50~57V之间,典型值为50V。典型工作电流为10~600mA,典型的输出功率:30W。受电设备PD支持Class4的分级。
IEEE802.3bt(PoE++): 802.3bt规范引入了四种新的高功率PD分级(Class),从而使单特征类别的总数达到9个。Class5~8对于PoE标准而言是新的,并转化为40.0W至71W的PD功率水平。
分级
PD可用功率
分级
PD可用功率
0
13W
5
40W
1
3.84W
6
51W
2
6.49W
7
62W
3
13W
8
71W
4
25.5W
802.3bt可向后兼容802.3at和802.3af。一个较低功率802.3at或802.3af的PD可连接至一个较高功率802.3bt的PSE,不会出现任何问题。而当一个较高功率802.3bt的PD连接至一个较低功率802.3at或802.3af的PSE,PD只需能够工作在各自的较低功率状态即可,这被称为“降级”。
各类网线支持的PoE协议: PoE
PoE+
PoE++
CAT 5E
√
√
CAT 6
√
√
CAT 6A UTP
√
√
CAT 6A FTP
√
√
CAT 7 S/FTP
二叉树小练习 1.根据二叉树创建字符串 需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。空节点则用一对空括号 “()” 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。
题目链接
class Solution { public: string tree2str(TreeNode* root){ string str; _tree2str(root,str); return str; } void _tree2str(TreeNode* root,string& str) { if(root==nullptr) { return; } str += to_string(root->val); //左不为空 或者 左为空右不为空 if(root->left || root->right) { str += "("; _tree2str(root->left,str); str += ")"; } //右不为空 if(root->right) { str += "("; _tree2str(root->right,str); str += ")"; } return; } }; 2.二叉树的层序遍历 层序遍历Ⅰ 逐层地,从左到右访问所有节点
层序遍历Ⅱ 按从叶子节点所在层到根节点所在的层,逐层从左向右遍历
层序遍历Ⅱ就是在层序遍历Ⅰ的基础上进行一个逆序,所以就只写一个层序遍历Ⅱ
class Solution { public: vector<vector<int>> levelOrderBottom(TreeNode* root) { queue<TreeNode*> q; vector<vector<int>> res; if(root==NULL){ return res; } q.
单例模式案例 模式定义于动机模式结构的角色单例角色类(Singleton) 单例模式分类(饿、懒)实现多例模式的案例案例背景代码实现文件结构或类图1. 饿汉式单例类2. 懒汉式单例类3. 客户类输出结果 模式适用环境 模式定义于动机 单例模式是一种对象创建型模式,它确保某一个类中只有一个实例,而且自行实例化并向系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
三个要点:
某个类只能有一个实例它必须自行创建这个实例它必须自行向整个系统提供这个实例 模式结构的角色 单例角色类(Singleton) 内容
提供一个自身的静态私有成员变量(单例类对象)提供一个公有静态方法getInstance(),使用户可以获取该实例构造函数私有化,防止在外部对该类实例化 单例模式分类(饿、懒) 饿汉式和懒汉式代码中的区别是:初始化单例对象的位置不同
饿汉式:在声明的时候 就初始化
(不管用不用这个单例对象,这个单例对象都初始化好了,所以显得着急,称为“饿”) public class PrintSpoolerSingleTon2 { private static PrintSpoolerSingleTon2 instance = new PrintSpoolerSingleTon2(); private PrintSpoolerSingleTon2(){} public static PrintSpoolerSingleTon2 getInstance(){ return instance; } } 懒汉式:在获取单例对象时进行判断,若没有该对象为null,则初始化,若该对象存在,则直接返回
(用的时候才初始化) public class PrintSpoolerSingleton { private static PrintSpoolerSingleton instance = null; private PrintSpoolerSingleton() { } public static PrintSpoolerSingleton getInstance() { if (instance == null) { System.out.println("创建打印池"); instance = new PrintSpoolerSingleton(); } else { throw new PrintSpoolerException("