写下此篇流水纯粹是为了重拾那些零星的记忆,只能建立起一个模糊的脉络,找不回具体的时间点了,现在也是试着能否从某些日志里寻回些线索来。本篇日志最早创建于 2014 年 2 月份,中间偶有修改,却一直在草稿箱里静静的躺着。终于又时隔多年首次放出一篇非技术文出来。
1. 开始的开始,2001 年工作起,进入一个几乎完全陌生的程序世界。为了奋力从大海洋中汲取营养,大跃进的方式学习,并坚持在笔记本上面现在看来像是抄写一样的记笔记,不觉几年功夫,工工整整,满满的记载了四五本笔记本。还有看到那些好的东西也爱打印下来,其实打印出来的东西与它在网络上是一回事,没完整看的还是没看完,写下来了可不一样。这样记笔记的习惯其实也是工作之后的事情,上学期间最爱在课本上记东西。
2. 到后来是网络的盛行,也是信息量的爆炸的时代,再系统再全的书籍也无法与 Google 相比了。所以大概是 2005 年想到了在 QQ 空间里记了三五篇,一块娱乐之地上记录这些东西格调十分不搭。
3. 找到了第一个真正意义上的 BSP,那就是 blogcn.com,它现在完全变样了。QQ 上的几篇只需要复制到编辑框保存就行,那应该是 2006 年的事情。blogcn 是个综合性的 BSP,不好玩,代码高亮用工具保存成的带样式的 HTML 代码,好像也只在这里折腾了一年多时光,到 2007 吧,继续寻租。 Read More
追溯到刚开始学习 Groovy 还是在 2008 年,距今 2018 年有九年半余,曾记下几篇 Groovy 的日志。那时学习 Groovy 并无明确的目的,只因它是脚本语言, 可用来快速验证 Java API。曾经 BeanShell 芸花一现, JRuby 和 Jython 总是别人家的语言照搬而来的。而 Scala,Nashorn(jjs), JShell 更是后来的事,唯有 Groovy 写起来很亲切,完全不懂 Groovy 都没关系,直接上 Java。
现如今之所以重新勾搭上了 Groovy 是因为它仍然坚挺着,在 SoupUI(ReadyAPI) 和 Jenkins 中获得了重视,倒不是因为 Gradle。先前 Groovy 在 Spring 框架中的地位估计要被如今的 Kotlin 取而代之。
好了,回顾完后进入正题,关于 Groovy 如何进行多重赋值,以及延伸到方法返回多个值的情形。这里所说的多重赋值不是指用连等号来同时赋为一个值,
def a = b = c = 100 //不是说的这个
而是指同时对多个变量一步到位的赋成不同的值,要实现这个必须用到 List 类型。看下面一个基本例子(GroovyConsole) Read More
Scala 有一个自身类型(self-type) 的东西,由来已久,居然今天才发现。如果一个类或 trait 指明了 self-type 类型(包括类和特质),它的子类型或是对象也必须是相应的类型。它产生的效果与继承(或 mixin) 颇有几分相似。self-type 的语法是this 的别名: 某一类型(class 或 trait), 直接看一个例子:1class User(val name: String) 2 3trait Tweeter { 4 this: User => //这个表示 Tweeter 本身也必须是一个 User,它的子类型必须想办法符合这一要求 5 def tweet(tweetText: String) = { 6 println(s"$name: $tweetText") 7 } 8} 9 10class VerifiedTweeter(val username: String) 11 extends User(username) with Tweeter { //Tweeter 要求这个类必须是一个 User, 所以需要继承自 User 类 12} 13 14val v = new VerifiedTweeter("Yanbin") 15v.tweet("Hello")
上面this: User =>中的this只是一个别名,可以是self或任何有效标识(如abc: User),这里使用this等于未指定别名,与原本的 this 重叠了。如果声明为非this的话则可以这么用 Read More
Akka 是什么?它提供了 JVM 上的 Actor 编程模型 -- 同时兼顾了并发与分布式。它由 Scala 编写的,替代了 Scala 本身的 Actor。Actor 视线程为重量级的资源,能够以少量的内存胜任更高的并发,类似的东西有纤程,协程。有一个数据对比是同样的 1GB 内存,可以创建 2.7M 个 Actor, 而线程只能创建 4096 个,仅供参考,当然 Java 也是会基于线程池来执行的。
Actor 增加了程序的灵活性,并减轻了复杂度(标准的赞美之辞)。
所谓 Action 编程模型兼顾并发与分布,是由于让你编程时可以不用考虑线程,线程配置成为部署的范畴; Actor 之间通信只能发送异步消息,Actor 可以分布在同一 JVM, 不同 JVM, 或是不同物理机器上。
因为 《Akka IN ACTION》中提供了第一个例子起点着实有点高,所以网上找来了一个了解 Akka Actor 的最简单例子,来自于 Simple Scala Akka Actor examples (Hello, world examples)。并非纯属翻译,主要是为了练手,所以不完全一致: Read More刚开始阅读 《Akka IN ACTION》这本书,刚开始是对
Revolution这个词翻译成中文是革命感到诧异,因为革命通俗来讲就是杀人的意思。至于Revolution英文解释不深究了,只是感叹何以颠覆性的变化就一定要杀人吗?也由此引出了编程中经常面对的
Concurrent(名词为:Concurrency) 和Parallel(名词为:Parallelism) 这两个词,基本上是认为它们是同一个意思。其实不然,下面慢慢道来。如果从英文字典对它们的解释也没有多大区别,差不多都是说同是发生,但字面上
Parallel多了一个平行的意思。所以在中文上,在计算机领域我们约定的翻译是- Concurrent(Concurrency) -- 并发
- Parallel(Parallelism) -- 并行
比如在多线程环境中它们的区别具体体现在:
并发:多个任务在同一个 CPU 核上按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。针对 CPU 内核来说,任务仍然是按细粒度的串行执行。也难怪在 Java 5 中新加的并发 API 的包名是
java.uti.concurrent。 Read More
对列表的去重处理,Java 8 在
Stream接口上提供了类似于 SQL 语句那样的distinct()方法,不过它也只能基于对象整体比较来去重,即通过 equals/hashCode 方法。distinct方法的功效与以往的new ArrayList(new HashSet(books))差不多。用起来是List<Book> unique = book.stream().distinct().collect(Collectors.toList())
并且这种去重方式需要在模型类中同时实现 equals 和 hashCode 方法。
回到实际项目中来,我们很多时候的需求是要根据对象的某个属性来去重。比如接下来的一个实例,一个 books 列表中存在 ID 一样,name 却不同的 book, 我们认为这是重复的,所以需要根据 book 的 id 属性对行去重。在 collect 的时候用到的方法是
collectinAndThen(...), 下面是简单代码: Read More
还是从 OSChina 网站上得知 Clojure 1.9 在 2017 年 12 月发布的,时值这么久才开始真正去了解一下这个新版本。距离上一个版本 1.8 的发布时间(2016 年 1 月), 大概两年才出一个版本,而且总的说来 Clojure 1.9 并没有带来多大惊喜。
唯一能带来点喜气的也就是 Clolure 有了自己的命令行工具了,再也无需寄身于 Leiningen(一个 Clojure 构建工具,相当于 sbt 之于 Scala) 的篱笆之下了。以 Mac OS 平台为例,以前试图用 brew 来直接安装clojure的时候会提示找不到clojure, 建议安装leiningen.$ brew install clojure
在 Clojure 1.9 出来之前,上面的命令会得到如下提示信息Error: No available formula with the name "clojure"
所以那时候不得不用 Read More
Clojure isn't really a program but a library managed as part of a
project and Leiningen is the user interface to that library. To install Clojure you should install Leiningen:
brew install leiningen
and then follow the tutorial:
https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md
初识 Mockito 这个测试框架后,我们要使用 Mock 的属性创建一个被测试类实例时,大概会下面这么纯手工来打造。
假定类
UserService有一个属性UserDao userDao, 需要构造UserService实例时 Mock 内部状态UserDao userDao = Mockito.mock(UserDao.class);
UserService testMe = new UserService(userDao);如此,userDao 的行为就可以自由模拟了,这种纯手工方式都不需要给测试类添加
@RunWith(MockitoJunitRuner.class)
//或
MockitoAnnotations.initMocks(this);因为上面两句是给 Mockito 的注解使用的。
如果所有的 Mock 对象全部通过手工来创建,那就不容易体现出 Mockito 的优越性出来。因此对于被测试对象的创建,Mock 属性的注入应该让
@Mock和@InjectMocks这两个注解大显身手了。标注在实例变量上的
@Mock相当于是Mockito.mock(Class)创建了一个 Mock 对象,而@InjectMock标的实例会寻找到相应 Mock 属性想法构造出被测试类的实例。看下面的例子: Read More
Docker 镜像在未指定仓库时默认是从 Docker Hub 拉取的。如果需向 Docker Hub 推送镜像的话还可用docker login在交互中完成登陆 Docker Hub 的操作。docker login的命令格式是docker login [OPTIONS] [SERVER]
所以我们可以连接到任何的 Docker 镜像仓库,也可以是本机,但我们这里所要介绍的是如何推送镜像到 AWS 给我们提供的 Docker 镜像仓库(Amazon ECR - Amazon Elastic Container Registry)。每个帐号下都有自己独立的仓库,镜像推送到了 Amazon ECR 后我们能够很方便的在 ECS, Batch 服务中使用它,也可以从 ECR 拉取镜像到本地来。
首先我们来做一个运行 Spring Boot Web 的简单的 Docker 镜像,假定已用mvc pacakge生成了一个可独立运行的 jar 包java-webapp-0.0.1-SNAPSHOT.jar。该应用开启一个 Web 服务,访问 http://localhost:8080 显示一行字符串Hello World!
创建一个目录 aws-docker, 并把java-webapp-0.0.1-SNAPSHOT.jar移入该目录,在其下创建Dockerfile文件,文件目录结构如下:aws-docker
Read More
├── Dockerfile
└── java-webapp-0.0.1-SNAPSHOT.jar
Bash 环境
多数时候我们用的是 Bash, 比如个人的 Linux 不愿去定制,远程服务器的由不得你去定制,所以就从 Bash 说起。
默认键绑定
emacs, 操作是ctrl-x, ctrl-e在默认的 Bash 环境下,只要在命令行中按下
ctrl-x, ctrl-e就会把当前命令的内容调入到环境变量$EDITOR指示的编辑器(默认为 emacs)去编辑,编辑后保存退出就会立即执行。如果未安装
Emacs编辑器,在按下ctrl-x, ctrl-e会得到如下提示[vagrant@localhost ~]$
-bash: emacs: command not found如果希望使用
vi来编辑当前命令,就需要设置EDITOR环境变量,比如在.bashrc中加入export EDITOR=vi
那么在命令行中按下
ctrl-x, ctrl-e使用打开vi来编辑当前命令。注:Emacs 要用
ctrl-x, ctrl-c, 再回答y, 命令保存到临时文中; 而 vi 的相应操作是:wq, 至少这个操作上 vi 要简洁些。 Read More