软件版本

一般项目版本分三段:主、次、修订。
SNAPSHOT表示开发中的版本
RELEASE表示正式发布版本
RC:release candidate 发布候选版本
GA:general avaliability 基本可用版本
NG:next generation
M:MileStone 里程碑
TM:Trade Mark 注册商标,带上TM同时起到了强调这个已是注册商标的作用。

周期顺序:
SNAPSHOT->ml->m2…->RC->GA->RELEASE

API版本控制,我使用的方式是,客户端在请求头中添加客户端版本号,服务端根据客户端版本控制响应内容。对新客户端而新增加的API,对其做好注释即可。
纵观各大网站的API,使用URL中显示添加版本号的最多,添加头部信息控制版本的次之,几乎没有强制使用统一版本的。
控制API使用周期,最多不超过5个版本同时在使用,定期下架老旧的API版本。
https://www.jianshu.com/p/e39f9d77e35d

Docker

从 2017 年 3 月开始 docker 在原来的基础上分为两个分支版本: Docker CE 和 Docker EE。Docker CE 即社区免费版,Docker EE 即企业版,强调安全,但需付费使用。

Docker官方文档
https://docs.docker.com/reference/
DOCKER入门
https://ppt.fujiabin.com/tutorial/docker/
Mac上用Docker搭建lamp环境
http://www.56cto.com/1089
Docker for Mac 初体验
https://segmentfault.com/a/1190000005106237
在MAC上运行Docker和Oracle 12.2数据库环境
http://database.51cto.com/art/201705/540105.htm
Docker 教程 及 Docker 命令大全
http://www.runoob.com/docker/docker-tutorial.html
http://www.runoob.com/docker/docker-command-manual.html
Docker —— 从入门到实践
https://yeasy.gitbooks.io/docker_practice/content/
https://www.gitbook.com/book/yeasy/docker_practice/details
Docker使用阿里云docker镜像加速
https://www.cnblogs.com/zhxshseu/p/5970a5a763c8fe2b01cd2eb63a8622b2.html
https://dev.aliyun.com/search.html
2017年,使用docker开发应用程序
https://zhuanlan.zhihu.com/p/25092632
下载Docker for Mac
https://download.docker.com/mac/stable/Docker.dmg

容器存储层

镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,这个存储层为容器运行时读写而准备,我们称它为容器存储层。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的持久化操作,都应该使用 数据卷(Volume),或者绑定宿主目录。在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
https://yeasy.gitbooks.io/docker_practice/content/basic_concept/container.html

运行时参数

    • –name 容器名称。
    • –hostname 容器主机名称。
    • -t 让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上
    • -i interactive,让容器的标准输入保持打开
    • -d detached 以后台进程方式运行容器,并返回容器ID。还可以使用Ctrl+p+q将容器放在后台运行。此时容器不会把输出的结果(STDOUT)打印到宿主机上面(输出结果可以用docker logs 查看)。
    • -p 创建特定端口绑定规则。一个-p指定一个端口映射,可使用多个-p指令多个映射。
    • –rm 容器退出后随之将其删除
    • –restart=always 设置容器的重启策略,以决定在容器退出时Docker守护进程是否重启刚刚退出的容器。–restart选项通常只用于detached模式的容器,i不能与–rm选项同时使用
    • -v 目录或文件映射挂载,宿主中的路径:Docker容器中的路径,主机和容器中某个目录同步。-v 参数可以多次使用,每次映射一个目录。
    • -w 表示将-v映射的/webapp目录设置为work directory,也就是运行node命令的目录。这个设置将覆盖Dockfiie中的设置:/Data。
    • –privileged=true 大约在0.6版,privileged被引入docker。使用该参数,container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。

更多参数解释 http://blog.csdn.net/alen_xiaoxin/article/details/54694051

运行时端口映射

-p参数内容有几种不同的格式:
ip:hostPort:containerPort| ip::containerPort | hostPort:containerPort | containerPort
其中,ip或者hostPort可以忽略。默认为tcp,如果需要udp,需要在最后指定,比如-p 1234:1234/udp。在多个容器都暴露端口时,须注意避免端口冲突。
所有发布(-p或者-P)的端口都暴露了,但并不是所有暴露(EXPOSE或–expose)的端口都会发布。

link用来解决关联的容器IP变化的问题,而expose只是用来标记一下开放的端口,没有任何实际的效果,官方文档上说给link用其实是种误导。因为在没有link和expose情况下,通过IP+端口也能从一个容器访问另一个容器的服务。

快速参考:

创建一个新的容器并运行一个命令

命令跟在镜像名之后,命令运行后容器终止。当Docker容器中指定的应用终结时,容器也自动终止。

docker run ubuntu /bin/echo "Hello world"
docker run ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

