Mysql复制表名自动转换大小写问题
这个问题是出现在windows平台。linux就没有出现过
解决方式
找到mysql的配置文件my.ini
添加如下的kv
1 | lower_case_table=2 |
进入任务管理器,找到服务,重启mysql服务。
如果已经是迁移完成的,可以在配置文件中找到data的路径。进入对应的路径.将小写的.fmt文件名更改成大小写就可以了。
需要在bat前面加上以下代码
1 | @echo off |
下面是启动aria2c的脚本代码
1 | @echo off |
发现以管理员运行bat文件时会发现路径错误。因为命令行运行的路径和当前运行的路径不一致。
重新将cmd定位回当前文件夹便可。需要在bat文件中添加如下命令
1 | set curdir=%~dp0 |
使用nslookup可以查询对应的域名
1 | nslookup 14.215.177.38 |
返回的值
1 | 服务器: TianYi.Home |
1 | nslookup www.baidu.com |
1 | 服务器: TianYi.Home |
ipconfig /all
可以查看各个网络的dns配置。
1 | 以太网适配器 以太网 2: |
windows更改dns步骤
windows在文件夹C:\Windows\System32\drivers\etc
中更改hosts文件,将地址放入。151.101.76.133 raw.githubusercontent.com
使用命令行ipconfig /flushdns
刷新dns.
1 | MKLINK [[/D] | [/H] | [/J]] Link Target |
为文件创建符号链接:
假设有一个文件名为aa.txt,想要为它创建一个符号链接名为bb.txt,通过bb.txt可以访问到aa.txt。
1 | >mklink bb.txt aa.txt |
通过上述命令就为aa.txt创建了软链接。同理,有一个文件夹名为aa,想要为这个文件夹创建个符号链接bb文件夹。使用下面的命令。
1 | >mklink /D bb aa |
如果link已经存在就不会创建成功。软连接的特性,删除链接的目标软连接失效。上述操作之后删除aa.txt、aa文件夹。无法通过bb.txt和bb去访问目标了。因为目标不见了。
graph LR aa.txt文件描述 --> 存储区域 bb.txt软链接-->aa.txt文件描述 cc.txt软链接-->aa.txt文件描述
删除了aa.txt之后,软链接无法再访问到存储区域。
硬连接是相对软连接的。
graph LR aa.txt文件-->存储区域 bb.txt硬链接-->存储区域 cc.txt硬连接-->存储区域
无论通过那种方式更改文件内容,都会同时生效。
使用下面的命令为target目录创建了一个联结
1 | >mklink /J aa target |
和使用mklink /D aa target
有何不同之处,使用/D
产生的符号链接移动到其他地方并不会影响target文件内的数据。
但是使用目录联结的话,移动aa到另外一个地方,aa里面的内容也会移动过去。然后target里面的内容就被aa给挪到另一个地方了。目录链接移动的话也会影响target,符号链接的目录移动不会影响target。
以下是这三个键盘的相应键码:
VK_VOLUME_MUTE (0xAD)
Windows 2000/XP: Volume Mute key 音量静音切换键
VK_VOLUME_DOWN (0xAE)
Windows 2000/XP: Volume Down key 音量递减键
VK_VOLUME_UP (0xAF)
Windows 2000/XP: Volume Up key 音量递增键
通过WIndows API的键盘发送函数,我们可以简单而快速的实现音量控制,以下是代码:
/音量加/
keybd_event (0xAF, 0, 0, 0);
keybd_event (0xAF, 0, KEYEVENTF_KEYUP, 0)
/音量减/
keybd_event (0xAE, 0, 0, 0);
keybd_event (0xAE, 0, KEYEVENTF_KEYUP, 0)
/静音切换/
keybd_event (0xAD, 0, 0, 0);
keybd_event (0xAD, 0, KEYEVENTF_KEYUP, 0)
查询一个文件夹中的文件数据,使用File类的list()
函数获得该目录下的文件数据,返回String数组。包括普通的文件名称和文件夹。list()
接收一个FilenameFilter
的实现类实例来过滤获得相应的文件。
1
2
3public interface FilenameFilter{
boolean accept(File dir, String name);
}
如何使用该过滤器?当调用list函数的时候会调用该接口的accept()函数来判断是否保留该文件数据返回。每个文件都会调用该函数一次,自己在accept()函数里面设置规则,就可以获得相应的文件数据。
File代表的是一个文件或目录,文件的相关信息都可以使用File中的函数来获得。下面是常用的函数。
函数名 | 作用 |
---|---|
getAbsolutePath() | 获得绝对路径,不会处理.和.. |
getCanonicalPath() | 获得标准的绝对路径。将.和..解析之后返回路径 |
canRead() | |
canWrite() | |
getName() | |
getParent() | 解析File文件中路径的父路径。只是对构造文件对象时输入的path字符串 |
getPath() | 获得文件路径,构造时传进来的文件路径 |
length() | 返回文件的字节大小,long类型 |
lastModified() | 上一次修改时间戳,long类型 |
isFile() | |
isDirectory() | |
exists() | |
createNewFile | |
renameTo(File f) | 重命名 |
delete() | |
mkdirs() | 创建文件/目录(可以多级创建) |
mkdir() | 仅一级创建。路径的上一个文件夹必须存在才能创建。 |
getParent()
、getName()
、getPath()
、getAbsolutePath()
、getCanonicalPath()
的区别
1 | File f = new File(".\\pom.xml"); |
ouput:
1 | . |
getParent()
获得的只是路径中的上一层,构造对象f时传进去的是.\\pom.xml
。是对该字符串解析。如果直接使用pom.xml
构造f对象,该函数返回的是空值。
mkdirs()
和mkdir()
创建”E:\test\test1\test2\test3”嵌套目录,使用mkdirs()可以顺利创建。但是使用mkdir()如果文件夹组”E:\test\test1\test2”存在,成功创建。否则创建失败。
Reader
和Writer
RandomAccessFile
1 | public static String |
1 | StringReader in = new StringReader( |
1 | DataInputSteam in = new DataInputStream( |
1 | PrintWriter out = new PrintWriter( |
1 | String filename = "Hello.java"; |
写 | 读 |
---|---|
writeUTF() | readUTF() |
writeDouble() | readDouble() |
更多的类型数据读写可以参考JDK.
标准的I/O中含有标准输入、标准输出、标准异常。在java中对应System.in
、System.out
、System.err
。out和err已经被包装成PrintStream对象。
1 | BufferedReader stdin = new BufferedRead( |
可以使用Scanner来读出特定的类型。
1 | // true 自动清空 |
标准IO一般默认是从控制台输入和输出的,但是可以通过重定向来改变标准IO的方向。
1
2
3System.setIn(InputStream)
System.setOut(PrintStream)
System.setErr(PrintStream)
经过重定向之后就可以使用System.out、System.in、System.err。
在java中运行其它的程序。使用Process类来运行程序。
1
2
3
4
5
6// comnands 是运行命令的String[]
Process process = new ProcessBuilder(commands).start();
// 获得运行的输出结果
BufferedRead result = new BufferedReader(new InputStreamReader(process.getInputStream()));
// 获得程序运行的错误
BufferedReader errors = new BufferedReader(new InputStreamReader(process.getErrorStream()))
nio不用太过在意,旧的IO已经用nio来实现过了。
唯一和通道交互得缓冲器为ByteBuffer。原始得字节形式输出和读取,没有办法输出和读取对象。也就是存进去得是什么,拿出来得也是什么。不会包装成String或者其它得对象。
1 | // 使用文件通道写入数据 |
1 | // 常量缓冲区的大小 |
flip()表示ByteBuffer已经写完数据,你从ByteBuffer可以读出来了。
clear()表示ByteBuffer已经清空完数据了,你现在已经可以往ByteBuffer写数据了。
rewind() 返回到数据开始部分。
两个通道相连除了通过上述中间变量之外,使用transferTo()和transFrom()可以将两个通道连起来。这两个不常用,知道就好。
1 | // in => out |
要想ByteBuffer存储有意义的数据,比如说字符串数据。需要写入字节之前对字符串进行编码,或者在读出的时候进行解码。
1 | // 获得字节数据的时候编码 |
使用java.nio.charset.Charset来实现编码和解码。
由于通道存储的只是字节数据。不方便进行读取和管理,这时候需要一个视图缓冲器来作为中间人让使用者直接读写为整型、字符、长整型、浮点、双精度浮点型。
注意: 由于通道存储的是字节数据,转换成相应的数据类型会占用不同字节大小。
类型 | 字节大小 |
---|---|
shorts | 2 |
chars | 2 |
ints | 4 |
floats | 4 |
longs | 8 |
double | 8 |
转换成Chars类型。
1 | CharBuffer cb = ((ByteBuffer)bb.rewind()).asCharBuffer(); |
其中bb是一个ByteBuffer的对象。
同理转换成其它的类型的视图
1 | FloatBuffer fb = ((ByteBuffer)bb.rewind()).asFloatBuffer(); |
有些基本的数据类型需要占用两个及两个以上的字节。计算机的基本存储单位是字节,对于像字符这种占用2个字节,存放有高位优先和低位优先两种方式。java默认的是高位优先。也就是说字符‘a’在内存中存放次序是[0,97]。如果是低位优先则是[97,0]。优先次序使用order来设置。
1
2
3
4// 高位优先
bb.order(ByteOrder.BIG_ENDIAN);
// 低位优先
bb.order(ByteOrder.LITTLE_ENDIAN);
字节存放次序并无优劣之分。重要的数据的一致性,存进去的和读出来的一致便可。
1 | public class UsingBuffers { |
输出结果:
1 | UsingBuffers |
使用“映射文件访问”更好,更高效。下面是使用传统的io流和通道map的读写对比差距。使用映射速度更加显著。
1 | Stream Write:73.48 |
使用mapped写数据
1 | FileChannel fc = new RandomAccessFile("temp.tmp","rw").getChannel(); |
使用mapped读数据
1 | FileChannel fc = new FileInputStream(new File("temp.tmp")).getChannel(); |
Preferences
Api每一个String对象都是不可变的,他们在创建的时候已经在内存中固定了。String对象的改变本质是拷贝一个当前的String的值然后完成修改后,生成新的String对象。这个新的对象和原来对象在内存中没有一丁点关系。是两个独立的对象
Java 不允许程序员重载任何操作符。"Hello" + "World"
本质是在编译器编译之后,生成一个StringBuilder
调用两次append()
将Hello
和World
添加。最后使用toString()
返回整合之后的字符串。如果使用+
太多的话就会产生很多的String中间量。上述的Hello和World产生两个String的中间量。
使用“+”编译器会自动将代码转换成StringBuilder对象。自动转换在循环内是会出现问题的,例如
1
2
3
4
5
6String[] strs = {"Hello","World","Java","Good"};
String result = "";
for(int i=0;i<strs.length;i++){
result += strs[i];
}
return result;
上述的代码会对循环内的每一个+=
操作创建新的StringBuilder对象完成字符串的拼接。使用如下的代码会更加高效
1
2
3
4
5
6String[] strs = {"Hello","World","Java","Good"};
StringBuilder result = new StringBuilder();
for(int i=0;i<strs.length;i++){
result.append(strs[i]);
}
return result.toString();
编译器自动编译有时候可能会愚蠢的优化代码。需要自己知道如何编写更加高效的代码。避开编译器的优化陷阱。
StringBuilder为什么效率更高?
StringBuilder 会在内存中申请一个空间。这个空间可以自己指定也可以使用默认的。使用append()操作的时候就是在自己的空间内完成操作,一次申请,随意改变。String 对象是只读的。内存的申请和释放都是有代价的!!
愚蠢的便捷
自己创建了一个StringBuilder然后在使用如下形式的函数
append(a + ":"+ b)
;
这个有什么问题。编译器会帮你将a+ ":" + b
部分新建一个StringBuilder对象来处理。这样就会得到两个字符串了。
小结
StringBuilder常用的操作有append()
和toString()
.其它的还有insert()、replace()、substring()、reverse()、delete()
StringBuilder和StringBuffer。前者线程不安全、后者线程安全。
一个类A中的toString()
的方法如下。为了输出该类当前实例对象的地址。
1 | public String toString(){ |
会产生异常,自动转换类型。将A类转换成String类。+ this
会将this转换成String类。this指向A类,然后A又调用toString()方法来转换成String.递归的无出口。this -> this.toString() -> this -> ….
想要打印当前对象的地址使用Object.toString()
.应该使用父类的toString() super.toString()
。这样就不会出现死递归。
String常用的操作在自己的编程至今。最多的就是字符串的更改和比较。更改使用StringBuilder更加好。String比较最多的便是相等比较。
equals(),equalsIgnoreCase()
相等比较。
使用"String".equals(a)
替换a.equals("String")
。如果a
是个null。调用equals()
方法会出现问题。
length()
字符串的长度
trim()
去掉自字符串两端的空白字符
其它的操作有
1 | charAt() |
用的时候再查帮助手册
使用System.out.printf()
可以输出和C语言中的占位符。格式化输出.使用System.out.format()来替代。
Sytem.out.format()
可以使用%d,%s 等占位符
在Java中,Formatter类是一个翻译器。翻译格式化字符和数据,构造Formatter类时需要传递一个输出流,说明要向什么地方输出。
向控制台输出
1
2Formatter f = new Formatter(System.out);
f.format("")
还可以使用OutputStream
和File
输出
格式化的语法
%[argument_index$][flag][width][.precision]conversion
字符 | 说明 |
---|---|
d | 整数型(十进制) |
c | Unicode字符 |
b | Boolean值 |
s | String |
f | 浮点数(十进制) |
e | 浮点数(科学计数法) |
x | 整数(十进制) |
h | 散列码(16进制) |
% | 字符‘%’ |
各种类型的适用字符
类型 | 可用转换字符 |
---|---|
字符 | c、b、h |
整数 | d、c、b、s、x、h |
浮点数 | b、s、f、e、h |
对象 | b、s、h |
布尔类型 | b、s、h |
b转换对于Boolean和boolean会对应true和false,但是对于其他的数据类型。只要不是null。对应转换的都是true,只要是null输出的是false
想要获得一个格式化的字符串,可以使用”+”和StringBuilder中的append()来构建。但是还有一个更加方便的方法。使用String.format()方法获得一个格式化的字符串。
字符表
字符 | 意义 |
---|---|
B | 指定字符B,可以是其他指定字符 |
\xhh | 十六进制为oxhh的字符串 |
\uhhh | 十六进制表示为oxhhhh的Unicode编码 |
\t | 标识符Tab |
\n | 换行符 |
\r | 回车 |
\f | 换页 |
\e | 转义 |
字符类,字符类是最需要掌握的。掌握字符类之后便可以显示正则表达式的威力
字符类 | 意义 |
---|---|
. | 任意字符 |
[abc] | 包含a、b和c的任何字符。等价于a|b|c |
[^abc] | 除了a、b和c之外的任何字符 |
[a-zA-Z] | 从a到z或A到Z的任何字符(范围) |
[abc[hij]] | 任意a、b、c、h、i和j的字符。等价于a|b|c|h|i|j展开合并 |
[a-z&&[hij]] | 任意h,i或j(交) |
\s | 空白符(空格、tab、换行、换页和回车) |
\S | 非空白字符,等价于[^\s] |
\d | 数字[0-9] |
\D | 非数字[^0-9] |
\w | 词字符[a-zA-Z0-9] |
\W | 非词字符[^\w] |
逻辑操作表
字符 | 意义 |
---|---|
XY | Y跟在X后面 |
X|Y | X或Y |
(X) | 捕获组 (capturing group).可以在表达式中用\i引用第i个捕获组 |
边界匹配表
字符 | 意义 |
---|---|
^ | 一行的起始 |
$ | 一行的结束 |
\b | 词的边界 |
\B | 非词的边界 |
\G | 前一个匹配的结束 |
量词的主要作用的确定要怎么匹配,有贪婪型、勉强型、占有型。
贪婪型|勉强型|占有型|如何匹配
:-:|:-:|:-:|:-:|:-:
X?|X??|X?+|一个或零个X
X*|X*?|X?+|零个或多个X
X+|X+?|X++| 一个或多个X
X{n}|X{n}?|X{n}+| 恰好n次X
X{n,}|X{n,}?|X{n,}+| 至少n次X
X{n,m}|X{n,m}?|X{n,m}| X至少n次,且不超过m次
字符串匹配正则表达式,可以使用String.matches(pattern)
.例如"Rudolph".matches(pattern)
其中pattern为String pattern = "[rR]udolph"
使用正则表达式的对象处理
1 | // 原始字符 |
matcher常用方法
方法名 | 解释 |
---|---|
boolean matches() | 整个输入字符串是否匹配正则表达式模式 |
boolean lookAt() | 判断该字符串的始部分是否能够匹配模式 |
boolean find() | 查找多个匹配,每调用一次就会自动向前迭代。 |
boolean find(i) | 查找特定索引的匹配,指定开始搜索的位置 |
int groupCount() | 该匹配器中的分组数目 |
String group(int i) | 返回前一次匹配的指定的组号,没有返回null。没有group(0)等价于group() |
int start(int group) | 返回在前一次匹配操作中寻找到的组的起始索引 |
int end(int group) | 返回在前一次匹配操作中寻找到的组的最后一个字符串索引加一的值。注意是加一!! |
pattern标记
Pattern Pattern.compile(String regex, int flag);
标记的作用的是设定特定模式的匹配规则,.是否匹配行终结符,是否考虑字符串的大小写等。
和String.split()分隔字符串有相同的作用
1
2
3String input = "This is unusual use!!of exclamtion!!points":
Pattern.compile("!!").split(input);
Pattern.complie("!!").split(input,3);
String[] split(CharSequence input);
// limit 分成几个部分
String[] split(CharSequence input,int limit);
scanner.useDelimiter("\\s*,\\s*");
scanner.match()
获得匹配的数据。1 | scanner.next(pattern); |
Qss 和CSS 几乎是相同的。都是由选择器(Selector)+声明(Declaration)。使用使用”属性:值”对设置。使用分号分隔数据(“;”),例如.设置背景颜色和字体颜色
1 | QPushButton{ |
调用组件(QWidget)中的setStyleSheet()
来设置样式。样式的具有继承,如果对最上层的(QWidget)设置,该QWidget中有相应的组件被选择便会被设置。
匹配所有控件
使用QPushButton
,QLineEdit
。这种特定的控件类型。
QPushButton 会匹配到QPushButton类和子类的实例。
如果想要几种类型的控件设置相同的样式。可以使用”,”来控制。例如:
1 | QPushButton,QLineEdit,QCombox {color:blue} |
等价于:
1 | QPushButton {color:blue} |
属性选择器是最灵活的,选择颗粒的到某一个单一控件的。例如:
1 | btn = QPushButton(self) |
选中该按钮
1 | # 页面主类 |
设置win中的属性name值为”myBtn”的按钮控件设置背景颜色为红色。
.QPushButton
匹配所有的QPushButton的实列。但是并不会匹配到子类。这要和第二种的类型选择的做区别。这个和CSS选择器不一样
#myButton
匹配ID为myButton的控件,控件使用setObjectName("myButton")
设置ID值。这个选择器也是最常使用的。
QDialog QPushButton{}
匹配QDialog
容器中的QPushButton
的样式。不管是直间还是间接的。
QDialog > QPushButton{}
匹配Dialog
中包含的QPushButton
。其中必须要求QPushButton的直接父容器是QDialog。
(1) 一次设置多种选择器类型,使用”,”。#frameCut,#frameInterrupt,#frameJoin{}
(2) #mytable QPushButton
复合控件的样式,例如下拉框的箭头,点击之后下拉列表。例如
1
QComboBox::drop-down { image: url(dropdown.png)}
下拉的图片为:dropdown.png
伪装态选择器,冒号开头的一个选择表达式。例如:QComboBox:hover{}
鼠标经过的样式。
QComboBox::drop-down:hover{background-color:red;}
复合控件下拉鼠标覆盖样式。:!hover
没有覆盖。
(1) 设置背景图片
1 | win = QWidget() |
(2) 设置背景颜色win.setStyleSheet("#MainWindow{background-color: yellow}")
(1) 设置背景图片
1
2
3palette = QPalette()
palette.setBrush(QPalette.Background,QBrush(QPixmap("./images/python.jpg")))
win.setPalette(palette)
注意:
当 窗口宽高 < 图片宽高 部分显示图片内容。
当 窗口宽高 > 图片宽高 图片重复填充。
(2) 设置背景颜色
1
2
3palette = QPalette()
palette.setColor(QPalette.Background, Qt.red )
win.setPalette(palette)
通过重写painEvent方法来设置窗口的背景或者图片
(1) 设置背景图片
1 | def paintEvent(self,event): |
(2) 设置背景色
1 | def paintEvent(self,event): |
不规则窗口才是美化应用界面,更加随心所欲的设置窗口的关键
可以使用setMask(self,QBitmap)
和setMask(self,QRegion)
。通过重写painEvent()
函数来设置蒙版。Qbitmap获得的是一个二值化后的图像。其中为1白色会不显示,黑色0显示。设置完蒙版的图片之后,再添加背景图片可以完成相应不规则窗体。
蒙版如下:
白色的部分会被镂空(透明)。黑色的部分会正常显示。
设置蒙版
1 | self.pix = QBitmap( "./images/mask2.png" ) |
运行之后的结果:
白色部分会显示桌面的图片
想要什么样的不规则的窗口,只需要设置相应的不规则蒙版才行。
通用的重写
1 | #重定义鼠标按下响应函数mousePressEvent(QMouseEvent)和鼠标移动响应函数mouseMoveEvent(QMouseEvent), |
设置窗口半透明可以使用setWindowOpacity()
来设置。如果想要组件有相应的颜色并且半透明,可以使用样式来设置。例子的总体效果如下
使用setMask来设置椭圆的样式。蒙版样式如下:
通过使用rgb的透明分量来设置按钮的样式的半透明和颜色background-color: rgb(255, 255, 255,0.5);
。椭圆使用border-radius:5px;
鼠标覆盖按钮和按下按钮时的透明度改变。样式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17style = """
QPushButton{
border-radius:5px;
background-color: rgb(255, 255, 255,0.5);
color:black;
}
QPushButton:hover{
border-radius:5px;
background-color: rgb(255, 255, 255,0.7);
color:black;
}
QPushButton:Pressed{
border-radius:5px;
background-color: rgb(255, 255, 255,0.9);
color:black;
}
"""
核心,鼠标覆盖按钮的时候,改变按钮的背景图片。
1
2
3
4
5
6
7
8exit_btn_style ="""
QPushButton{
border-image: url(./image/close.png);
}
QPushButton:hover{
border-image: url(./image/close-hover.png);
}
"""
个人资源管理平台
需要一个软件平台来管理自己日益复杂和丰富的资源。包括但不限于个人文档、积累的电子书、下载的音乐、下载的视频教程,一些常用的功能。日记、笔记等。一些相关的人工智能的资源整合。如车标识别、orc等常用的接口。未来可能要接入物联网的相关设备、由于腾讯云的服务器的存储资源有限,未来需要将自己本地的文件外挂到该平台,即可以减小服务器的开销,还可以保护文档的私密性。服务器只做数据中转,而不是数据存储。服务器算力也有限,需要将算力分到本地外挂的设备。
宅男喜欢二次元、现在积累了几个G的图片文件。但是很杂,该平台提供相册、分类的功能
音乐很多,想要有自己的音乐播放器,类似于网易云音乐那种。
视频很多、非常多。需要有效的管理
1、能够看视频(宽带问题,无法流畅的看视频)
2、用户能够根据名字搜索视频
3、用户能够创建自己的栏目,并且往里面添加视频(类似于blibli的收藏夹功能)
4、用户能够删除视频
笔记有很多成熟的产品,但是数据不可控。自己不想把数据放在他们的服务器上。所以需要一个支持多端编写的文档的功能。数据放在自己的数据库中。支持富文本和markdown格式的语法。
学习工作中有很多工具的需求,图片转文字、开发中json格式化、还有很多的开发手册。这些都是用得到的,并且自己已经实现了车标的识别并且建立了模型。可以将该功能整合
到平台中
1、二维码工具。能够根据字符串生成二维码,也能识别二维码为字符串。
2、车标识别工具。能够根据上传的图片识别相应的车标。
3、
未来自己会将家里的物联网的设备挂在该平台中,并且能够在该平台进行管理。空调、冰箱、台灯、电视机。自己梦想中的家。需要一个同一的管理平台,而不是各自为政。
添加设备,每个设备都有自己的id码,并且有相应的命令。
用来记录自己的计划和执行情况,主要借鉴TODO List的功能
添加计划,一个计划会有开始时间、截止时间、完成时间(用户完成),具体内容,轻重缓急。
编辑、删除计划,只有未开始的计划才能编辑和删除
生成报表,可以按周、按月生成报表。记录计划的预计完成时间和实际完成时间,计算完成工作计划的轻重缓急的比例。
笔记本:t_notebook
字段 | 属性 | 说明 |
---|---|---|
id | bigint | 主键 |
notebook_name | varchar | 笔记本名 |
notebook_description | varchar | 笔记本描述 |
create_id | bigint | 创建者id |
created_time | timestamp | 创建时间戳 |
modify_time | timestamp | 修改时间戳 |
del | tinyint | 删除标记 |
笔记条目:t_notebook_item
字段 | 属性 | 说明 |
---|---|---|
id | bigint | 主键 |
notebook_id | bigint | 主键 |
notebook_item_title | varchar | 笔记条目标题 |
notebook_item_content | text | 笔记条目内容 |
create_time | timestamp | 创建时间 |
modify_time | timestamp | 修改时间 |
del | tinyint | 删除标记 |
Request URL: 127.0.0.1:8080/Api/User/Login
Request Method:post
Request Body:
1 | { |
Response Body:
1 | { |
Request URL: 127.0.0.1:8080/Api/User/Logout
Request Method: post
Request Body: null
Response Body:
1 | { |
Request URL: 127.0.0.1:8080/Api/User/UserInfo?token=usertoken-token
Request Method: get
Response Body:
1 | { |
sequenceDiagram participant user as 用户 participant front as 前端 participant backend as 后端 user->>front: 填写账号和密码 front->>front: 校验账号密码 front->>backend: 登录请求 backend->>backend: 处理登录请求 backend-->>front: 返回token front->>front: 保存token front->>front: 进入首页 front->>backend: 根据token获得用户数据 backend-->>front: 返回用户数据,包括用户名,头像,路由等 front->>front: 保存用户数据,处理路由数据动态渲染。 front->>front: 进入系统 front-->>user: 完成登录
大数据量数据传输TCP的有序也不能自己分割数据组
数据分割协议:
1 | 数据总长度(4bit) + 数据流 |
使用一个缓冲区先存数据,看是否已经可以拿回数据了。
1 | // 重新构建和显示软件列表 |
使用链表将每个软件和节点对应起来,拥有前后指针,方便增删改查
1 | root <--> classNode <--> class2 <----> class3 |
关于样式的设置,有可选项,可以使用极简,也可以使用自定义的配置
自定义更换背景图片,获取文件,读取文件,更换渲染.
软件布局的计算,自己计算还是使用官方的布局器,可以自己确定整个应用的宽高,然后一行最多能够放下多少个组件,然后将剩下的空间计算间距。
使用自定义的组件,有图标,下面有软件名称。
多设备组装成物联网,每个设备均有不同的属性功能,如何在抽象层统一管理设备?
如果将设备看作是由多个服务组合而成的结构体,服务之间的调用作为设备间的交互。
APP,PC,PI,CAMERA。设备之间的差异是什么?
服务的差异?一个APP和PC中运行的软件是否可以一致?一个Camera视乎只能提供音视频的服务。
文件相互传输可能就是APP和PC之间的服务调用。
难点:
设备的基础能力定义是什么?每个设备都必须存在的基础服务是什么?注册登录心跳
设备之间如何相互发现?设备与设备之间如何联动?
多设备协同,算力如何分配?能否将流式定义计算任务?将计算任务分配在不同的设备上??
安全性:证书说大不大,说小不小,但是对于只有几百k的内存和存储空间有时候不能不牺牲繁杂的安全校验,这也许就是物联网设备安全问题频出的原因吧。
解决问题的步骤:定位问题,解决方案。目标是解决问题。
对于单核多线程的物联网设备来说,数据的收发及时性是非常有必要的。但是,为了最求低延迟不能使用死的循环。
收发线程适当的休眠更有利于整个系统的执行速度。如果收发线程都使用循环,并且没有休眠。这时候会出现一种现象,
普通赋值语句,strcpy,memset等语句耗时不定。为了最求极致的及时性,反而会使整个系统的执行效率降低。
一个设备的算力是固定的,不管多少线程,能够享受的算力是固定了。有时候,多线程不一定比单线程跑得快。系统调度也会占用算力。
怎么组网,怎么相互发现??
这几年零零碎碎的学了很多东西,但是都没有完整的串联起来。对于物联网慢慢的了解了,就想要自己建立一个平台。控制属于自己的物联网设备,虽然很多的厂家已经有成熟的产品,但是,国内的企业尿性。到时候不看个广告都开不灯不是不可能。有些东西得掌握在自己得手里。
建立一个可用得平台其实说难不难,说简单不简单。边端云每一侧都有很多的东西需要处理,但是这些处理大部分是为了满足用户的特殊需求。自己一个小小的系统
需要满足自己的需求就可以了,就远程开个灯而已。把数据安全搞好,剩下的慢慢来。
一个SDK都有哪些功能?
基础的模块:每个设备都会有的模块
设备服务模块: 不同的设备均由不同的服务组合而成。可选项。
设备属性值:对于一些设备,没有对外提供服务的能力,只有自身的设备属性。比如开关控制器。除了基础的模块,不提供任何服务。
最简单的设备用户管理,协助设备间服务调用和组网,处理操作人机交互数据。
1 | /** |
运行的结果:
右键复制的得到的字符串,后面要用
由于跨域问题,下载图片需要在图片所在的域名下下载。。。
1 | /** |
请求结果:
需要开启chorme的连续下载
下载结果
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true