需安装pywin32 pip install pywin32
直接上源码。简单几行就搞定 很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:101677771
import os, sys import win32com.client import time import hashlib def pwd_xlsx(old_filename,new_filename,pwd_str,pw_str=''): xcl = win32com.client.Dispatch("Excel.Application") # pw_str为打开密码, 若无 访问密码, 则设为 '' wb = xcl.Workbooks.Open(old_filename, False, False, None, pw_str) xcl.DisplayAlerts = False # 保存时可设置访问密码. wb.SaveAs(new_filename, None, pwd_str, '') xcl.Quit() if __name__ == '__main__': old_filename = 'C:\\Users\\admin\Desktop\\20200805.xlsx' new_filename = 'C:\\Users\\admin\Desktop\\test122222.xlsx' pwd_str = '654321'#新密码自定义 pwd_xlsx(old_filename,new_filename,pwd_str)
1、读取sql文件创建数据表 有一个形如下图的sql文件,使用python读取文件并在数据库中创建所有的表。
很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:101677771
代码是很久以前搬的,忘了出处了> <,输入sql文件名称和数据库名称即可创建,执行成功或失败时都会有打印哪条sql语句执行成功或失败
import pymysql def CreateTables(document,database): try: db = pymysql.connect(host='localhost', user='root', password='123', database=database, charset='utf8') cursor = db.cursor() with open(document,encoding='utf-8',mode = 'r') as f: sql_list = f.read().split(';')[:-1] for x in sql_list: if '\n' in x: x= x.replace('\n',' ') if ' ' in x: x= x.replace(' ',' ') sql_item = x+';' cursor.execute(sql_item) print("执行成功sql:%s"%sql_item) except Exception as e: print(e) print('执行失败sql:%s'%sql_item) finally: cursor.close() db.commit() db.close() 2、增删改查 假设如上面sql文件里的table_1,想在数据库中创建一个这样的表
在Servlet程序中使用@WebServlet()注解访问页面地址出现404
1、检查@WebServlet()中的跳转地址是否出错 跳转地址输入错误是常有的事,所以首先检查页面的跳转地址是否错误。若错误了修改未正确的地址
2、web.xml版本问题 检查这两个标签
version的值必须是3.0以上才行,这是在servlet中使用注解的必要条件metadata-complete的值是否为true,因为当这个标签的值为true时,servlet中就只能使用web.xml进行配置;若为false,就可以使用注解的方式对servlet进行配置。
抽象基类中建立指针数组的注意点: 这个可以归结到指针的知识点,即区分清楚用指针创建一维和二维数组时到底代表了什么。在类这个范围的限制下,又有其独特的含义。 1.一维数组建立时,数组每个元素都代表了一个数组类型的数据。 int *p = new int[2]; 在这里p[0],p[1]都是一个int型的数据。
放到类中来讲,建立一个类的一维数组实际上就是建立了多个类对象。 class Circle{ double radius; public: Circle(double r = 0) : radius(r){} double Area(){ return 3.1415 * radius * radius;} } int main(){ Circle *p = new Circle[2]; } 这里在new指针数组时,就相当于创建了2个Circle类的对象,即p[0]、p[1]。
2.二维指针数组建立时,每个元素本质上还是指针,只不过是不同数据类型的指针而已。这就相当于建立了一个该数据类型的指针数组。 int **p = new int* [2]; 这里p[0]、p[1]都是一个int *p
对类来说,建立类的二维指针数组并没有生成类对象(没有动用构造函数),只仅仅创建了多个类的指针而已。 class Circle{ double radius; public: Circle(double r = 0) : radius(r){} double Area(){ return 3.1415 * radius * radius;} } int main(){ Circle **p = new Circle* [2]; } 这里p[0]、p[1]都是Circle类的指针
ceph-deploy new node 问题:
1 2 3 4 5 6 Traceback (most recent call last): File "/usr/bin/ceph-deploy", line 18, in <module> from ceph_deploy.cli import main File "/usr/lib/python2.7/site-packages/ceph_deploy/cli.py", line 1, in <module> import pkg_resources ImportError: No module named pkg_resources 解决办法:
python 版本问题 ,注意检查系统的python版本,此处ceph-deploy实则为通过执行python脚本来实现安装,
更改/usr/bin/ceph-deploy文件中 更改python2.6的部分为2.7(此处应当与系统python版本相同) 更改第一行文件为 #!/usr/bin/python2.7 重新执行ceph-deploy new即可
ceph-deploy disk zap node12:sdb 问题:
1 [ceph_deploy][ERROR ] RuntimeError: zap command needs both HOSTNAME and DISK but got "None node12:sdb" 解决办法:
写在前面:本文是参考知乎任乾大佬的帖子完成,增加了自己的注释以及一些其他功能,如果有理解不到位的地方,请大家指正~
目录 里程计流程front_end_node.cpp的注释可视化debug参考 里程计流程 1、如果当前帧是第一帧,那么将其看做关键帧,进行关键帧更新
2、关键帧更新都做了什么?更新local_map队列,更新local_map,更新ndt的target_cloud。
3、如果不是第一帧,那么将其与local_map进行ndt配准,配准的所需要的guess_pose是根据匀速运动模型进行计算的。
4、配准得到当前帧的pose,利用当前帧和上一阵的pose,结合匀速运动模型得到下一次配准的guess_pose;如果当前帧的pose相对于上一关键帧的pose距离较大,则更新关键帧。
front_end_node.cpp的注释 /* * @Descripttion: 对任乾大佬的tag4.0增加map--->lidar的tf变换,并可视化最原始的变换后的点云 * @vision: * @Author: suyunzzz * @Date: 2020-08-20 23:40:44 * @LastEditors: Please set LastEditors * @LastEditTime: 2020-08-26 23:20:21 */ /* * @Description: * @Author: Ren Qian * @Date: 2020-02-05 02:56:27 */ #include <ros/ros.h> #include <pcl/common/transforms.h> #include "glog/logging.h" #include "lidar_localization/global_defination/global_defination.h" #include "lidar_localization/subscriber/cloud_subscriber.hpp" #include "lidar_localization/subscriber/imu_subscriber.hpp" #include "lidar_localization/subscriber/gnss_subscriber.hpp" #include "lidar_localization/tf_listener/tf_listener.hpp" #include "lidar_localization/publisher/cloud_publisher.hpp" #include "lidar_localization/publisher/odometry_publisher.hpp" #include "lidar_localization/front_end/front_end.hpp" // 前端相关的头文件 #include <tf/transform_broadcaster.
使用注解、切面、反射,对前端传递的参数,做统一的空格(trim)处理 业务场景:由于目前的前后端分离,在某些情况下,前端可能没有对传入后端的字符串做出来,导致传递到后端的数据可能有偏差,两端出现空格的情况。所有我就想,怎么能够统一的对前端的传参做一个处理,让后端不用太关心前端的参数问题。
实现思路:前端的参数一般都放在请求体中,作为后端的一个入参。我们需要做的就是,把前端的参数的空格去除。所以我们需要获取到需要处理的方法的入参。拿到入参后并且要把,它的值给它改变。
实现方法:使用注解对需要处理的方法,加上注解,作为一个标志。然后通过这个标志,我们定义一个切入点。对它进行环绕增强。再利用反射,动态的去设值到原DTO中。
实现步骤:
定义一个标志注解 @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AutoString { } 为方法加上@AutoString 注解 @AutoString @ApiOperation("test01") @PostMapping("/test01") public Object test01(@RequestBody TestDto testDto){ System.out.println(testDto); return testDto; } @AutoString @ApiOperation("test02") @PostMapping("/test02") public Object test02(@RequestBody Test02Dto test02Dto){ System.out.println(test02Dto); return test02Dto; } 定义测试的DTO,包含一些常用的类型 public class Test02Dto { private String name; private Integer size; private Double weight; private Boolean activeFlag; private List<String> ids; @Override public String toString() { return "Test02Dto{" + "name='" + name + '\'' + "
本文转至顶级架构师
我们要了解的是微服务和DDD到底有什么关系呢?
因为在互联网时代,软件所面临的问题域比以往要复杂得多,这种复杂性来源于不断扩展的问题域自身,也来源于创新变化,以及这种规模性增长所带来的挑战。
然而一个人一个团队,他对复杂的事物的认知是有极限的,面对这种复杂问题唯一的方法就是分而治之。分主要考虑的是如何去分;治意味着分出来的每一个部分要能够独立的运行,能够互相的协作,完成整体的目标,能够一来应对外部变化所带来的冲击。
微服务的缺陷 微服务架构在分和治两个方面都给出了很好的理论指导和最佳实践,那微服务是不是解决复杂问题的银弹呢?其实不然,很多团队在应用了微服务架构来构建他们的系统以后,发现并没有完全解决这种复杂性问题,甚至还带来了一些其他的问题。比如:
服务并没有解决复杂系统如何应对需求变化这个问题,甚至还加剧了这个问题。
当一个需求变化了,需要花大量的精力去识别这个变化影响到了哪些微服务,这些服务的多个团队之间,需要通过无休止的扯皮去决定哪个服务多一些,哪些服务少改一些。
然后测试团队还需要做昂贵的这种联调测试
即便如此呢,开发团队依然不放心,还要通过一系列的开关控制,小心翼翼的去做切流,去做灰度发布。
从业务层面来看,微服务架构没有避免这种散弹式的修改。甚至反而加重了他,这是为什么呢?一个重要的原因是微服务架构在分的这个纬度考虑的并不全面。
DDD功用 当我们去做分的这种工作的时候,,需要考虑哪些维度呢?我觉得我们至少要考虑三个维度:
功能纬度
质量纬度,比如性能,可用性
工程纬度
微服务对第2个给出了很好的指导,对第3个也给出了一些建议。但是,对第1个功能纬度只给出来非常有限的指导,就是为什么随着微服务的流行,领域驱动设计(DDD)又被重新重视起来的原因。
DDD弥补了微服务在功能划分方面没有给出很好指导的缺陷。所以他们在面对复杂问题和构建系统时候是一种互补的关系,在系统拆分的时候可以很好的协作。
关注顶级架构师公众号回复“Java”,送你一份Java面试题和答案惊喜礼包。
只是他们看待系统拆分这个角度是不同的。微服务当中的服务所关注的范围正是DDD所推崇的六边形架构中的领域层。
拆分案例 接下来结合DDD和微服务来拆分一个复杂系统。
关于领域 我们称企业的业务范围和在这个范围里进行的活动为领域,和软件系统无关。领域会分成多个子域,比如我们一个电商系统,会有:
商品子域
订单子域
库存子域等等。
在不同的子域里,不同的概念有不同的含义。所以我们在进行领域建模的时候,必须要有一个明确的领域边界,也就是DDD里称做的限界上下文,它是系统内部的一个架构边界,决定了这个系统架构。
划分系统内部架构边界 架构简洁之道这本书里边就说过:『系统架构是由系统的内部架构边界以及边界之间的依赖关系所决定的,与系统中各个组件之间的通信和调用的方式是无关的』。我们常说的微服务的服务调用本身只是一种比函数调用方式成本稍高的,分割应用程序行为的一种形式,系统架构无关。
所以,复杂系统划分的第一重要的是要划分内部的架构边界,即划分清楚这个上下文,以及明确他们之间的关系,这对应于我们之前说的功能的维度。这正是DDD用武之处。其次我们才考虑基于非功能的维度如何划分,这是微服务能够发挥其优势的地方。
举个例子,我们把系统分成ABC三个个上下文,三个上下文的代码可以在一个部署单元里运行,通过进程内调用来完成操作,这就是典型的单体架构;
也可以各自在一个独立的部署单元里运行,通过远程调用来完成操作,这就是现在流行的微服务架构。
边界清晰的好处 我们更多的是两种架构模式的一个混合,比如A和B一起是一个部署单元,C是另外一个独立的部署单元,这种情况往往是因为C非常重要,他并发的访问量非常大,或者它的需求变更比较频繁。将C拆分出来的有以下几个好处:
资源倾斜
使用弹力设计模式:比如重试,熔断,降级
使用特殊技术:比如Go语言
具备独立代码库:有独立团队和运维人员,和A和B的运行期做到隔离不互相影响
这四点正是服务架构所关注的,它是基于非功能纬度的视角来看待拆分这件事情的,他关注的不是系统架构的逻辑边界,更多的关注的是应用程序行为的分隔。
关注公众号‘架构师老毕’送你一份架构资料
那为什么不把A和B都拆成一个独立的部署单元?
这会带来更多的好处,也会带来额外的成本,架构应该是可以演进的,在业务发展的早期,应该关注系统架构的逻辑边界,保持逻辑边界的清晰和关系的正确,随着业务量的增加,逐步在做拆分,这是组合应用DDD和微服务架构带来的最大的好处。
在单体架构中,保持架构逻辑边界不被突破是有一定难度。如果逻辑边界不清晰,在需要服务器拆分的时候,就未必能拆得出来了。另外没有人一下子就可以把逻辑边界定义正确,即使这个上下文定义的不太正确,在DDD聚合根这个概念可以保障我们能够演进出更适合的上下文。
DDD界限上下文内部通过实体和值对象来对领域概念进行建模,一组实体和值子对象归属于一个聚合根。那按DDD要求
聚合根用来保证内部实体规则的正确性和数据的一致性
外部对象只能通过ID来引用聚合根,不能引用聚合根内部的实体
聚合根之间不能共享一个数据库事务,它们之间的数据一致性需要通过最终的一致性来保障
有了聚合根,基于这些约束,未来可以根据需要把聚合根升级为上下文,甚至拆分成微服务都是比较容易的。
今天就给你介绍到这儿,希望对你有所启发。
背景 为了 实现 uboot 中连接上 QEMU-host 的网络。
非常奇怪,本人的 系统中 存在/dev/net/tun驱动,但是 lsmod | grep tun 却没有任何结果,所以实际上,这篇文章本人仅仅停留在理论基础之上。
概念 QEMU中的网络,包含两部分的内容:
客户机使用的虚拟网络设备和上述虚拟设备通信的网络后端,这些后端负责把虚拟设备的数据包发到宿主机的网络中 要创建一个网络后端,可以指定如下选项:
# TYPE为后端类型:user、tap、bridge、socket、vde等 # id为一个标识符,将虚拟网络设备和网络后端关联在一起 # 如果客户机有多个虚拟网络设备,则每一个都需要自己的网络后端 -netdev TYPE,id=NAME,... QEMU 两种上网方式(不同的网络后端):
user mode network :
这种方式实现虚拟机上网很简单,类似vmware里的nat,qemu启动时加入-user-net参数,虚拟机里使用dhcp方式,即可与互联网通信,但是这种方式虚拟机与主机的通信不方便。
tap/tun network :
这种方式要比user mode复杂一些,但是设置好后 虚拟机<-->互联网 虚拟机<-->主机 通信都很容易
这种方式设置上类似vmware的host-only,qemu使用tun/tap设备在主机上增加一块虚拟网络设备(tun0),然后就可以象真实网卡一样配置它。
QEME支持多种网络后端: USER后端 如果没有指定网络选项,QEMU默认会模拟单张Intel e1000 PCI网卡,该网卡基于user后端(SLIRP)连接到宿主机:
# 不指定网络 qemu # 等价配置。自0.12开始废弃的配置方式 -net nic相当于-device DEVNAME;-net TYPE相当于-netdev TYPE qemu -hda disk.img -net nic -net user # 等价配置。-netdev指定网络后端,-device指定虚拟网络设备,后者通过netdev字段引用后端的ID qemu -netdev user,id=network0 -device e1000,netdev=network0 在客户机看来:
GridView控件是一个visualStudio自带的数据控件,它可以非常快速的将数据以表格方式显示在web页面上。下面就是一个利用GridView控件进行数据绑定的小例子,内容如下:
数据来源自一个XML文件,至于如何操作XML文件,这里不作详细描述,具体可以参考 http://www.cnblogs.com/programsky/p/3816073.html
1.XML内容如下:
<?xml version="1.0" encoding="utf-8"?> <gunbook> <gun type="自动步枪" gid="001"> <name>AK-47</name> <from>俄罗斯</from> <clip>30</clip> <accurate>0.2</accurate> <range>300M</range> </gun> <gun type="狙击枪" gid="002"> <name>AWM</name> <from>英国</from> <clip>10</clip> <accurate>1</accurate> <range>1000M</range> </gun> <gun type="冲锋枪" gid="003"> <name>MP5</name> <from>美国</from> <clip>80</clip> <accurate>0.1</accurate> <range>280M</range> </gun> <gun type="霰弹枪" gid="004"> <name>气锤</name> <from>德国</from> <clip>10</clip> <accurate>0.2</accurate> <range>120M</range> </gun> </gunbook> View Code
(这里的数据源还可以从数据库中读取,比如“select uid,uname,usex,uage from users”…这样就可以不用XML了)
2.定义了一个model类便于数据交换:
//定义一个枪的数据模型类
public class GunModel { public GunModel() { } //枪的名称 public string GunName { get; set; } //枪的类型 public string GunType { get; set; } //枪的编号 public string GunID { get; set; } //枪的产地 public string GunFrom { get; set; } //枪的弹夹 public string GunClip { get; set; } //枪的精准度 public string GunAccurate { get; set; } //枪的射程 public string GunRange { get; set; } } View Code
Linux内存管理之kmalloc、malloc、vmalloc的区别 kmalloc和vmalloc分配的是内核空间的内存,malloc分配的是用户空间的内存。kmalloc保证分配的内存在物理上是连续的,内存只有在被DMA(直接存储器访问)访问的时候才需要在物理上连续。vmalloc分配的内存在虚拟地址空间上是连续的。malloc分配的是很多内存片断,不是连续的地址空间。kmalloc分配的内存比较小,malloc和vmalloc分配的内存较大。vmalloc要比kmalloc速度慢。尽管只有被DMA访问的时候才需要kmalloc分配内存,但是很多内核代码用kmalloc来获取内存,主要是出于性能的考虑。vmalloc函数为了使得申请的内存在虚拟地址空间是连续的页,需要专门建立页表项。通过vmalloc获取的页,需要一个一个的进行地址映射,因为在物理地址空间不是连续的,这会导致比直接内存产生内存抖动,降低内核处理速度。
PE Tools:一款功能强大的PE文件编辑工具,具有进程内存转储、PE文件头编辑、PE重建等丰富多样的功能,并且支持插件。下载地址PE Tools工具可用获取系统中正在运行的所有进程的列表,并将之显示在主窗口中。
进程内存转储 转储:将内存中的内容转存到文件,这种转储技术主要用来查看正在运行的进程内存中的内容,文件时运行时解压缩文件时,其只有在内存中才以解压缩形态存在,此时借助转储技术可用轻松查看与源文件类似的代码与数据。程序主窗口分为上下两部分,上半部分显示的时正在运行的进程,下半部分显示的时当前所选进程加载的DLL模块,转储进程的可执行文件映像时,先在上半部分窗口选中相应进程,然后单击鼠标右键,弹出快捷菜单。PE Tools为用户提供了如下3各转储选项: Dump Full(完整转储)
PE Tools会检测进程PE文件头,并从ImageBase地址开始转储SizeOfImage大小的区域。Dump Partial(部分转储)
该功能用来从相应进程内存的指定地址开始转储指定大小的部分。
Dump Region(区域转储)
进程内存(用户区域)中所有分配区域都被标识为某种状态,区域转储功能用于转储状态标识为COMMIT的内存区域。
PE编辑器 直接手动修改PE文件时,需要修改PE文件头,此时使用PE Tools的PE编辑器功能会非常方便,使用时拖动目标PE文件,或在工具栏中选中Tools-PE Editor即可。PE编辑器可用列出PE文件头的各种信息,借此可用对其进行详细修改。
这篇文章的意义是,为wpf自定义控件,定义它的专属属性,这个属性不仅仅可以在c#中使用,也可以在xaml中使用,在xaml中赋值或者绑定。
在wpf开发过程中,总会用到格式各样的控件,但是原生控件远远不能满足实际开发的需要,这时候wpf强大之处就能体现出来了。根据实际需求自定义各种不同的控件满足不同的业务需求。
首先说需求吧:
一:根据某个绑定的int值,控制一个圆形控件显示或者不显示某种颜色。
分析:
一:需求就一句话,但是根据这一句话,就能得到一些必要的信息。
1.控件绑定的值是个int型。
2.圆形控件。
3.根据传进来的int值做逻辑处理。
分析完需求之后就要开始思考怎么实现了,仔细想想,其实wpf中的Ellipse控件可以画出带颜色的圆形,问题就在于如何根据绑定的值显示某种颜色。
如果对代码要求不高,没什么复用性要求的话,可以直接写在xaml对应的.cs文件中,按照bool值来给控件赋值颜色,但是如果对这个圆形复用性很高,或者代码分离,不允许在.cs文件中写代码,那就只能想其他办法了。
啰嗦到现在,实现这个控件有三个方式:1.写在xaml对应的.cs中。2.写一个convert类来转换。3.自定义一个圆形控件。
本文着重说一下自定义圆形控件,另外两种方式不赘述。
实现:
一.新建wpf引用程序,名为LedTest,新建一个名为LED的用户控件,用来写自定义的控件,项目结构为下图:
二.在用户控件中的界面上先画好带颜色的圆形:
三.重头戏来了,接下来就是依赖属性了。
首先,什么是依赖属性?为什么要用依赖属性?
完整的依赖属性解释百度上有,我就说一下我的理解:依赖属性是wpf提供的一种为丰富控件属性,使依赖属性可以依赖于控件绑定的值,并可以对这些值进行一些逻辑处理的东西。
了解了什么是依赖属性后就知道了为什么要用依赖属性,因为依赖属性能够拓展控件的属性,譬如给button增加一个新的属性,使button绑定值的时候能达到某种效果。
废话不说了,直接上代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace LedTest
{
/// <summary>
/// LED.xaml 的交互逻辑
/// </summary>
public partial class LED : UserControl
{
/// <summary>
/// 构造函数
/// </summary>
public LED()
{
InitializeComponent();
}
/// <summary>
/// 定义属性
/// </summary>
public int Colors
{
get { return (int)GetValue(ColorsProperty); }
一、静态类型转换:static_cast #include<Windows.h> #include<iostream> using namespace std; class A { public: virtual void Show() { cout << "基类:A\n"; } void role() { cout << "啥也不干!\n"; } }; class B :public A { public: void Show() { cout << "派生类:B\n"; } void role() { cout << "哈哈哈\n"; } }; class C :public A { public: void Show() { cout << "派生类:C\n"; } void role() { cout << "啦啦啦\n"; } }; int main(void) { A a; B b; C c; A* ap = &b; /**************************************************** 静态类型转换:static_cast 仅当允许转换的时候,才可以用,取代隐式转换 ****************************************************/ B* bp = static_cast<B*>(ap); bp->role(); system("
在Android中,您可以通过调用方法setOnClickListener将OnClick绑定到按钮等view上。
在Flutter中,有两种方法:
1.如果Widget支持事件监听,则可以将一个函数传递给它并进行处理。例如,RaisedButton有一个onPressed参数 @override Widget build(BuildContext context) { return new RaisedButton( onPressed: () { print("click"); }, child: new Text("Button")); } 2.如果Widget不支持事件监听,则可以将该Widget包装到GestureDetector中,并将处理函数传递给onTap参数 class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( body: new Center( child: new GestureDetector( child: new FlutterLogo( size: 200.0, ), onTap: () { print("tap"); }, ), )); } } 2.1.使用GestureDetector,可以监听多种手势 (1)Tap
onTapDownonTapUponTaponTapCancel (2)Double tap
onDoubleTap 用户快速连续两次在同一位置轻敲屏幕 (3)长按
onLongPress (4)垂直拖动
onVerticalDragStartonVerticalDragUpdateonVerticalDragEnd (5)水平拖拽
onHorizontalDragStartonHorizontalDragUpdateonHorizontalDragEnd 2.2.示例:监听FlutterLogo的双击事件,双击时使其旋转。 void main() => runApp(DemoApp()); class DemoApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: '导航演示1', home: new MyAppHome(), ); } } class MyAppHome extends StatefulWidget{ @override _MyAppHomeState createState() => _MyAppHomeState(); } class _MyAppHomeState extends State<MyAppHome> with TickerProviderStateMixin{ AnimationController controller; CurvedAnimation curve; @override void initState() { super.
什么是AJAX,为什么要使用Ajax?
AJAX是异步的JavaScript和XML,是一种用于创建快速动态网页的技术,使用AJAX可以更新部分网页内容,是非常方便使用的在 Ajax应用中信息是通过XML数据或者字符串在浏览器和服务器之间传递的(json字符串居多)在浏览器端通过XMLHttpRequest对象的responseXMl属性,得到服务器端响应的XML数据。
AJAX优点: 最大的一点是页面无刷新,用户的体验非常好。使用异步方式与服务器通信,具有更加迅速的响应能力。可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。 AJAX缺点: ajax不支持浏览器back按钮。安全问题 AJAX暴露了与服务器交互的细节。对搜索引擎的支持比较弱。破坏了程序的异常机制。不容易调试。 AJAX应用和传统Web应用有什么不同?
传统的web前端与后端的交互中,浏览器直接访问Tomcat的Servlet来获取数据。Servlet通过转发把数据发送给浏览器。
当我们使用AJAX之后,浏览器是先把请求发送到XMLHttpRequest异步对象之中,异步对象对请求进行封装,然后再与发送给服务器。服务器并不是以转发的方式响应,而是以流的方式把数据返回给浏览器
XMLHttpRequest异步对象会不停监听服务器状态的变化,得到服务器返回的数据,就写到浏览器上【因为不是转发的方式,所以是无刷新就能够获取服务器端的数据】
ajax 的执行过程
创建XMLHttpRequest对象,也就是创建一个异步调用对象
创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
设置响应HTTP请求状态变化的函数
发送HTTP请求
获取异步调用返回的数据
使用JavaScript和DOM实现局部刷新
// 1.创建 ajax请求 依赖一个对象xhr对象 var xhr; if (window.XMLHttpRequest){// IE7+, Firefox, Chrome, Opera, Safari xhr = new XMLHttpRequest(); } else{// IE6, IE5 xhr = new ActiveXObject("Microsoft.XMLHTTP"); } //服务器响应:如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。 console.log(xhr) console.log("状态码:" + xhr.readyState) //0 1 2 3 4 console.log("响应码:" + xhr.status) console.log("响应的内容:" + xhr.responseText) //响应的文本 // 2.
二叉树的度是指树中所以结点的度数的最大值。二叉树的度小于等于2,因为二叉树的定义要求二叉树中任意结点的度数(结点的分支数)小于等于2 。
1 基本概念 二叉树是树形结构中一种特殊的树形结构:二叉树中的每个结点至多有2棵子树(即每个结点的度小于等于2),并且两个子树有左右之分,顺序不可颠倒。在二叉树中还有种特殊的二叉树就是完全二叉树:度为1的N1只有0个或1个称之为完全二叉树。所有结点中除了叶子结点以外的结点都有两棵子树的完全二叉树称为满二叉树。 2 重要性质 二叉树中,第m-层最多有2^(m-1)个结点(根结点为第一层)
高度为k的二叉树至多有2^k-1个结点
二叉树T叶子结点总数为n0,度为2的结点个数为n2,则n0=n2+1
如果完全二叉树有n个结点,那么树最高为log2(n)+1
对于完全二叉树,从上至下,从左至右对每个结点从1-n编号,那么对于结点n有:
如果i=1,那么此结点为根结点,如果i>1那么该结点的父结点为不大于i/2的最大整数
如果2i>n,那么i结点没有左子树,如果2i<=n那么该结点的左子树编号为2*i
如果2i+1>n,那么结点i没有右子树,如果2i+1<=n那么该结点的右子树编号为2*i+1
例如: 比如一棵二叉树有10个度为1的节点,7个度为2的节点,则二叉树有多少个节点(25)
根据刚才说的,节点数比度数多1,可以列出计算式子:
10 * 1 + 7 * 2 + 1 = 25
分支数: 有多少条边 3 基本操作集合 InitBitTree(&T):初始化二叉树为一棵空树 CreateBitTree(&T):创建二叉树 DestroyBitTree(&T):删除二叉树 InsertLeftChild(p,c):将二叉树c插入到p所指向的左子树 InsertRightChild(p,c):将二叉树c插入到p所指向的右子树 LeftChild(&T,e):返回左孩子 RightChild(&T,e):返回右孩子 DeleteLeftChild(&T,p):删除左孩子 DeleteRightChild(&T,p):删除右孩子 PreOrderTraverse(T):前序遍历二叉树 InOrderTraverse(T):中序遍历二叉树 PostOrderTraverse(T):后序遍历二叉树 LeverTraverse(T):层次遍历二叉树 BitTreeDepth(T):求二叉树的高度 4 存储方式 顺序存储:完全二叉树中每个结点的编号可以通过性质求得,所以可以将元素按从上至下、从左至右的顺序放入一维数组中。而对于非完全二叉树,则只需要将相对于完全二叉树缺失的结点用“^"代替。
链式存储:二叉树的链式存储需要三个域存储:数据域、左孩子指针域和右孩子指针域。两个指针域分别指向左右子树。这种存储结构叫做二叉链表存储。如果再加上一个指向父结点的指针域那么就称为三叉链表存储。
1.类加载器
1.1类加载【理解】
类加载的描述 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始 化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把 这三个步骤统称为类加载或者类初始化 类的加载 就是指将class文件读入内存,并为之创建一个 java.lang.Class 对象 任何类被使用时,系统都会为之建立一个 java.lang.Class 对象 类的连接 验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致 准备阶段:负责为类的类变量分配内存,并设置默认初始化值 解析阶段:将类的二进制数据中的符号引用替换为直接引用 类的初始化 在该阶段,主要就是对类变量进行初始化 类的初始化步骤 假如类还未被加载和连接,则程序先加载并连接该类 假如该类的直接父类还未被初始化,则先初始化其直接父类 假如类中有初始化语句,则系统依次执行这些初始化语句 注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3 类的初始化时机 创建类的实例 调用类的类方法 访问类或者接口的类变量,或者为该类变量赋值 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象 初始化某个类的子类 直接使用java.exe命令来运行某个主类 1.2类加载器【理解】 1.2.1类加载器的作用
负责将.class文件加载到内存中,并为之生成对应的 java.lang.Class 对象。虽然我们不用过分关心类加载机 制,但是了解这个机制我们就能更好的理解程序的运行! 1.2.2JVM的类加载机制
全盘负责:就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载 器负责载入,除非显示使用另外一个类加载器来载入 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器 无法加载该类时才尝试从自己的类路径中加载该类 缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜 索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成
Class对象,存储到缓存区 1.2.3Java中的内置类加载器
Bootstrap class loader:它是虚拟机的内置类加载器,通常表示为null ,并且没有父null Platform class loader:平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类 System class loader:它也被称为应用程序类加载器 ,与平台类加载器不同。 系统类加载器通常用于定义应 用程序类路径,模块路径和JDK特定工具上的类 类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap 1.2.4ClassLoader 中的两个方法
方法名 说明
static ClassLoader getSystemClassLoader() 返回用于委派的系统类加载器
1.函数式接口
1.1函数式接口概述【理解】
概念 有且仅有一个抽象方法的接口 如何检测一个接口是不是函数式接口 @FunctionalInterface 放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败 注意事项 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数 式接口定义的条件,也照样是函数式接口。但是,建议加上该注解 1.2函数式接口作为方法的参数【应用】
需求描述 定义一个类(RunnableDemo),在类中提供两个方法 一个方法是:startThread(Runnable r) 方法参数Runnable是一个函数式接口 一个方法是主方法,在主方法中调用startThread方法 代码演示
public class RunnableDemo { public static void main(String[] args) { //在主方法中调用startThread方法
//匿名内部类的方式 startThread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + “线程启动了”); } }); //Lambda方式 startThread(() -> System.out.println(Thread.currentThread().getName() + “线 程启动了”));
}
private static void startThread(Runnable r) { new Thread®.start(); } }
1.3函数式接口作为方法的返回值【应用】
需求描述 定义一个类(ComparatorDemo),在类中提供两个方法 一个方法是:Comparator getComparator() 方法返回值Comparator是一个函数式接口 一个方法是主方法,在主方法中调用getComparator方法 代码演示