运行交互式的容器

docker run --name name1 -i -t ubuntu /bin/bash

通过exit命令或使用CTRL+D退出并停止容器。使用组合键 ctrl(Mac上是control) + p + q 退出容器后容器不会停止。

交互式连接容器

如果容器运行的时候加了 -d 参数,就可以通过 attach 或 exec 进入容器进行操作:

docker attach -i -t CONTAINER_NAME /bin/bash
docker exec -it CONTAINER_ID bash
docker exec -it CONTAINER_ID /bin/sh

在输入exit或者logout命令退出docker容器时,有时会出现“there are stopped jobs”,这个提示表示服务器有程序被停止[注意,不是终止],需要重新启动或者完全终止这个程序才可以退出系统。这可能是由于按下了Ctrl+Z之后使程序或者进程被挂起。
输入命令jobs -l显示停止进程的详细列表。
可以通过如下命令杀死或者激活停止的进程:
杀死:kill %1(%1是将要被杀死的job的进程号)
激活:fg %1(%1是将要被激活的job的进程号),fg代表foreground(前台),可以唤醒被suspended(挂起)的进程。
再次用logout、exit就可以退出了。

运行mysql

docker run -p 3306:3306 --name mysql1 -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6

使用Docker快速搭建Mysql,并进行数据卷分离
https://www.jianshu.com/p/57420240e877
docker安装mysql,可能mysql8要对用户进行授权,否则用navicat连接不上。
https://blog.csdn.net/wyl9527/article/details/79111467

运行nginx

nginx相关路径有 /etc/nginx/、/etc/nginx/conf.d、/usr/share/nginx/html

docker run --name nginx1 -p 8887:80 -v /主机html目录:/usr/share/nginx/html nginx
docker run -p 81:80 --name szsmart-www -v /opt/szsmart/angular:/usr/share/nginx/html -d nginx
docker run -p 82:80 --name hksmart-www -v /opt/hksmart/angular:/usr/share/nginx/html -d nginx

运行mongo

docker run -p 14000:27017 --name mongo_db -v /opt/mongo_db:/data/db -d mongo

运行tomcat

docker run -d –restart always -v /alidata/webapps/ReadAdmin.war:/usr/local/tomcat/webapps/ReadAdmin.war -p 8080:8080 –name tomcat1 tomcat
Docker实践 – 安装Docker并在容器里运行tomcat
https://blog.csdn.net/massivestars/article/details/54352484

数据卷Volume映射

-v 后面可以跟多个映射,本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动创建它。
Docker 挂载数据卷的默认权限是读写,可以在容器路径后加上 :ro 指定为只读。

-v /some/nginx.conf:/etc/nginx/nginx.conf:ro

还可以对正在运行的容器追加映射:

docker run -v /path/to/hostdir:/mnt $container

生成镜像

1.从基础镜像生成镜像
编辑Dockerfile文件,例如输入内容:

FROM docker.io/tomcat    #基础镜像
MAINTAINER XXX@qq.com    #作者
COPY docker.war /usr/local/tomcat/webapps  #拷贝war包到tomcat的webapps目录

根据当前目录下的Dockerfile文件配置生成镜像

docker build -t nginx-demo:v1 .

2.保存容器成镜像
将容器的存储层保存下来成为镜像,在旧的镜像上添加了新的一层,形成新的镜像。
脱离容器保持运行,使用ctl+p+q快捷键,然后可以看到刚启动的容器继续在运行。

docker commit -m "descriptiont" -a "author" container_id new_name
docker commit \
--author "作者" \
--message "修改了默认网页" \
webserver \
nginx:v2

自动处理安装过程中的询问,Do you want to continue? [Y/n] Abort.
添加 -y、–yes、–assume-yes参数,例如 apt-get install xxx –assume-yes

导出镜像为文件

docker save container_ID > /home/nginx-demotest.tar

查看容器相对镜像的改动
docker diff CONTAINER_ID
查看镜像内的历史记录
docker history 镜像名

其它命令

#启动docker服务
service docker start

当服务器因docker慢时,可以停止docker,或docker rm删除中的服务。

镜像操作:

#查找镜像
docker search ubuntu
#获取镜像
docker pull nginx:latest
#查看本地镜像
docker images | grep abc
docker images IMAGE_NAME
#删除镜像
docker rmi IMAGE_ID

容器操作:

#查看运行的容器
docker ps
#查看运行和终止状态的容器
docker ps -a
#删除容器
docker rm  CONTAINER_ID  要删除一个运行中的容器,可以添加 -f 参数,Docker 会发送 SIGKILL 信号给容器。
docker rm $(docker ps -a -q) 清理所有处于终止状态的容器。
docker stop $(docker ps -q) 停用全部运行中的容器
docker rm $(docker ps -aq) 删除全部容器
docker stop $(docker ps -q) & docker rm $(docker ps -aq) 一条命令实现停用并删除容器

