服务端消息框架

消息规范

JMS:Java Message Service,Java消息服务,是基于JVM消息代理的规范。
AMQP:Advanced Message Queuing Protocol,高级消息队列协议,也是一个消息代理的规范,它不仅兼容JMS,还支持跨语言和平台。2004年,摩根大通和iMatrix开始着手AMQP开放标准的开发。2006年,AMQP规范发布。2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0 发布。RabbitMQ采用Erlang语言开发。
AMQP与JMS不同,JMS定义了一个API和一组行为,而AMQP是一个线路级协议。线路级协议描述的是通过网络发送的数据传输格式,任何符合该数据格式的消息发送和接收工具都能互相兼容和进行操作,这样能实现跨技术平台的架构方案。
MQTT:物联网(Internet of Things,IoT)机器之间(Machine-to-Machine,M2M)的大规模沟通中使用传统的HTTP请求/回答(Request/Response)模式不再合适,取而代之的是发布/订阅(Publish/Subscribe)模式。这就是轻量级、可扩展的MQTT,即Message Queuing Telemetry Transport,消息队列遥测传输,是IBM开发的一个即时信息传输通讯协议,是一个客户端服务端架构的发布/订阅模式的基于TCP/IP的基于二进制的消息传输协议。在物联网开发中,MQTT不是唯一的选择,与MQTT互相竞争的协议有XMPP和CoAP协议等,MQTT如今已经成为OASIS规范。MQTT规范很简单,非常适合需要低功耗和网络带宽有限的IoT场景。
TCP/IP参考模型可以分为四层:应用层、传输层、网络层、链路层。TCP和UDP位于传输层,应用层常见的协议有HTTP、FTP、SSH等。MQTT协议运行于TCP之上,属于应用层协议,因此只要是支持TCP/IP协议栈的地方,都可以使用MQTT。

异步消息

异步消息中有两个很重要的概念,即消息代理(message broker)和目的地(destination),消息发送者发送消息之后,消息将由消息代理接管,再由消息代理负责保证消息传递到指定目的地。
目的地形式有两种:队列(queue)和主题(topic)。队列用于点对点(point-to-point)形式的消息通信,主题用于发布订阅式(publish/subscribe)的消息通信。队列中的消息一次取出即逝,主题形式的消息可以做到多次使用。

消息框架

ActiveMQ: Apache出品,是最流行的,能力强劲的开源消息总线,是一个队列项目,支持MQTT、AMQP等协议。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经很久了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

kafka同RabbitMQ,ActiveMQ等是分布式消息队列,或者叫分布式消息中间件,或者叫做一种MQ产品(Message Queue)。kafka不支持MQTT协议。

事件驱动框架

事件驱动框架的优势是耦合度很低、系统扩展性好,而且生产者无需关心消费者。事件驱动框架可理解为观察者模式的升级,而观察者模式是固定调用关系的解耦。

参考:
管中窥豹:一线工程师看MQTT,协议详解 http://blog.csdn.net/tangxiaoyin/article/details/76053348
MQTT-Node.js实现-Mosca简介
http://www.jianshu.com/p/8315acec4e6b
MQTT入门篇
https://zhuanlan.zhihu.com/p/20888181
物联网核心协议—消息推送技术演进
http://www.cnblogs.com/Free-Thinker/p/5559798.html
物联网MQTT协议分析和开源Mosquitto部署验证 mosquitto_sub -t topic_name
http://www.cnblogs.com/Free-Thinker/p/5559816.html
MQTT协议笔记之消息流
http://www.blogjava.net/yongboy/archive/2014/02/15/409893.html
MQTT协议通俗讲解
http://blog.csdn.net/u011216417/article/details/69666752

centos6.9下mosquitto搭建

