2017 QCON全球软件开发大会 北京·国家会议中心 04.16~04.18

地址及日程如下

第一天

主题演讲 大会堂A

微服务与实时处理架构演进(厂商共建) 306B

Google、Uber 的分布式系统设计 311A

互联网新挑战 甲骨文黑科技(厂商专场) 306B

人工智能与深度学习 311A

快速进化的容器生态 309B

新一代 APM 技术(厂商专场) 306A

第二天

主题演讲 大会堂A

推荐系统架构演进 307A

业务架构那些事 310

第三天

容器应用与工程效率提升(厂商共建) 大会堂A

网络信息安全建设最佳实践 307A

大规模分布式系统架构与实践 310

17:10 演讲结束

附:

2017上海QCON日程链接

DIP

依赖倒置,是一种依赖原则:

a.高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
b.抽象不应该依赖于细节,细节应该依赖于抽象。

IoC

控制反转,是一种实现DIP的设计思想

IoC也体现了好莱坞原则

The Hollywood principle

don‘t call us, we‘ll call you

IoC容器既是”好莱坞”

DI

依赖注入,是一种IoC的基本实现手段(除DI外还有DL(依赖查找)、DP(依赖拖拽)等)

Spring IoC容器

Spring IoC容器其实就是一个应用程序的上下文,根据官方文档

org.springframework.beansorg.sprinframework.context包是Spring框架的基础IoC容器。BeanFactory接口提供了高级的配置机制来管理任意对象。ApplicationContextBeanFactory的一个子接口,它增加了更易于集成的Spring AOP特性;消息资源处理(用于国际化),事件发布以及特定的应用层上下文,例如,用于Web应用的WebApplicationContext

在Spring Web应用中, 我们常用到两种IoC容器,它们以不同的配置初始化。一个是Application Context,另一个是Web Application Context

ApplicationContext

接口org.springframework.context.ApplicationContext提供了一个Spring IoC容器,它代表了beans可靠的实例化、配置化以及组件化。 容器通过读取配置元数据(xml或annotation或Java Code)来实例化、配置或组装对象。

Application Context这个容器,由定义在web.xml中的ContextLoaderListenerContextLoaderServlet初始化,其配置一般如下

1
2
3
4
5
6
7
8
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:*-context.xml</param-value>
</context-param>

上面的配置中,我们让spring去加载所有classpath中的-context.xml结尾的文件并且用它们创建了一个应用程序上下文. 这些文件常常包含的是一些在应用中将被用到的中间层事务服务、数据访问或其它对象。基于这个配置,对于每个应用都会有这样一个应用程序上下文。

WebApplicationContext

在Spring MVC框架中,每个DispatcherServlet有它自己的WebApplicationContext,它继承了所有已经定义在根WebApplicationContext中的beans。那些继承的beans可以在具体的servlet作用域中被重载,而且在这个Servlet实例中你可以定义一些有特定作用域的beans

WebApplicationContext是一个应用程序上下文的子上下文。每个在Spring Web应用中定义的DispatcherServlet都有一个关联的WebApplicationContext,其一般配置如下

1
2
3
4
5
6
7
8
9
<servlet>
<servlet-name>platform-services</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:platform-services-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

你需要提供spring配置文件(xml)的名字作为servlet的初始化参数。值得注意的是,这个xml的名字必须是*-servlet.xml的格式。拿上面的配置为例来说,servlet的名字为platform-services,因此xml的名字必须为platform-service-servlet.xml。不论ApplicationContext中定义的beans是否可用,它们都将被每个WebApplicationContext所引用。最佳实践是,保持一个清晰的分层,中间层服务作为业务逻辑组件,而数据访问层(通畅定义在ApplicationContext)和web相关组件作为控制器和视图解析器(通常定义在每个Dispatcher Servlet的WebApplicationContext中)

参考: understand Spring MVC’s ApplicationContext hierarchy and basic components and lifecycles in a servlet container and application initialization

Spring DI(依赖注入)

依赖注入的对象是bean,也就是各种java对象

被注入Bean的作用域

Spring中使用scope属性来声明bean的作用域