#查看容器内的标准输出。
docker logs -f -t --since="2019-05-31" --tail=10 CONTAINER_ID
参数:
--since : 此参数指定了输出日志开始日期,即只输出指定日期之后的日志。
-f : 查看实时日志
-t : 查看日志产生的日期
-tail=10 : 查看最后的10条日志。
#停止容器运行,对于只启动了一个终端的容器,通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止。
docker stop CONTAINER_ID
#将一个终止状态的容器启动运行
docker start CONTAINER_ID
#重启容器
docker restart CONTAINER_ID
#容器内运行nginx服务
docker exec CONTAINER_ID nginx  
#查看容器运行时端口绑定信息
docker port CONTAINER_ID
#查看容器详细的网络信息
docker inspect CONTAINER_ID
#查看容器的IP
docker inspect CONTAINER_ID | grep '"IPAddress"',或者 进入容器内部后 cat /etc/hosts
#主机和容器之间拷贝文件
docker cp mysql_master:/etc/mysql/my.cnf /alidata/docker_work/mysql_master/config/my.cnf

Detached vs foreground

启动一个container时,首先需要确定这个container是运行在前台模式还是运行在后台模式。
Detached (-d)
如果在docker run 后面追加-d=true或者-d,则containter将会运行在后台模式(Detached mode)。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。因为container不再监听你执行docker run的这个终端命令行窗口。但你可以通过执行docker attach 来重新挂载这个container里面。需要注意的时,如果你选择执行-d使container进入后台模式,那么将无法配合”–rm”参数。
Foregroud
如果在docker run后面没有追加-d参数,则container将默认进入前台模式(Foregroud mode)。Docker会启动这个container,同时将当前的命令行窗口挂载到container的标准输入,标准输出和标准错误中。也就是container中所有的输出,你都可以再当前窗口中查看到。
容器是否会长久运行,和docker run指定的命令有关,和 -d 参数无关。

查找镜像
sudo docker search nginx
而具体版本号到https://hub.docker.com/explore/中查找。

How to run NGINX as a Docker container
https://www.techrepublic.com/article/how-to-run-nginx-as-a-docker-container/

Linux f2b4dd41f60e 4.9.49-moby #1 SMP Wed Sep 27 23:17:17 UTC 2017 x86_64 GNU/Linux

查看docker容器的系统信息

wangweikedeMacBook:~ admin$ docker run --name nginx1029 -t -i nginx bash
root@b519367267ca:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@b519367267ca:/# uname -r
4.9.36-moby
root@b519367267ca:/# uname -a
Linux b519367267ca 4.9.36-moby #1 SMP Wed Jul 12 15:29:07 UTC 2017 x86_64 GNU/Linux

公司测试服务器

#mongodb
docker run -p 14000:27017 –name mongo_db -v /opt/mongo_db:/data/db -d mongo
docker run -p 81:80 –name szsmart-www -v /opt/szsmart/angular:/usr/share/nginx/html -d nginx
docker run -p 82:80 –name hksmart-www -v /opt/hksmart/angular:/usr/share/nginx/html -d nginx

在Centos中安装与卸载docker

yum install docker-io
service docker start

https://docs.docker.com/install/linux/docker-ce/centos/#install-docker-ce-1
https://rancher.com/docs/rancher/v1.6/zh/hosts/#docker%E7%89%88%E6%9C%AC%E9%80%82%E7%94%A8%E5%AF%B9%E6%AF%94

docker容器运行后退出的问题

Docker容器后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就是会自动退出的。这个是docker的机制问题。

docker run -d -it --net=host --name cnmp4 wwk/cnmp /bin/sh

http://blog.51cto.com/gentle/1826820

使用 Dockerfile脚本 定制镜像

把每一层修改、安装、构建、操作的命令都写入Dockerfile,用这个脚本来构建、定制镜像,解决了之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题。
使用Dockerfile构建Docker镜像为一个规范的方式,根据Dockerfile可以了解镜像中安装的组件的详细内容。
Dockerfile一般由四部分组成:
第一,构建的基础镜像;
第二,镜像构建者的信息;
第三,构建镜像过程中镜像层添加指令;
第四,由该镜像启动容器时执行的程序。

link

设定的别名要和容器环境中使用的变量名字一致。

Docker在连接容器的时候,会根据–link提供的参数自动的在接收者容器中创建一些环境变量,包括源容器的Dockerfile中使用ENV命令设置的环境变量和源容器启动时(docker run),使用-e或者–env, –env-file参数指定的环境变量。
除了环境变量之外,Docker也在接收容器的/etc/hosts文件中更新了hosts信息。与环境变量不同的是,如果源容器重启了,接收容器中/etc/hosts中的信息会自动更新。
https://www.cnblogs.com/jytx/p/5438747.html