1.下载libwebsockets和mosquitto
libwebsockets下载页面:https://github.com/warmcat/libwebsockets/releases
mosquitto下载页面:https://github.com/eclipse/mosquitto/releases
2.安装依赖
yum -y install gcc gcc-c++ openssl-devel c-ares-devel libuuid-devel wget cmake xmlto
3.增加websocket支持
cd /home
tar -zxvf libwebsockets-2.4.1.tar.gz
cd libwebsockets-2.4.1
mkdir bulid
cd bulid
cmake ..
make && make install
sudo ldconfig #If you’ve installed libwebsockets with make install then you probably just need to run sudo ldconfig to update the linker cache。
4.安装mosquitto
cd /home
tar -zxvf mosquitto-1.4.14.tar.gz
#添加websocket支持
修改config.mk文件以使后面编译的mosquitto文件支持websocket
cd mosquitto-1.4.14
找到mosquitto-1.4.14目录下的config.mk文件,把config.mk文件中的WITH_WEBSOCKETS:=no改为yes,如下:
# Build with websockets support on the broker.
WITH_WEBSOCKETS:=yes
#安装
make && make install
#如果安装过报错如下:
warning: failed to load external entity “/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl”
compilation error: file manpage.xsl line 3 element import
xsl:import : unable to load /usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl
compilation error: file mosquitto.8.xml line 4 element refentry
xsltParseStylesheetProcess : document is not a stylesheet
make[1]: *** [mosquitto.8] Error 5
make[1]: Leaving directory `/home/mosquitto-1.4.14/man’
make: *** [docs] Error 2
,则修改/home/mosquitto-1.4.14/man/manpage.xsl中

修改为:
重新执行:make && make install
#如果执行程序时找不到libwebsockets的库文件,执行下面的命令为库做一下符号连接:
ln -s /usr/local/lib/libwebsockets.so.6 /usr/lib64/libwebsockets.so.6
#其它操作
groupadd mosquitto
useradd -g mosquitto mosquitto
#创建mosquitto.conf、pwfile文件
cd /etc/mosquitto/
cp mosquitto.conf.example mosquitto.conf
cp pwfile.example pwfile
cp aclfile.example aclfile
#mosquitto.conf修改配置如下,注意去掉每行前面的tab空白:

	# =================================================================
	# General configuration
	# =================================================================
	# 服务进程的PID
	pid_file /var/run/mosquitto.pid
	# 服务端口号
	port 1883
	# websockets端口号
	listener 9090
	# 添加websockets协议支持
	protocol websockets
	# 最大连接数,-1表示不限制
	max_connections -1
	# 服务进程的系统用户
	user mosquitto

	# =================================================================
	# Security
	# =================================================================
	# 不允许匿名用户
	allow_anonymous false
	# 用户/密码文件,默认格式:username:password
	password_file /etc/mosquitto/pwfile
	# 配置用户访问控制
	acl_file /etc/mosquitto/aclfile

	# =================================================================
	#Persistence configuration
	# =================================================================
	# 消息自动保存的间隔时间:默认30分钟往磁盘写一次,0表示mosquitto关闭才写到磁盘中
	autosave_interval 1800
	# 消息自动保存功能的开关
	autosave_on_changes false
	# 持久化功能的开关
	persistence true
	# 持久化DB文件
	persistence_file mosquitto.db
	# 持久化DB文件目录
	persistence_location /usr/mosquitto/

	# =================================================================
	# Logging
	# =================================================================
	# 4种日志模式:stdout、stderr、syslog、topic
	# 日志路径:none 则表示不记日志,此配置可以提升些许性能
	log_dest file /usr/mosquitto/mosquitto.log
	# 选择日志的级别(可设置多项)
	log_type error
	# 是否记录客户端连接信息
	#connection_messages true
	# 是否记录日志时间
	#log_timestamp true

#创建用户及密码,此处用户名是hthl_pub
mosquitto_passwd -c /etc/mosquitto/pwfile hthl_pub
输入命令后,控制台会提示输入新建用户的密码,连续输入两次密码后,则会生成一个pwfile文件。
注意:mosquitto_passwd -c 每次都只会生成只包含一个用户的文件,如果想在passwd.conf中存放多个用户, 可以使用mosquitto_passwd -b 命令:
mosquitto_passwd -b [最终生成的password_file文件] [用户名] [密码]
mosquitto_passwd -b /etc/mosquitto/pwfile hthl_sub 123456
mosquitto_passwd -D 命令删除一个用户
mosquitto_passwd -D [最终生成的password_file文件] [用户名]
#aclfile修改配置如下:

	#This only affects clients with username "hthl_pub".
	user hthl_pub
	topic write hthl/#
	# This only affects clients with username "hthl_sub".
	user hthl_sub
	topic read hthl/#

#创建存储目录
mkdir /usr/mosquitto
chown -R mosquitto /usr/mosquitto

5.启动 mqtt
mosquitto -c /etc/mosquitto/mosquitto.conf -d
6.推送测试
mosquitto_pub -h 127.0.0.1 -t topic1 -u hthl_pub -P 123456 -m “你好,世界!”
7.卸载
cd /home/mosquitto-1.4.14
make uninstall
reboot

8.Docker build file for mosquitto

sudo docker run -p 1883:1883 --name mosquitto --restart always -d ansi/mosquitto

https://hub.docker.com/r/ansi/mosquitto/

参考
http://www.voidcn.com/article/p-fjphobex-brk.html
http://www.cnblogs.com/littleatp/p/4835879.html

命令行发布测试:
mosquitto_pub -h localhost -t topic1 -u username1 -P password1 -m “你好,世界!”
命令行订阅测试:
mosquitto_sub -t topic1 -u username1 -P password1

Maven

Maven是一个基于java平台的自动化构建工具(编译-测试-打包-部署->自动构建),也是项目管理工具。
Maven的设计核心是约定优于配置(convention over configuration),也称作按约定编程,是一种软件设计范式。

主流的项目构建工具有:Ant、Maven、Gradle等。
Apache Maven是一个软件项目管理工具,基于POM(项目对象模型)的概念,管理项目的依赖、编译、文档等信息。
使用Maven管理项目时,项目依赖的jar包不必存在于工程内,而是集中放置在用户目录中的.m2目录中。
Ant是命令式,Maven是声明式。Ant需要指明各种动作,以及执行这些动作的顺序。Maven则默认大家都知道有各种动作,都遵守一个良好的目录结构,一个通用的构建过程。因此使用Maven时我们只需要告诉Maven希望构建什么,不需要告诉它如何构建。因为Maven已经在构建生命周期、阶段和目标中定义好了。我们要做的就是编写声明式的pom.xml文件。
Gradle结合以上两个的优点,继承了Ant的灵活和Maven的生命周期管理,它被google作为了Android御用管理工具。它不用XML作为配置文件格式,采用了DSL格式,使得脚本更加简洁。Gradle引入了基于Groovy语言的DSL语法来代替XML配置,因此它的配置文件是一个Groovy文件。Gradle还把Maven的设计核心(Convention Over Configuration)发扬光大,而Gradle的配置即代码又超越了Maven.在Gradle中任何配置都可以作为代码被执行的,我们也可以随时使用已有的Ant脚本,Java类库,Groovy类库来辅助完成构建任务的编写。

Apache Maven最初用于替代Apache Ant。相比Ant的指令方式,Maven采用了不同方式对项目进行构建进行抽象,比如约定源码、资源、目标文件的位置。
Maven的约定目录结构:
I.main->执行项目,test->测试项目,两个目录下都有java和resources(java:java代码,resources:资源代码/配置代码)。
II.target:用于存放编译、打包后的输出文件。
III.pom.xml:项目对象模型。
域名反转.大项目名
子模块名
版本号

Maven中央仓库信息速查

http://mvnrepository.com/
http://maven.outofmemory.cn/

maven plugin中的概念

lifecycle:总任务,它是一系列的phase组成,它运行完后就得到了一个结果,中间的过程是phase完成的。
常见的lifecycle有 | clean | package ear | pageage jar | package war | site等等

phase:阶段任务,一个lifecycle可以包含任意个phase,phase的执行是按顺序的,一个phase至少绑定很一个goal,没有goal的phase是没有意义的。
常见的phase有package,install,deploy。

goal: 执行任务的最小单元,它可以绑定到任意个phase中,一个phase有一个或多个goal,goal也是按顺序执行的,一个phase被执行时,绑定到phase里的goal会按绑定的时间被顺序执行。

mojo: lifecycle与phase与goal都是概念,mojo才是做具体事情的,可以简单理解mojo为goal的实现类。

Maven的插件机制是完全依赖Maven的生命周期的,因此要先理解Maven生命周期。

Maven生命周期

Maven有三套生命周期,它们相互独立、负责软件工程的不同方面的工作。这三套生命周期分别是:

  • Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle 构建的核心部分,编译,测试,打包,部署等。
  • Site Lifecycle 生成项目报告,站点,发布站点。

它们是相互独立的,可以仅调用clean来清理工作目录,调用site来生成站点。也可以直接运行mvn clean install site运行全部三套生命周期。

每套生命周期都由一组阶段(Phase)组成,我们平时在命令行输入的命令总会对应于一个特定的阶段。
例如运行mvn clean,这个的clean是Clean生命周期的一个阶段。Clean生命周期一共包含了三个阶段:

  • pre-clean 执行一些需要在clean之前完成的工作
  • clean 移除所有上一次构建生成的文件
  • post-clean 执行一些需要在clean之后立刻完成的工作

mvn clean中的clean就是上面的clean阶段,在一个生命周期中运行某个阶段的时候,它之前的所有阶段都会被运行,即mvn clean等同于mvn pre-clean clean,mvn post-clean 等同于 pre-clean clean post-clean。这是Maven很重要的一个规则,可以简化命令行的输入。

打包

使用mvn package进行编译打包时,Maven会执行src/test/java中的JUnit测试用例,使用参数-DskipTests和-Dmaven.test.skip=true可以跳过测试,这两个参数的主要区别是:
-DskipTests,不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下。
-Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类。

安装jar到本地Maven库

把生成的Jar文件放入本地库,以让其他项目使用。 /.m2/repository目录是Maven本地库的默认位置。
在项目目录下执行: mvn install
成功后输出:
[INFO] Installing /Users/hycx/i_workspace/yirui/yirui-common/target/yirui-common-1.0-SNAPSHOT.jar to /Users/hycx/.m2/repository/com/yirui/yirui-common/1.0-SNAPSHOT/yirui-common-1.0-SNAPSHOT.jar
[INFO] Installing /Users/hycx/i_workspace/yirui/yirui-common/pom.xml to /Users/hycx/.m2/repository/com/yirui/yirui-common/1.0-SNAPSHOT/yirui-common-1.0-SNAPSHOT.pom
[INFO] BUILD SUCCESS

mvn deploy:另外还可以把生成的jar放到远程仓库,例如可以用Sonatype创建一个私有的服务存放私有的jar。

打包时加入本地库

spring boot工程中pom.xml内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<dependencies>
<!--local jar-->
<dependency>
<groupId>0</groupId>
<artifactId>0</artifactId>
<version>0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/CCP_REST_SMS_SDK_JAVA_v2.6.3r.jar</systemPath>
</dependency>
</dependencies>

<!--springboot-1.5.x对应的springcloud的版本需要使用Camden.SR6-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--指定includeSystemScope为true,打包本地库-->
<configuration><includeSystemScope>true</includeSystemScope></configuration>
</plugin>
</plugins>
</build>
</project>

添加源代码目录

<build>
    <plugins>
        <!-- add generated proto buffer classes into the package -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.8</version>
            <executions>
                <execution>
                    <id>add-source</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>${project.basedir}/../yirui-savenergy-common/src/main/java</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Maven中模块间的关系

3种关系:继承、依赖、聚合。
继承是指子项目继承了父项目的Pom。
依赖即导入组合。
聚合是指一个聚合工程(aggregator),它也是Maven Project,其pom文件中打包方式(packaging)为pom。并且它引入了新的元素:modules—module,用来包含了多个子模块,每个子模块也是一个Maven Project。其pom内容示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yirui.common</groupId>
    <artifactId>yirui-modules</artifactId>
    <version>1.0-SNAPSHOT</version><!--版本:聚合模块的版本和被聚合模块版本一致,如果被子模块继承,
这里就是唯一指定版本的地方-->
    <packaging>pom</packaging>
    <modules>
        <module>yirui-common</module>
        <module>yirui-common-database</module>
        <module>yirui-common-message</module>
        <module>yirui-common-security</module>
        <module>yirui-common-sms</module>
    </modules>

</project>

https://blog.csdn.net/wanghantong/article/details/36427411

在一些最佳实践中我们发现:一个POM可以既是聚合POM,又是父POM,这么做主要是为了方便。

pom文件配置

modelVersion: 表示pom文件的Maven版本。
dependency下scope:表示此类库在项目中的作用阶段范围,默认为compile,表示在编译和打包时都需要此类库。阶段分为编译、单元测试、打包、运行。scope 可选择项有compile、provided、runtime、test。
build:build下可以包含plugins,这些插件可以修改项目的构建方式。例如编译的java版本。

dependencyManagement与dependencies

dependencyManagement的特性:在dependencyManagement中配置的元素既不会给parent引入依赖,也不会给它的子模块引入依赖,仅仅是它的配置是可继承的。
dependencyManagement 元素用在父项目的POM文件中,用来统一模块间的依赖版本问题。子项目中可以引用一个依赖而不显示地指明版本号,Maven会沿着父子层次向上查找一个拥有dependencyManagement元素的项目,找到后使用在dependencyManagement元素中指定的版本号。
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。
父项目中的dependencies被子项目全部继承。如果依赖只在某个子项目中使用,则可以只在子项目的pom.xml中引入,防止父pom的过于臃肿。

类似地,dependencyManagement 元素是用来管理插件的。

配置settings.xml

在Maven中提供了一个settings.xml文件来定义Maven的全局环境信息。这个文件会存在于Maven的安装目录的conf子目录下面,或者是用户家目录的.m2子目录下面。
根标签settings标签中的元素:

  • servers 下面可以定义一系列的server子元素,表示连接远程服务器的验证方式。主要有username/password和privateKey/passphrase这两种方式。
    <servers>
    <server>
    <id>id</id>
    <username>用户名</username>
    <password>密码</password>
    </server>
    </servers>
    
  • mirrors 用于定义一系列的远程仓库的镜像。
    mirrors中可以配置多个mirror,maven的mirror是镜像,而不是“分库”,只有当前一个mirror无法连接的时候,才会去找后一个,类似于备份和容灾。多个mirror,maven会根据id的字母排序来指定第一个,所以不管怎么排列,一定会找到A这个mirror来进行查找,当A无法连接,出现意外的情况下,才会去B查询。id:是用来区别mirror的,所有的mirror不能有相同的id。
    mirrorOf:用来表示该mirror是关联的哪一个仓库,其值为其关联仓库的id。当要同时关联多个仓库时,这多个仓库之间可以用逗号隔开;当要关联所有的仓库时,可以使用“*”表示;当要关联除某一个仓库以外的其他所有仓库时,可以表示为“*,!repositoryId”;当要关联不是localhost或用file请求的仓库时,可以表示为“external:*”。
    url:表示该镜像的url。当Maven在建立系统的时候就会使用这个url来连接远程仓库。central是官网仓库的id,如果存在多个mirror,一定要把mirrorOf *(星号)的放到最下面。

maven仓库搜索顺序

build一个Maven项目的时候,Maven会检查pom.xml文件中项目的依赖,然后按以下顺序依次搜索依赖,直到找到:
1)搜索本地仓库
2)搜索中央仓库
http://repo1.maven.org/maven/是旧仓库,有时会从这里下载。
https://repo.maven.apache.org/maven2是新的仓库。
3)pom.xml里声明的私有远程仓库

关于maven配置文件setting.xml中的配置
https://blog.csdn.net/TheManOfCoding/article/details/78864965
https://blog.csdn.net/cwh056056/article/details/49646111

-source 1.5 中不支持方法引用

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Maven打包

在/tests下自定义settings.xml文件,然后启动docker容器:
docker run –name maven1 -v /tests:/root/.m2 -it maven /bin/bash
进入后在项目目录中运行 mvn package 打包。

https://hub.docker.com/r/library/maven/

常用Maven Plugin,插件介绍
https://www.cnblogs.com/crazy-fox/archive/2012/02/09/2343722.html

产品设计

商业计划书:BP

产品经理专业导读-李建忠

避免玩具项目

产品设计中的文档:
BRD:商业需求文档,制定方向,总监,VP来做,给决策人员,核心团队,VC看。制定战略,获取资源。
MRD:市场需求文档,制定产品,可能和BRD合并, 总监做,给市场研发运营职能部门看,研发看技术可行性,运营人员看资源调配。制定产品边界,建立共识。
PRD:产品需求文档,制定功能,给UI/UE开发看,产品经理做,制定功能细节。
ProtoType:线框图原型/高保真原型UI/UE:展现细节,产品经理或UI/UE实现,确定产品视觉和交互细节。

古董只能用来怀旧,不能用来使用。

微博早期只支持最多发一张图片。
要跟随产业规律,做早了死掉,做晚了没机会。
行业规律:去中心,自组织,碎片,快速。

书:
启示录-打造用户喜爱的产品
从0到1-开启商业与未来的秘密
精益创业-新创企业的成长思维
浪潮之巅-吴军著
失控-凯文凯利著
奇点临近-2045年,当计算机智能超过人类
人人时代-无组织的组织力量、
维基经济学-大规模协作如何改变一切。
定位-有史以来对美国营销影响最大的观念
创新者的窘境-就算我们把每件事情都做对了,仍有可能错失城池
免费-商业的未来
长尾理论
系统化思维导论
交互设计精髓
赢在用户-Web人物角色创建和应用实践指南
用户体验要互-以用户为中心的产品设计
设计心理学-日常的设计
Don’t make me think
重来-rework
人月神话
人件
消费者行为学
引爆点 Tipping Point
怪诞行为学
影响力
乔布斯传
facebook效应
腾讯传

要有产业基础,才不会人云亦云、飘忽不定。
iPhone4 2010年出现,微信2012,微软一些产品却按年出。

你的灯亮着吗?-发现问题的真正所在h1

axure

master 母版,在页面内选中一些控件,右键转为母版。母版可能只在项目内使用。
http://www.woshipm.com/rp/420885.html

APP原型实战
http://www.maiziedu.com/wiki/prototype/app/
https://www.axure.com.cn
http://www.mobileui.cn/add-some-animation-effects-for-prototype-design.html

做移动应用有什么好的原型工具?OmniGraffle
https://www.zhihu.com/question/19688700

justinmind

justinmind学习站
http://www.jmstu.com/
justinmind中文网
http://www.jmfans.com/
名词对照:
master 母版
widget 部件
数据母版即数据库
母版即一个通用的模板

原型设计到底是用Justinmind还是Axure?

原型设计到底是用Justinmind还是Axure?

Axure学习笔记:手机APP微信读书原型设计

Axure学习笔记:手机APP微信读书原型设计

移动APP:2015 UI/UX 趋势,Material design布局未来!
https://www.iamue.com/7797
https://www.zhihu.com/question/24874514

在开始设计原型之前我们需要做的第一步是选择合适的设计分辨率,目前使用Axure设计移动端原型时普遍采用的是(宽)375px*(高)667px和(宽)414px*(高)736px两种分辨率尺寸,这两种尺寸分别是由目前主流的移动设备Iphone7和Iphone7 PLUS的屏幕分辨率尺寸等比缩放而定义出来的,同时也是Iphone7和Iphone7 PLUS的逻辑分辨率。

有朋友可能会疑惑在设计原型的时候为什么不直接采用移动设备实际的分辨率呢?因为这主要考虑到设计时的便携性,毕竟我们输出的原型主要是用于演示而不是视觉稿,所以不需要达到那么高的精度,另外如果按移动设备实际的分辨率进行设计,在对元件进行编辑和排版的时候会是一件很耗费时间的事情,同时也不方便在电脑浏览器上进行查看。

本人在进行原型设计的时候一般用的是375px*667px这个分辨率尺寸,因为Axure常用的元件默认的字号一般是14px或18px,这两种字号也刚好匹配Iphone7上常用字号的比例,而且这个分辨率尺寸在电脑浏览器上刚好一屏就可以显示完整。

http://www.woshipm.com/rp/692285.html?utm_source=itdadao&utm_medium=referral

阿里图标库 http://www.iconfont.cn/
web主题 http://www.weidea.net/

推荐:5款最好用的AngularJS程序构建框架
http://www.cocoachina.com/webapp/20150930/13625.html

16个良好的 Bootstrap Angularjs 管理后台主题
http://www.open-open.com/news/view/a364b

原型工具只使用 axure 即可,它可能是免费和最灵活强大的。
mind工具可以使用 MindMaster、XMind。
流程图工具有 ProcessOn。
计划进度工具 GanttProject
 

效果图截图留存

Javascript

创建对象

1.new 构造函数形式
2.Object.create形式

定义类继承

有原型链法、属性复制法和构造器应用法等。

作用域
大多数语言里边都是块作作用域,以{}进行限定。而js里边是函数作用域,一个变量在函数内前后都有效,例如变量p1在函数最后一行定义,在第一行也有效,但是其值是undefined。
全局变量若在函数内被重定义,则在函数内外的变量互不影响。
https://blog.csdn.net/dome_/article/details/79205210

apply、call和bind
三者都可以把一个函数应用到其他对象上。apply、call是直接执行函数调用,bind是绑定,执行需要再次调用。apply和call的区别是apply接受数组作为参数,而call是接受逗号分隔的无限多个参数列表。

    function Person() {
    }
    Person.prototype.sayName() { alert(this.name); }
    var obj = {name: 'michaelqin'}; // 这是另一个普通对象,它不是Person的实例。

    1) apply
    Person.prototype.sayName.apply(obj, [param1, param2, param3]);
    2) call
    Person.prototype.sayName.call(obj, param1, param2, param3);
    3) bind
    var sn = Person.prototype.sayName.bind(obj);    
    sn([param1, param2, param3]); // bind需要先绑定,再执行 
    sn(param1, param2, param3); // bind需要先绑定,再执行

caller、callee和arguments
caller、callee是调用与被调用的关系,就像是employer和employee(雇主和雇员)之间的关系。二者返回的都是函数对象引用。arguments是函数的所有参数列表,是一个类数组的变量。

    function parent(param1, param2, param3) {
        child(param1, param2, param3);
    }

    function child() {
        console.log(arguments); // { '0': 'mqin1', '1': 'mqin2', '2': 'mqin3' }
        console.log(arguments.callee); // [Function: child]
        console.log(child.caller); // [Function: parent]
    }

    parent('mqin1', 'mqin2', 'mqin3');

闭包
所有函数都是闭包.通俗的说闭包就是作用域范围,因为js是函数作用域,所以函数就是闭包。闭包的应用是在内嵌函数,这涉及到内嵌作用域,或者叫作用域链。内嵌就是父子引用关系(父函数包含子函数,子函数因为函数作用域又引用父函数,所以叫闭包),这就会带来另外一个问题,什么时候引用结束?如果不结束,就会一直占用内存引起内存泄漏。不用的时候把引用设为空,死结就解开了。

Object的方法
Object.defineProperty(obj, prop, descriptor)用来给对象定义属性,有value,writable,configurable,enumerable,set/get等。
hasOwnProerty用于检查某一属性是不是存在于对象本身,继承自的父亲的属性不算。
isEnumerable用来检测某一属性是否可遍历,也就是能不能用for..in循环来取到。

常用设计模式在js中的实现思路,利用eval等方法。

判断对象类型

#判断是Buffer
Object.prototype.toString.call(obj1) === '[object Uint8Array]'
#判断是Array
Object.prototype.toString.call(obj1) === '[object Array]'

JS判断字符串结尾

  String.prototype.endWith=function(endStr){
      var diff=this.length-endStr.length;
      return (diff>=0 && this.lastIndexOf(endStr)==diff)
  }

ES6中export及export default的区别:
但在一个文件或模块中,export、import可以有多个,export default仅有一个。
对于export default,导入的时候没有花括号;对于export,导入的时候有花括号;
http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632

遍历对象

for (var key in obj){
      var value=obj[key];
    }

触发其它元素的点击

//IE浏览器
if(document.all) {
document.getElementById("clickme").click();
}
//其它浏览器
else {
var e = document.createEvent("MouseEvents");
e.initEvent("click", true, true);
document.getElementById("clickme").dispatchEvent(e);
}

MDN : Mozilla 开发者网络学习平台
https://developer.mozilla.org

slice与splice的区别
slice() 选取数组的的一部分,并返回一个新数组。
splice() 从数组中添加或删除元素。

数组

#插入元素 array.splice(pos, length, object);
#插入元素到数组头
array.splice(0, 0, “three”);
清空数组
array.length=0;
克隆数组
var clone = myArray.slice(0);

日期时间

var datetimeMonthAgo=new Date(new Date().getTime()-30*24*60*60*1000).toISOString();

合并对象

Object.assign(target, …sources),返回target。

正则

var reg = /url=\”(.*?)\”/g;
var arr = str.match(reg);//得到整个reg匹配的内容
var arr = reg.exec(data.value);//得到reg匹配的内容和子内容
str=arr[1].replace(/&/g,””);//使用正则做全部替换

Post提交方式下载文件
https://blog.fedepot.com/postti-jiao-fang-shi-xia-zai-wen-jian/

Vue

Vue学习要点记录:

Vue 实例暴露了一些有用的实例属性与方法,这些属性与方法都有前缀$,与代理的 data 属性区分。
Vue.js 没有“控制器”的概念。组件的自定义逻辑可以分布在这些钩子中。
钩子:create, mounted、 updated 、destroyed等。
在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时, Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。如果熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,也可以不用模板,直接写渲染(render)函数,使用可选的 JSX 语法。
Mustache语法,胡子语法:{{}}
v-bind:指令可以省略为一个冒号
v-click指令可以省略为一个@
模板内的表达式只能包含单个表达式,应只用于简单的运算。
计算属性:在computed中声明并实现属性值的计算方法。与methods的区别是:计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
大括号有时显示在界面上的原因,是因为框架未加载完成,使用v-text可以避免这个问题。

& 父级作用域: 传递进来的参数必须是父级的函数方法, 然后在指令中,通过 test() 获取到 传递进来的函数,这个还不够,还必须再执行一次 test()() 才是真正的执行这个方法。
@ 本地作用域: 只能传递字符串进来,对于方法或者对象是传递不进来的。
= 双向属性: 可以传递对象进来,也可以是字符串,但是不能传递方法。 同时可以在指令中修改这个对象,父级里面的这个对象也会跟着修改的。

手摸手,带你用vue撸后台 系列一(基础篇)
https://segmentfault.com/a/1190000009275424#articleHeader16

vuejs 和 element-ui 搭建的一个后台管理界面

# install dependencies
npm install

# serve with hot reload at localhost:8081
npm run dev

# build for production with minification
npm run build

http://www.cnblogs.com/taylorchen/p/6083099.html

vue-element-admin
vue-element-admin技术栈基于 ES2015+、vue、vuex、vue-router 和 element-ui,提前了解和学习这些知识会对使用本项目有很大的帮助,是一个企业级中后台前端的集成方案,不适合当基础模板来进行二次开发。若使用模板建议使用另一个 vueAdmin-template。可以把 vue-element-admin当做工具箱或者集成方案仓库,在 vueAdmin-template 的基础上开发,要什么就去 vue-element-admin 那里复制过来。
https://panjiachen.github.io/vue-element-admin-site/#/zh-cn/README

ES6:

ES6提供的许多新特性。这些新特性中包含一些简便书写的方法:
箭头函数
默认参数
不定参数
解构赋值
模板字条串

ECMAScript 6 入门
http://es6.ruanyifeng.com/

vue 常用组件库
http://blog.csdn.net/zhouzhiwengang/article/details/72621219

Mint UI 基于 Vue.js 的移动端组件库
http://mint-ui.github.io/#!/zh-cn

Vue-strap, Bootstrap components built with Vue.js.
https://github.com/yuche/vue-strap
http://yuche.github.io/vue-strap/#modal

vue相关错误

执行npm run dev报错:
events.js:160 Error: listen EADDRINUSE :::8030
原因可能是端口被上一次启动占用

执行npm run dev报错:
Vue packages version mismatch:
原因是vue 和 vue-template-compiler版本不对应,执行 npm update vue-template-compiler

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
http://www.kancloud.cn/yunye/axios/234845

Vue ElementUI 使用 Starter Kit 项目模板
http://element-cn.eleme.io/#/zh-CN/component/quickstart
https://github.com/ElementUI/element-starter

Java基础

命令行运行java

jar包都放在lib文件夹里

java -Djava.ext.dirs=lib Main

ubuntu 安装jdk

JDK是java的开发环境,它包括了运行环境(jre)和开发中需要的编译、调试、程序诊断。
很多软件已不需要通过环境变量JAVA_HOME来找到java的运行环境。
http://www.cnblogs.com/a2211009/p/4265225.html

jre是提供java运行环境而不是开发环境
OpenJDK 和 Sun JDK 的关系

sudo apt-get install openjdk-8-jdk

Centos安装OpenJDK

#yum搜索OpenJDK8软件包 
yum search java-1.8.0|grep openjdk 
#安装java-1.8.0-openjdk.i686
yum install java-1.8.0-openjdk.x86_64 -y 

Map和List的简单构建方式

new HashMap(){{
            put("saleState",saleState);
            put("serveType",serveType);
        }}

new ArrayList<List>(){{
add(masterSocketDeviceIds);
add(dimmingLightDeviceIds);

Array转List
List list= Arrays.asList(strArr);
}};

Java没有范型数组

枚举

ordinal()返回的值是索引,value()返回的是给枚举变量赋予的值。

public enum EnumDeviceType {
    Unknow(0),
    MasterSocket(1),
    SlaveSocket(2),
    DoorbellController(42),
    PowerControl(43);

    private int value = 0;

    private EnumDeviceType(int value) {
        this.value = value;
    }

    public int value() {
        return value;
    }
}

byte

char与byte:
byte是8位的一个字节,char是UNICOEDE字符,是16位的整数;

java中的byte、int等都是有符号的,取byte的无符号数只要进行&0xff操作即可:

public static int[] toUbytes(byte[] bytes){
        int[] ints=new int[bytes.length];
        for(int i=0;i<bytes.length;i++){
            ints[i] = bytes[i] & 0xff;
        }
        return ints;
    }

public static String bytes2HexString(byte[] bytes) {
        String ret="";
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret+=hex;
        }

        return ret.toUpperCase();
    }

Java字段反射+POI示例:
http://blog.csdn.net/panpan96/article/details/76566475

Base64

BASE64Encoder/BASE64Decoder类在sun.misc包中,是sun公司的内部方法,以后有删除的潜在可能,
Base64类在java.util包中,推荐使用Base64.getEncoder()。

split

String[] subs=str.split(“,”,-1);//limit -1 不忽略两端的分隔符。

java -jar 命令行传参并获取的方法

方式一:
java -jar xxx.jar aaa bbb cccc,传了3个参数,通过main方法的参数获取。
方式二:
java -jar xxx.jar -Da1=aaa -Db1=bbb -Dc1=ccc,通过System.getProperty(“aaa”,”1″); 方式获取。作为环境变量。
方式三:
java -jar xxx.jar –a1=aaa –b1=bbb,springboot的写法,可以通过@Value(“${a1}”)获取。
注意参数的位置以及中划线符号的数目:
jar、Dspring.profiles.active前面是一个中划线,db.url等自定义参数前面是2个中划线。
-Dspring.profiles.active位于-jar之前,–db.url参数位于.jar之后。

java -Dspring.profiles.active=dev -jar yirui_clock_storage-1.0.jar --db.url=localhost --db.port=14000 --db.username=数据库用户名 --db.password=数据库密码

spring.profiles.active运行时指定方式

mvn命令运行:mvn spring-boot:run -Drun.profiles=test
命令行运行jar文件: java -jar -Dspring.profiles.active=test xxx.jar

Java对象的地址

对象的hashcode是否是它的地址,这取决于具体的实现,一般来说,它常常是对象的初始地址的整数表示,但是这种实现技术并不是Java编程语言所规定的。在GC后,对象的地址可能会变动,不同的JVM实现也有差异。

java知识网站

http://www.java1234.com

Java的参数传递都是值传递

传值分为值内容值和地址值,传地址值可以认为是传引用。
值传递:方法调用时,实际参数把它的值的副本传递给对应的形式参数。特点:此时内存中存在两个相等的基本类型,即实际参数和形式参数,后面方法中的操作都是对形参这个值的修改,不影响实际参数的值。
引用传递:方法调用时,实际参数的地址的副本被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址。在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到原始对象。但对引用的赋值不会影响原始对象。
基本类型:传递的是值的拷贝,也就是说传递后就互不相关了,也就是说,不过副函数的副本如何变化,主本永远不会被影响。
引用类型:传递的是引用地址值,有可能会被影响。
String:具有不可变。是特殊的引用类型,其作用跟基本类型一样,传递后不相关。

String

andyweike博客之String

浏览器

插件架构:NPAPI和PPAPI

NPAPI是当今最流行的插件架构,由网景开发,后Mozilla维护,几乎所有浏览器都支持,不过存在很大的安全隐患,插件可以窃取系统底层权限,发起恶意攻击。
2010年,Google在原有网景NPAPI(Netscape Plugin API)基础上开发了新的PPAPI(Pepper Plugin API),将外挂插件全部放到沙盒里运行。最新版本的firefox和chrome都不支持大多数NPAPI插件了。

播放rtmp

HTML5不支持rtmp,由flash插件来支持播放。
下载Adobe Flash Player,对不同的浏览器提供了支持不同类型API的插件版本。
http://get.adobe.com/cn/flashplayer/otherversions/
在Windows上,vlc安装过程中可以看到只提供了Mozilla和ActivX插件勾选。
在Ubuntu上,下载flash_player_npapi_linux.x86_64.tar.gz解压后,拷贝后重启firefox。

sudo cp libflashplayer.so /usr/lib/firefox-addons/plugins/libflashplayer.so

rtsp协议流数据在前端播放,没有特别好的解决方法,需要在本机装一个vlc 插件,依靠这个插件才能让 RTSP 协议 在网页上能播放,但是目前高版本的 Chrome浏览器已不支持 NPAPI 插件,也就是说高版本的 Chrome 浏览器还是不能播放(46 以上的版本都不行)。
对于rtsp,由于新版本的ff、chrome都不支持vlc插件,所以暂只能考虑使用旧版本。
http://www.cnblogs.com/qiaojie/p/5733335.html

Firefox 52.0 分支作为长期支持版本,将会持续到 2018 年三四月份,从该版本起,Firefox 将不再支持除了 Flash 插件之外的所有 NPAPI 插件。
Chrome uses PPAPI-based plugins ONLY now, while vlc-browser-plugin is NPAPI-based

Linux版本的chrome在版本35时已经没有enable-npapi选项了。
Since version 35 NPAPI is no longer supported in Linux versions of Chrome and Chromium. In the Windows versions you can still enable it on the page: chrome://flags/#enable-npapi.

播放rtsp

在angular或vue等框架中使用vcl插件播放rtsp视频时,可以js动态操作vlc播放,如果使用双括号表达式给mrl赋值,可能在firefox中产生每次进入视频页面都需要重新激活插件。

<object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc1' events='false' width="720" height="410">
  <param name='mrl' value='rtsp://u.itvitv.com/jpm1' />
  <param name='volume' value='0' />
  <param name='autoplay' value='true' />
  <param name='loop' value='false' />
  <param name='fullscreen' value='true' />
  <param name='controls' value='false' />
</object>
var vlc=document.getElementById("vlc1");
var id=vlc.playlist.add($scope.videoUrl);
vlc.playlist.playItem(id);

当测试接口地址单独访问时返回数据正常,而在站点中总是访问不正常时,要深度清除缓存,24小时及以上。

OPC

OPC是什么?
http://opcfoundation.cn/about/what-is-opc/index.aspx
http://blog.csdn.net/u013120247/article/details/50163147

HowToStartWithUtgard
https://openscada.atlassian.net/wiki/display/OP/HowToStartWithUtgard

控制系统经常用到的是DCS和PLC
目前常用的无线网络标准最流行的3个是ZigBee、Bluetooth和WiFi。

OPC client examples include utgard and jeasyopc
https://github.com/luoyan35714/OPC_Client

也可以不使用AccessBase方式,使用for循环轮询查看item的数值。
http://tonynju.iteye.com/blog/289929

模拟器
http://www.matrikonopc.cn/products/opc-drivers/opc-simulation-server.aspx
http://www.hifreud.com/2014/12/27/opc-1-install-MatrikonOPC-Server-for-Simulation-and-Test/
http://www.hifreud.com/2014/12/27/opc-2-what-is-opc/
http://www.hifreud.com/2014/12/27/opc-3-main-feature-in-opc/
http://www.hifreud.com/2014/12/27/opc-4-client-invoke-use-utgard/
http://www.hifreud.com/2014/12/27/opc-5-client-invode-use-JeasyOPC/

APP开发架构

NativeApp
跨平台解决方案:
WebApp
dist是指distribution,发布,
dest则是destination,目的。
facebook-reactnative

PhoneGap/Cordova

使用iOS、Android等原生的WebView控件,用浏览器,基本上不能混合开发
Phonegap在每个移动平台(iOS、android、blackberry等)中都实现了一套后台框架,分别与各平台系统API进行交互,从而调用其native API,对应用开发人员提供了统一的JS调用接口,即phonegap API,开发人员只需要采用html、js、css等web技术即可进行移动平台快速开发。
Phonegap的“一次编写,到处运行”是指应用程序开发只需编写前端代码,并且可完全复用到其他平台,复用到其他平台时需要另外搭建相应的开发环境才能运行。

android平台phonegap框架实现原理
http://blog.csdn.net/wuruixn/article/details/7405175

ionic

Ionic 底层打包使用 Cordova ( 和 Phonegap 一样 ) 底层打包用 Cordova 是不错的。 Ionic 是一个全堆栈的混合应用开发框架,可以理解成 Ionic = Cordova + AngularJS + Ionic UI

ionic app 优化三件套,让其更贴近原生app:
禁用ionic 自带的滚动效果
在低版本android中,Crosswalk WebView提供了比原生WebView更好的性能;但是相应的会使app体积大20m左右,这就是其唯一的缺点,但是为了性能,这点问题当然不是问题啦;
引入插件 ionic-native-transitions,这是我个人觉得对app体验最最重要的一步。这能使app的页面切换效果 “纵享丝滑”,告别ionic自带的页面切换卡顿效果!
需要调用支付,蓝牙什么的功能务必用 ionic,因为有 phonegap,后期可以给你省很多事
如果你只是做纯粹展示型的 app 那么 weex 和 rn 都可以,如果 react 熟就 rn,不熟怕麻烦还是 weex

ionic3 教程
http://www.jianshu.com/p/1baf40713c1c

weex / react native / ionic 技术选型
http://www.sunzhongwei.com/weex-react-native-ionic-technology-selection

Bower

Bower 是 twitter 推出的一款包管理工具,基于nodejs的模块化思想,通过 Bower 来管理模块间的联系。
“包”是指一系列有意义的资源的集合,在bower这里,更多体现在json文件,它是这些资源的配置文件,一个完整的包都应该有一个bower.json文件。
“管理”包含获取,下载,安装,更新,查找,注册等等一系列对资源的操作。

bower与npm
npm是专门管理node模块的管理工具,而bower是node的模块,因为bower是依赖node,npm和git。npm擅长的是管理node模块,而bower管理的范围更大,涉及html,css,js和图片等媒体资源。常在服务器端使用npm,而在客户端使用bower。

gulpjs

gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速度更快。

$ sudo npm install gulp -g 
$ gulp 
Local gulp not found in 
Try running: npm install gulp 
如果报上面二行错误,在工程目录下执行下面的命令:
npm link gulp 

如果gulp出现gulp Error: Cannot find module ‘object.defaults’等错误,先执行bower install,再npm cache clear、remove node_modules、npm install。

JSHint、JSCS、ESLint、JSLint
JSHint 可以帮助检测 JavaScript 代码中的错误和潜在的问题
JSCS 是一个 JavaScript 的代码风格检查工具,通过使用这两款 QA Tools 能在团队协作中大大提升代码的正确性、准确性、完整性、简洁性、统一性及易读性。

Framework7

Framework7 是一个开源免费的框架可以用来开发混合移动应用(原生和HTML混合)或者开发 iOS & Android 风格的WEB APP。也可以用来作为原型开发工具,可以迅速创建一个应用的原型。