1
<bean class="com.company.class" scope="singleton" />

scope取值如下

作用域 描述
singleton 在每个Spring IoC容器中一个bean定义对应一个对象实例,即单例。如果没有显示声明scope属性,则默认scope为singleton。
prototype 一个bean定义对应多个对象实例。
request 在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例, 它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。
session 在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global session 在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。

集中注入

对于1控制层、2中间业务层、3数据访问层对象。往往是3注入2,2注入1,如果系统或业务庞杂,那么注入配置会很臃肿,注入关系不清晰,如果你的不是按3->2->1这样注入,那可能情况会更糟糕。

控制层、中间业务层、数据访问层的对象往往都是以singleton的形式存在于我们的系统,基于这一点,我们可以对一个类注入同一层中所有的对象,这个类本身再以__singleton__初始化到IoC容器中,哪里需要则注入就可以了。

这里只有典型的三层的对象, 如果有更复杂的分层分块对象需要注入,则更需要集中管理注入。

循环注入

Circular dependencies

If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws aBeanCurrentlyInCreationException.

One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario).

link

最近读了张鹤的《从零开始学理财》。张鹤是著名的财经作家和理财专家,撰写过《成功理财的16堂课》《银行投资理财赚钱法》等理财类的畅销书。

书中介绍了理财的基本概念、常见的误区和实用的理财技巧。其中的__水库模型__和__资产4321分配法__让理财新手能够快速上手理财。

一、理财的基本概念

理财是一个系统的工程,它由__收入__、__消费__、__储蓄__、__投资__、__负债__和__保险__6部分构成

二、水库模型

书中用一个基本的理财模型:水库,形象的描述了理财6个构成部分之间的关系。

想象自己有一个水库,你每个月都要朝水库里灌水,这就是__收入__。水库的一侧还有一个大坝,衣食住行都会让水从大坝往外流,是你的__消费__。水库里的存水是你的__储蓄__,水库旁边还有一口井,可以慢慢向你的水库里注水,这就是你的__投资__。如果水库干了,向别人借水,这个是__负债__,还水的时候要多给一些,就是__利息__。为了防止意外发生得稳固大坝,就需要__保险__。

三、最低目标:财务自由

合理的分配6个部分的比例,构建牢固的“水库”。最终我们可以达到最低目标:__财务自由__。

所谓财务自由是指: 理财的被动收入高于最低消费的财富自由状态

之所以把财务自由作为最低目标是我个人观点,因为只有财务自由了,才可以不用靠出卖劳动力去获得生活成本,才算是脱离了生存压力,生活才有了选择权,是自由的,而自由的生活是我的最低目标。

四、误区

1. 没钱就不理财

没钱更要先建立理财观念,系统性地提高收入,节约开支,增加储蓄,持续投资,清理负债,设置保险。

可以先投资自己,把钱投入到提升自己的技能和素质提高上。关注投资界信息,交学费积累经验。给自己买一份保险,把防水的闸门修得牢固一些。

2. 钱是挣来的,不是攒出来的

攒钱有2个好处,一个是可以给你积累本金,能让你在看准机会的时候能出手。另一部分好处是能避免急功近利的心态。最成功的投资基本上都是长线投资。

3. 理财就是整天关注理财产品

时刻关注自己的理财产品会增加时间的[1]沉没成本。好的投资策略往往是盯着一个看好产品,然后长期持有,不要频繁更换。

个人认为时间本身就是最昂贵的资产,如果一项投资(学习、认知除外)需要占用你大量的时间,那便是不划算的。

五、四三二一资产分配法

书中提到了一种适用于理财新手的资产分配方法:4321资产分配法。它是基于恒定混合性策略,即保持[2]投资组合中各类资产的比例固定。

40% 投资

初期可选风险较小的债券、基金定投、黄金等。投资是零和博弈,有人赚就有人亏,风险高的投资一定要用闲钱。

e.g. 国债,蚂蚁聚宝下的基金定投,黄金,混合基金等

30% 消费

理财需要很强的自控力和克制消费的冲动。如果想持续地增长自己的财富,一定要控制消费,延迟欲望。给自己确立一个维持现有幸福感的最低消费水平,避免陷入一种无限替换和升级的状态。