基于Docker搭建LNMP环境,独立安装mysql、php-fpm、nginx,然后各容器用link参数建立起联系。
https://blog.csdn.net/xy752068432/article/details/75975065

https://blog.csdn.net/zhangyifei216/article/details/50921215
https://www.jianshu.com/p/13752117ff97

docker加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF' #相当于在daemon.json中输入以下内容
{
  "registry-mirrors": ["https://4qqg0972.mirror.aliyuncs.com"]
}
EOF
#重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker

从容器中访问到宿主机的网络

在docker容器中访问localhost是访问的容器的localhost,而不是宿主机的localhost。
1.使用宿主机公网IP
2.使用宿主机虚拟IP
安装Docker的时会在宿主机安装一个虚拟网关 docker0 ,可以使用宿主机在 docker0 上的IP地址。
使用如下命令查询宿主机IP地址:

ip addr show docker0

发现宿主机的IP是 172.17.0.1 ,但是不同系统下宿主机的IP是不同的,例如Linux下一般是 172.17.0.1 , macOS下一般是 192.168.65.1 ,并且这个IP还可以更改。所以使用虚拟IP不能跨环境通用。
3.使用host网络
Docker容器运行的时候有 host 、 bridge 、 none 三种网络可供配置。
默认是 bridge ,即桥接网络,以桥接模式连接到宿主机;
host 是宿主网络,即与宿主机共用网络;
none 则表示无网络,容器将无法联网。

当容器使用 host 网络时,容器与宿主共用网络,这样就能在容器中访问宿主机网络,那么容器的 localhost 就是宿主机的 localhost 。
在docker中使用 –network host 来为容器配置 host 网络:

$ docker run -d --name nginx --network host nginx

上面的命令中,没有必要使用 -p 80:80 -p 443:443 来映射端口,是因为本身与宿主机共用了网络,容器中暴露端口等同于宿主机暴露端口。

上述方法各有优劣,使用宿主机IP隔离性更好,但通用性不好;使用host网络,通用性好,但带来了暴露宿主网络的风险。

wordpress

docker run --name wp1 --link mysql1:mysql -p 80:80 -v /home/apache2/apache2.conf:/etc/apache2/apache2.conf -v /home/www/brogrammer:/var/www/html -e WORDPRESS_DB_NAME=wwk_wordpress -d wordpress

Centos 7.5 中 docker 启动web服务,但外部无法访问。

解决办法:
# vi /etc/sysctl.conf
或者
# vi /usr/lib/sysctl.d/00-system.conf
添加如下代码:
net.ipv4.ip_forward=1

重启network服务,或者重启服务器。
# systemctl restart network

docker容器中安装缺失命令

先要执行apt-get update同步 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出的源的索引,这样才能获取到最新的软件包。
apt-get install vim
​apt-get install telnet
apt-get install net-tools
apt install iputils-ping

设置docker开机自启动
systemctl enable docker
成功后打印 Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.

错误处理

启动一个容器时遇到过以下问题:
docker: Error response from daemon: service endpoint with name xxx already exists.
这说明此端口已经被名为xxx的容器占用了。
https://blog.csdn.net/moshenglv/article/details/82533896

锚点

锚点

(1)使用id定位
id定位可以针对任何标签。
(2)使用name定位
name属性只能针对a标签来定位。

html页面内锚点定位及跳转方法

第一种方法,使用锚点,缺点是点击锚点之后,浏览器的URL会发生变化。
第二种方法,在js事件中通过window.location.hash=”xxid”跳转,地址也会发生变化。
第三种方法,用js的srollIntoView方法,document.getElementById(“divId”).scrollIntoView(),使用这种方法URL不会变,同时能够响应相应的scroll事件。
第四种方法,在js事件中通过window.location.href=”xxid”跳转,效率比srollIntoView差。

“window.location.hash = location.hash” does not work in Webkit (Safari & Chrome)

Webkit responds to window.location.href instead of window.location.hash (like all the other browsers do). Curiously, webkit can still read the URL’s hash tag using location.hash

https://stackoverflow.com/questions/6970769/window-location-hash-location-hash-does-not-work-in-webkit-safari-chrome

Spring-mongodb

Spring Boot中访问数据库

1.JdbcTemplate,是Spring在JDBC的基础上做了一些封装,面向SQL的访问数据库方式。
2.使用Spring-data-jpa在JPA提供的简单语义上做了一定的封装,整合orm框架访问数据库,默认采用Hibernate实现。Spring Data是面向对象的访问数据库方式。
JPA:Java Persistence API,java持久化api。
Repository 抽象了对数据库的操作,提供了以下接口:CrudRepository、PagingAndSortingRepository、JpaRepository。
注解查询:@Query中允许使用JPQL或SQL来给出查询方法。

Spring-data-mongodb

Spring-data对MongoDB进行了很好的支持,包括以下特征:
mongodb在spring中的配置支持注解 @Configuration和xml的方式。
MongoTemplate辅助类扩展了Mongo operations的生产效率,提供了document和pojo类型之间的转换。MongoOperations是MongoTemplate实现的接口,MongoOperations中有很多操作文档的方法。

参考:
http://docs.spring.io/spring-data/data-document/docs/current/reference/html/
Spring-mongodb 查询
http://docs.spring.io/spring-data/mongodb/docs/1.2.0.RELEASE/reference/html/mongo.repositories.html
http://blog.csdn.net/congcong68/article/details/47183209
Spring Data与MongoDB:不协调的设计,及评论
http://www.infoq.com/cn/news/2013/11/spring-data-mongo-mismatch
MONGODB中的分组聚合在JAVA中的用法
http://www.debugrun.com/a/1pcWFsT.html

MongoRepository

如果只需要用简单的CRUD操作,则不需要添加其他的方法,MongoRepository提供的方法足够使用。
MongoRepository接口有两个参数:第一个参数是带有@Document注解的对象类型,第二个参数是带有@Id注解的属性类型。

public interface PersonRepository extends MongoRepository<Person, String>{
}
注解 描述
@Document(collection=”name1″) 标示映射到mongoDB文档上的领域对象
@ID 标示某个为ID域
@DbRef 标示某个域要引用其他的文档,这个文档有可能位于另外一个数据库中
@Field(“field1”) 为文档域指定自定义的元数据,若不使用@Field注解,域名与Java属性相同
@Version 标示某个属性用作版本域

 

@Query注解指定查询:
使用@Query时,方法名可不按照规则来写,这可能自由缩短条件多的查询方法名。
@Query注解中的内容是一个 JSON 对象,和在 MongoDB 的控制台查询的find()中的内容是一样的,只不过将双引号换成单引号,将需要变量用 [0]、[1] 和 [2] 的形式表示第一、第二和第三个参数。?#{} 是表示里面的内容是个 SpEL (Spring 的表达式语言) 表达式。

import org.bson.types.ObjectId;
public interface PersonRepository extends MongoRepository<Person, ObjectId> {
    //根据实体类中的属性进行模糊查询带分页,同时指定返回的键:
    /*
    value是查询的条件,?0是占位符,对应着方法中参数中的第一个参数,如果对应的是第二个参数则为?1。
    fields指定返回字段,其中id是自动返回的,不用指定。bson中{'name':1}中的1代表true,表示返回此字段。
    */
    @Query(value="{'name':?0}",fields="{'name':1}")
    public Page findByNameLike(String name,Pageable pageable);

    //查询所有id不为空的数据,同时指定返回的键。方法名的定义规则为:find + By + 属性名(首字母大写) + NotNull。
    @Query(value="{'_id':{'$ne':null}}",fields="{'name':1}")
    public Page findByIdNotNull(Pageable pageable);
}

当MongoDB遇上Spring
http://blog.csdn.net/u012150370/article/details/51822776
A Guide to Queries in Spring Data MongoDB

A Guide to Queries in Spring Data MongoDB

distinct

mongoTemplate.getCollection("collection_name").distinct("field", new BasicDBObject("price", new BasicDBObject("$gt", 10)));
Criteria criteria = getCriteria(conditions, "and");
List values = mongoTemplate.getCollection(collectionName).distinct(distinctField, new Query(criteria).getQueryObject());
String jsonSql="{distinct:'terminalRecord', key:'areaId'}";
CommandResult commandResult=mongoTemplate.executeCommand((DBObject) JSON.parse(jsonSql));
DBObject dbObject=BasicDBObjectBuilder.start("distinct",collectionName).add("key",distinctKey).get();
CommandResult commandResult=mongoTemplate.executeCommand(dbObject);
List values=(List)commandResult.get("values");

微信开发

小程序

获取用户过去三十天微信运动步数,需要先调用 wx.login 接口。
https://developers.weixin.qq.com/miniprogram/dev/api/we-run.html
小程序登录
https://developers.weixin.qq.com/miniprogram/dev/api/api-login.html
关于小程序中网络相关API的说明
https://developers.weixin.qq.com/miniprogram/dev/api/api-network.html?t=1524891362

高数

阶乘

阶乘是基斯顿·卡曼(Christian Kramp,1760~1826)于 1808 年发明的运算符号。
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿·卡曼引进这个表示法。
亦即n!=1×2×3×…×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。阶乘没有封闭的通项公式。