30%的范围内可以犒劳一下自己,装点一下生活。

20% 储蓄

既是原始资金的积累,也是一份保障。最好的实行办法就是强制(e.g. 定期)。

10% 保险

常在河边走,哪有不湿鞋

​关键要养成保险意识。在短期内,一个人发生意外事件的可能性是非常低,但是如果把时间尺度拉长,就会发现,早晚会遭遇一次小概率事件。

再有多余收入或飞来横财,再按以上规则迭代分配

六、总结

理财是一个长期、系统的过程,首先你得有一种很强的未来感,把自己、沉没成本以及财产都纳入一个长期的规划和打算。养成理财的习惯,合理分配资产可以帮助我们达到理想的财务状态,实现财务自由,最重要的是能把生活品质带上一条持续向上的斜坡,这是把控自己的生活,实现幸福生活的关键。


[1]沉没成本 即已经付出且不可收回的成本,如时间、金钱、精力等

[2]投资组合 由投资人或金融机构所持有的股票、债券衍生金融产品等组成的集合。投资组合的目的在于分散风险。

本文介绍使用Gradle快速构建Java项目

由于博主使用的是Intellj IDEA,所以如果你对Intellj IDEA的项目结构不熟悉,那你可能需要先了解一下Intellj IDEA的项目结构:一个project(区别eclipse中的project)+ 多个modules,以下图为例,spring-boot-rmi是项目,greenqiang,laowang,oldwang,xiaoming是4个module

Gradle准备

  • 安装jdk或者jre,且版本至少是6以上
  • 官网安装gradle

配置文件与构建脚本

使用gradle构建项目,项目根目录下会有build.gradle和settings.gradle两个文件(如上图)

settings.gradle 配置文件

1
2
3
//多项目(或多modules)管理
//rootProject.name = "spring-boot-rmi" //根项目
include "old-wang", "green-qiang"

build.gradle 构建脚本

  • 根目录下的构建脚本 /build.gradle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//项目基本信息
group 'cn.willowspace'
version '1.0-SNAPSHOT'

//allprojects or subprojects
allprojects {
//应用插件
apply plugin: 'java'
//指定编译级别
sourceCompatibility = 1.8
targetCompatibility = 1.8
//指定依赖仓库
repositories {
mavenLocal()
mavenCentral()
maven {
url 'http://repo.spring.io/libs-milestone/'
}
}
//依赖管理
dependencies {
//spring-boot-starter-parent
compile group: 'org.springframework.boot', name: 'spring-boot', version: '1.2.8.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.2.8.RELEASE'
}
}
  • old-wang子项目的构建脚本 old-wang/build.gradle
1
2
3
4
5
6
7
8
9
10
11
//指定项目的源码及资源文件路径
sourceSets {
main {
java {
srcDir 'old-wang/src/main/java'
}
resources {
srcDir 'old-wang/src/main/resources'
}
}
}
  • green-qiang子项目的构建脚本 green-qiang/build.gradle
1
2
3
4
5
6
7
8
9
10
11
//指定项目的源码及资源文件路径
sourceSets {
main {
java {
srcDir 'green-qiang/src/main/java'
}
resources {
srcDir 'green-qiang/src/main/resources'
}
}
}

通过settings.gradle及build.gradle两类文件,我们就可以建立起项目之间的依赖及第三方依赖,一个java项目的基本构建就完成了。

更多gradle相关的用法,参考Gradle User Guide 中文版

IDEA中Gradle的设置 ,特别注意:不要在IDEA里开启offline work选项,否则你可能经常找不到你要的dependencies

  • Offline work - use this check box to work with Gradle in the offline mode. In this case Gradle will use dependencies from the cache. Gradle will not attempt to access the network to perform dependency resolution. If required dependencies are not present in the dependencies’ cache, a build execution will fail.