组合

组合(combination),数学的重要概念之一。从n个不同元素中每次取出m个不同元素(0≤m≤n),不管其顺序合成一组,称为从n个元素中不重复地选取m个元素的一个组合。所有这样的组合的总数称为组合数。

排列

排列可分选排列与全排列两种,在从n个不同元素取出m个不同元素的排列种,当m小于n时,这个排列称为选排列;当m=n时,这个排列称为全排列。n个元素的全排列的个数记为Pn。
Pn=n!。

同济高等数学第六版上册习题全解指南.
https://pan.baidu.com/share/link?uk=2317362003&shareid=3026054346
人教版高中数学电子课本全套pdf
https://zhidao.baidu.com/question/1888471680276922628.html

计算公式

阶加:1+2+3+…+n = n(n+1)/2
阶乘:1×2×3×…×n = n! = (n-1)! * n

数学符号

定义符号“[]”为取整符号,即[x]表示一个小于或等于x的最大整数,读作高斯x。
向上取整,取比自己大的最小整数, 运算称为 Ceiling,用数学符号 ⌈⌉ (上有起止,开口向下)表示。
向下取整,取比自己小的最大整数,运算称为 Floor,用数学符号 ⌊⌋ (下有起止,开口向上)表示。
对整数向上向下取整,结果都是整数自己。

JS函数:

1. 向上取整,有小数就整数部分加1
Math.ceil(5/2)  //3
2. 四舍五入.
Math.round(5/2)  //3
3. 向下取整
Math.floor(5/2) //2

计算器log以2为底,用换底公式:log(2)x=(lnx)/(ln2)。

|集合A| 表示集合A的点的数量。

http://www.fhdq.net/sx/12.html

Spring boot 项目容器化

1.在pom.xml中增加使用docker-maven-plugin,Spring Boot Maven plugin 提供了很多方便的功能,包括:
收集的类路径上所有 jar 文件,并构建成一个单一的、可运行的jar。
搜索 public static void main() 方法来标记为可运行的类。

<properties>
    <docker.image.prefix>wwk</docker.image.prefix>
</properties>
<build> 
<plugins> 
<plugin> 
<groupId>com.spotify</groupId> 
<artifactId>docker-maven-plugin</artifactId> 
<configuration> 
<imageName>${docker.image.prefix}/${project.artifactId}</imageName> 
<dockerDirectory>src/main/docker</dockerDirectory> 
<resources> 
<resource> 
<targetPath>/</targetPath> 
<directory>${project.build.directory}</directory> 
<include>${project.build.finalName}.jar</include> 
</resource> 
</resources> 
</configuration> 
</plugin> 
</plugins> 
</build>

imageName指定镜像的名字。
dockerDirectory指定 Dockerfile文件 的位置。
resources是指那些需要和 Dockerfile 放在一起,在构建镜像时使用的文件。

构建镜像有两种方式,第一种是将构建信息指定到 POM 中,第二种是使用 Dockerfile 配置构建信息。
2.编写Dockerfile
Docker 使用 Dockerfile 文件格式来指定 image 层。
创建文件 src/main/docker/Dockerfile:

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD test-docker-1.0.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

3.执行构建和运行镜像

mvn package docker:build
docker run -p 8080:8080 -t wwk/test-docker

[INFO] Copying /Users/hycx/i_workspace/test/test-docker/target/test-docker-0.0.1-SNAPSHOT.jar -> /Users/hycx/i_workspace/test/test-docker/target/docker/test-docker-0.0.1-SNAPSHOT.jar
[INFO] Copying src/main/docker/Dockerfile -> /Users/hycx/i_workspace/test/test-docker/target/docker/Dockerfile
[INFO] Building image wwk/test-docker

4.
手动上传Dockerfile和jar文件到服务器,到同目录下,运行下面的命令,生成镜像。

docker build -t wwk/test-docker .
docker images

用 Docker 构建、运行、发布来一个 Spring Boot 应用
https://blog.csdn.net/kkkloveyou/article/details/50942275

Alpine Linux

frolvlad/alpine-oraclejdk8:slim 镜像的基础镜像是 Alpine Linux 3.7。
Alpine Linux 是一个社区开发的面向安全应用的轻量级 Linux 发行版。Alpine采用了musl libc和busybox以减小系统的体积和运行时资源消耗,在保持瘦身的同时,Alpine Linux还提供了自己的包管理工具apk,可以在其网站上查询,或者直接通过apk命令查询和安装。
Alpine Linux作为基础镜像只有5MB。

Spring boot 与 docker

Springboot服务本质上是一个java服务,它也可以同时在jar中打包一个Web服务器例如tomcat。java服务运行所依赖的就是java虚拟机,java虚拟机在大多数操作系统上都会安装。而spring boot服务可以打包为一个可执行的jar,可以很简单的运行管理。这样,一般地在已经安装了java运行环境的服务器上,把spring boot服务运行于docker内的必要性就不大了。

二叉树

Binary Tree,第i(i>=1)层上结点数最大值:2i-1。即1、2、4、8、16…。
深度为i的树的结点数最大值,或从第i(i>=1)到1层所有结点数最大值:2i-1。即1、3、7、15、31。这称为满二叉树。满二叉树的结点数为2k-1,只有度为0和2的结点,并且叶结点都处在最下层。
结点总数n=n2+n1+n0,度为0的结点数n0=n2+1,即叶结点数比双分支的结点数多1个。
二叉树中序号大于n/2的结点没有孩子结点。
完全二叉树中度为1的结点数是0或1。
完全二叉树,n个结点,深度=⌊log2n⌋+1。
完全二叉树,若深度k>1,则 2k-1>=叶子结点数>=2k-2,结点数>=2k-1
深度为k的二叉树,结点数最多为2k-1,最少为k。
深度为k的二叉树,若只有度为0、2的结点,结点数最少为2k-1。
第i个结点的父结点编号为⌊i/2⌋,左孩子编号为2*i,右孩子编号为2*i+1。
n个结点的二叉树的二叉链表中,有2n个指针域,n-1个指针域不为空,n+1个指针域为空,结果发现2n没有被平分,而是多出了一个空指针域是因为根结点没有被指向。
n个结点的二叉树的三叉链表中,除了具有二叉链表的统计结果,然后所有parent指针中只有根结点的parent指针为空。

结点的度:结点的子树的数目。
树的度:树中最大的结点度。
树的高度:也叫深度,即从1开始的最大层次数。
树的出度:树中结点度为D(D>=0)的结点的个数与D的乘积。
树的结点数=各个度(0到树的度)的结点的个数之和=各个结点的度之和再加一。

存储

完全二叉树的顺序存储结构中,编号为i的结点的层次为⌈log2(i+1)⌉ 。

二叉树的链式存储结构中,三叉链表比二叉链表的结点中多了一个parent指针域。

遍历

PreOrder、InOrder、PostOrder、LevelOrder。
先序序列的第一个结点是根结点,后序序列的最后一个结点是根结点,中序序列中由根结点将序列分为为两部分。

先序序列和中序序列相反,则二叉树每个结点只有左子树,左单极树。
先序序列和中序序列相同,则二叉树每个结点只有右子树。
先序序列和后序序列相反,则二叉树高度和结点数相同即可。
先序序列和后序序列相同,则二叉树只有一个根结点。
从一个遍历序列推导出不同形状的二叉树,首先宽二叉树,然后是多种每层单节点二叉树。

中序序列中前后结点在二叉树中的关系是,前面的结点在后面的结点的左边,左边是指左子或其所在分支的父。
交换所有分支左右子树的位置,利用前序遍历方法最合适。
一棵二叉树的前序序列和中序序列,或后序和中序序列可唯一确定这棵二叉树。在先序中第一个字符是根结点,而在后序中最后一个字符是根结点。在中序中,根结点前后分别是其左右子树。按照这个思想递归可推导出二叉树。
方法一:以中序为主线,在前序中找中序的根:
1.在中序中,由树的根分左序L,右序R。在先序中找到排在根后面的第一个L中的值,即为根的左结点。同样地,在先序中找到排在根后面的第一个R中的值,即为根的右结点。在中序中标记根值为墙表示它是已处理完毕的界线,在树中对字符画圈也表示它已处理完毕。
2.再把左右两个结点分别视为根,依次进行步骤1。
当是在后序序列中辅助查找时,方向是从后向前。

遍历实现

1.二叉链表上遍历的递归实现。还可以利用递归遍历求得二叉树的高度为较高的子树的高度加1。
2.二叉树的层次遍历可以借助队列来实现。将根结点入队列,从队列中出一个结点,将该结点的左右孩子结点入队列。如此出入直至队列为空。则入队列或出队列的顺序即为层次遍历的序列。
3.二叉树顺序存储或链式存储上的非递归实现可以借助栈来实现。

算法:输出二叉树各结点的值

//中序遍历
void printtree (BiTree BT)
{
  BiTnode* p=BT;
  InitStruct(s); //构造一个数组结构s
  s.top=0;
  
  while (p || s.top!=0)
  { 
    //把p、左子、左子的左子...,存入eles。
    while (p)
    { 
      s.eles[s.top++]=p;
      p=p->lchild ;
    }
    
    if (s.top>0)
    { 
      //输出eles中最后一个元素。
      p=s.eles[s.top--];
      cout < < p->data;//int pos=s.top,输出的元素将不在eles中继续保存。
      //遍历p的右子树
      p=p->rchild; //在下一次进入循环时,eles[pos]会被替换为p,即原p的右子结点。
    }
  }
}