朝 代 起 讫 都 城 今 地
约前2146-1675年 安邑 山西夏县
[1] 约前1675-1029年 河南商丘
西周 [2]约前1029-771年 镐京 陕西西安
东周 前770-256年 洛邑 河南洛阳
前221-207年 咸阳 陕西咸阳
[3]西汉 前206—公元25 长安 陕西西安
东汉 25—220 洛阳 河南洛阳
三国
曹魏 220-265 洛阳 河南洛阳
蜀汉 221-263 成都 四川成都
孙吴 222-280 建业 江苏南京
西晋 265-317 洛阳 河南洛阳
东晋 317-420 建康 江苏南京
[4]十六国 304-439
南朝
420-479 建康 江苏南京
479-502 建康 江苏南京
502-557 建康 江苏南京
557-589 建康 江苏南京
北朝
北魏 386-534 平城 河南洛阳
东魏 534-550 河北临漳
北齐 550-577 河北临漳
西魏 535-557 长安 陕西西安
北周 557-581 长安 陕西西安
581-618 大兴 陕西西安
618-907 长安 陕西西安
五代十国
后梁 907-923 河南洛阳
后唐 923-936 河南洛阳
后晋 936-946 河南开封
后汉 947-950 河南开封
后周 951-960 河南开封
[5]十国 902-979
北宋 960-1127 开封 河南开封
南宋 1127-1279 临安 浙江杭州
907-1125 皇都(上京) 内蒙古 巴林左旗
大理 937-1254 太和城 云南大理
西夏 1038-1227 兴庆府 宁夏银川
1115-1234 会宁 阿城(黑龙江)
中都 北京
开封 河南开封
1368-1644 北京 北京
1616-1911 北京 北京
中华民国 1912-1949 南京 江苏南京
中华人民共和国 1949-10-01 北京 北京

附注:

  1. [1]约公元前14世纪盘庚迁都于殷,此后商也成为殷。
  2. [2]公元前841年(西周共和元年)为中国历史确切纪年的开始。
  3. [3]包括王莽建立的”新”王朝(公元8年—23年)。王莽时期,爆发大规模的农民起义,建立了农民政权。公元23年,新王莽政权灭亡。公元25年,东汉王朝建立。
  4. [4]这时期,在我国北方,先后存在过一些封建政权,其中有:汉(前赵)、成(成汉)、前凉、后赵(魏)、前燕、前秦、后燕、后秦、西秦、后凉、南凉、北凉、南燕、西凉、北燕、夏等国,历史上叫做”十六国”。
  5. [5]这时期,除后梁、后唐、后晋、后汉、后周外,还先后存在过一些封建政权,其中有:吴、前蜀、吴越、楚、闽、南汉、荆南(南平)、后蜀、南唐、北汉等国,历史上叫做”十国”。 |

文件上传

1
curl -H "Cookie:SESSION_ID=122F2F097414B9B8DA06E01F0025A5FF" -F "file=@/var/data/image.jpeg" http://demo.cn/uploadFile

通过设置Cookie来模拟登陆调试接口

Cookie的获取可以通过在Chrome的Network里查看域名下任一一个请求的Head,复制Cookie即可

1
curl -X POST -H "Host:{hostName}" "http://{ip}/{uri}" -H "Cookie:{values}" -d "{parameters}" -i -v

下载文件

1
2
3
4
# 使用curl
curl -o ${saved_filename} ${url}
# 使用wget
wget -O ${saved_filename} ${url}

测速

1
curl -o /dev/null -s -w '%{time_connect}:%{time_starttransfer}:%{time_total}\n' 'https://demo.cn'
计时器 描述
time_connect 建立到服务器的 TCP 连接所用的时间
time_starttransfer 在发出请求之后,Web 服务器返回数据的第一个字节所用的时间
time_total 完成请求所用的时间
time_namelookup DNS解析时间,从请求开始到DNS解析完毕所用时间(记得关掉 Linux 的 nscd 的服务测试)
speed_download 下载速度,单位-字节每秒。

使用curl调试dwr接口

-i参数可现实response的相关头信息

1
curl -X POST -H "Host:{hostName}" "http://{ip}/{path}/{dwrClass}.{dwrMethod}.dwr" -H "Content-Type: text/plain" -d "{dwrUrlParameter}" -i -v

0%