树和二叉树的转换

树转二叉树:
1.将所有兄弟连接起来;
2.保留兄弟中的第一个结点与父结点的连接,断开其它的父连接;
3.结果即是使这条兄弟链变成以兄长为根的子树,新枝都变为右枝,旧枝变为左枝;
转换后得到的二叉树的根结点的右子树总是空的。

森林转二叉树:
1.将森林中的每棵树转为二叉树;
2.将每棵树对应的二叉树的根作为兄弟结点连接起来;
3.同样遵循子树外部左排列、子树内部右排列的规则;
森林中有m个非终端结点,则其对应的二叉树中有m+1个右指针域为空的结点。右指针为空,即没有右孩子。因为每个非终端结点转换成二叉树后都对应(本身是,或者它的右孩子…是)一个无右孩子的结点,另外最后一棵树的根结点转换后也没有右孩子。
转换后得到的二叉树的根结点和其左子对对应森林中的第一棵树,右子树对应森林中的所有其它树。

二叉树转森林:
1.将根结点与其右子树连线断开,继续对新生的二叉树断开其根结点和其右子树的连接,得到多棵无右子树的二叉树。
2.把每个二叉树中的所有右支中的各结点依次断开连接并连接到支的父结点;最终得到多棵只根其结点多枝,其它结点都单枝的树。

树的遍历

树的先序遍历,与其对应的二叉树的先序遍历,结果相同。
树的中序遍历,与其对应的二叉树的中序遍历,结果相同。

树存储结构:孩子链表表示法、孩子兄弟链表表示法、双亲表示法。

按层遍历孩子兄弟链表结点,采用队列辅助,在访问某个结点后,立即把它的孩子和兄弟都加入队列。
1.根结点入队列
2.判断队列不为空时,出列一个元素,并访问这个元素的数据
3.将上一步访问的元素的孩子及其兄弟、兄弟的兄弟…,入队列。
4.循环步骤2、3。

哈夫曼(Huffman)树

树的应用之一是可以描述分类过程,按标准将数据划分为不同的种类。

判定树:描述分类过程的二叉树。分类问题中的因素有总数N,某个类别的属性有名称、条件、占比(权重)。二叉树中分叉结点表示判断条件,叶子结点表示值。判断树中的问题在于,同一个分类问题有不同的分类算法,会产生不同的判定树。它们从表面上看有纵深形状或水平形状,那么它们的总加权遍历查找的计算量也不同。则判定树中要研究的课题是要使平均比较次数计算量最小,使权重大的类别的比较次数尽量少。

哈夫曼算法和哈夫曼树,是从序列生成树的过程:
1.给定一组类别,{p1,p2,…,pk},其初始对应为单根树的森林{T1,T2…Tk}。
2.从森林中选两个根结点权(即占比)最小的树合并,它们分别为新树的左右子树,整齐起见可以按左小右大排列,新树的根结点权为左右子结点权之和。
3.直到森林中只剩一棵最小带权路径长度的二叉树,即哈夫曼树。
哈夫曼树也是满二叉树,其中共有2n0-1个结点,n0个叶结点是初始森林中的结点数。
WPL(Weight Path Length Of Node 带权路径长度)= 权与比较次数的乘积之和。

哈夫曼树的树形不一定唯一,但其WPL值最小且相等
哈夫曼字符编码不一定唯一,但总码长最短
哈夫曼树没有严格要求区别左右子树权重次序

哈夫曼编码:
在通信领域,希望字符在传输中总编码长度最短。
给出所有不同的字符,根据其出现次数比重构造哈夫曼树,然后将每个结点的左分支路径标记为0,右分支路径标记为1,每个叶结点都有一个从根结点开始的唯一的0、1序列,这个序列即是这个字符的编码,即哈夫曼编码。

下端物联网架构

物联网(Internet Of Things)

GPRS模块与云端通信,
GPRS模块通过串口与zigbee模块通信,
zigbee模块通过有线与传感器模块通信,或者zigbee主模块与多个zigbee从模块通信,zigbee从模块再通过有线与传感器通信。

zigbee具有自组网功能,从模块之间也可以通信。

2538 zigbee。
2540 蓝牙

485接口

物联网云平台:
百度云开工
机智云
选型的因素包括:有的系统只能在局域网内部使用。

机智云等使用缺点:
费用,
数据不能自己保存,第三方存储也不安全,
不能灵活定制。

Qsc厂家的数字音频处理器
给录播编码器配置信号源;

继承SchedulingConfigurer类并重写其方法,实现并行任务