一个最基础的 Spring 4 MVC Maven 项目

这是一个最基本的 Spring 4 MVC 的 Maven 项目,非 SpringBoot 的,SpringBoot 由于有许多自动化配置特性,会更简单些。本例全部用 Java 代码作为配置,免除了创建 web.xml 和如 dispatcher-servlet.xml 这样的文件。本人更倾向于 Java 配置,它的优势在于能进行编译期检查,逻辑性也强,配置文件只是改动无需重新编译,都是要重启服务的; 关于使用 XML 配置文件的方式可参考文后的链接。

本文侧重于 Spring MVC 项目提供 RESTful JSON API, 因而静态 Web 内容提及较少。创建一个 Maven 项目的方式,可以直接创建一个 pom.xml 文件,然后编辑它的内容,使用 IntelliJ IDEA 的话只需要选择导入为一个 Maven 项目就成,Eclipse 的话可能还要事先运行 mvn eclipse:eclipse 初始化一下。

项目结构布局

就是一个普通的 Maven 项目,稍稍不同的是 src/main 目录中除了 java 和 resources 之外,还有 webapp 目录,用于存放 web 静态文件或模板文件的。 阅读全文 >>

Scala 自身类型(self-type) 解析

Scala 有一个自身类型(self-type) 的东西,由来已久,居然今天才发现。如果一个类或 trait 指明了 self-type 类型(包括类和特质),它的子类型或是对象也必须是相应的类型。它产生的效果与继承(或 mixin) 颇有几分相似。self-type 的语法是 this 的别名: 某一类型(class 或 trait), 直接看一个例子:

上面 this: User => 中的 this 只是一个别名,可以是 self 或任何有效标识(如  abc: User),这里使用 this 等于未指定别名,与原本的 this 重叠了。如果声明为非 this 的话则可以这么用 阅读全文 >>

Akka Actor: 从最简单的例子开始

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)。并非纯属翻译,主要是为了练手,所以不完全一致: 阅读全文 >>

并发(Concurrent) 与并行(Parallel) 的区别

刚开始阅读 《Akka IN ACTION》这本书,刚开始是对 Revolution 这个词翻译成中文是革命 感到诧异,因为革命 通俗来讲就是 杀人 的意思。至于 Revolution 英文解释不深究了,只是感叹何以颠覆性的变化就一定要杀人吗?

也由此引出了编程中经常面对的 Concurrent(名词为:Concurrency) 和 Parallel(名词为:Parallelism) 这两个词,基本上是认为它们是同一个意思。其实不然,下面慢慢道来。

如果从英文字典对它们的解释也没有多大区别,差不多都是说同是发生,但字面上 Parallel 多了一个平行的意思。所以在中文上,在计算机领域我们约定的翻译是

  • Concurrent(Concurrency)  --  并发
  • Parallel(Parallelism)           --  并行

比如在多线程环境中它们的区别具体体现在:

并发:多个任务在同一个 CPU 核上按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。针对 CPU 内核来说,任务仍然是按细粒度的串行执行。也难怪在 Java 5 中新加的并发 API 的包名是 java.uti.concurrent阅读全文 >>

Java 8 根据属性值对列表去重

对列表的去重处理,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(...), 下面是简单代码: 阅读全文 >>

使用 Mockito 的 @InjectMocks 创建被测试类实例

初识 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 属性想法构造出被测试类的实例。看下面的例子: 阅读全文 >>

Scala 中应用 Future 并发编程

Java 世界里进行并发编程有 Future 和  ExecutorService(当成 ThreadPool 来对待),及至 Java 8 引入了更为趁手的 CompletableFuture。那么使用 Scala 该如何进行并发编程呢?Scala 能毫无障碍的使用 Java 类库,所以完全可以用 Java 的 API 来使用线程池,只是那不太 Scala 罢了。

既然是 Scala, 就尽量写成 Scala Style 吧,Scala 也有自己的 Future, 还有 Promise 呢? 至于 Promise 与 Future 多大区别,语义上似乎也差不多,只看到 Promise 中有一个 Future 的属性。如果想玩得高级一点的话就该把  Actor 弄起来,它算是所谓的纤程,多个  Actor 可跑在同一个线程中,当然启动要快,内存消耗少,还避免了上下文切换。

这里还是先体验 Scala Future 的用法。Future 本身只是描述了一个任务,及将要获得的结果(或执行的动作),因此那样一个任务也是要放到线程池中去执行。这和 Java 的 Future/ThreadPool 是一样的概念。稍有不同的是线程池的创建与使用,线程池的默认大小配置等。看个简单的应用示例,本次测试的 Scala 版本是 2.11.12,为了突出实际的线程池大小,我们把任务数设置为 20 个

Scala Future 并发编程体验

阅读全文 >>

用 PreparedStatement 向 SqlServer 中一次性插入多条记录

标准 SQL 都提供了下面这种方式一条 INSERT INTO 语句插入多条记录

INSERT INTO Customers(Id, Name, Age) VALUES (1, 'Name1', 21.5), (2, 'Name2', 32.3)

VALUES 之后用括号列出每一条记录。但是在 Java 中想把上面的语句转换成 PreparedStatement  来插入多条记录时就有些问题。要么写成

INSERT INTO Customers(Id, Name, Age) VALUES(?, ?, ?), (?, ?, ?), (?, ?, ?) ....

我们不知道 VALUES 后应该列多少个问号,而且  JDBC 对参数的个数是有限制的,最多 2000 个参数。如果根据字段个数来算一次添加多少条记录,那么这条 SQL 语句也是动态的,不能很好的作为 PreparedStatement 进行预编译。以一个表三个字段为例,2000 个参数下一次性最多能插入记录数 666 条,也可能由于输入是 666 条记录的任意数量,所以生成的语句非静态的。

这种方式与每次手动拼凑一个完全静态的 INSERT INTO 语句应该不会有太多的差别。

如果只是写成 

INSERT INTO Customers(Id, Name, Age) VALUES(?, ?, ?)

然后试图进行下面的操作 阅读全文 >>

体验 Scala 2.12 支持的 Java 8 风格(SAM) Lambda

上一次关注 Scala 新版本特性还是在将近五年前,针对的是  Scala 2.10. 后来也一直在使用 Scala,基本上是 Scala 2.11,但对 Scala 2.11 所带来的新特性基本无知,大约有个 Macro 功能,没什么机会用上,应用 sbt 时稍有接触。还是老句老话,了解新特性最可靠的文档是每个版本的的 Release Notes, 比如 Scala 2.12.0 Release Notes.

其中 Scala 2.12 带来的主要特性在于对 Java 8 的充分支持:

  1. Scala 可以有方法实现的 trait 直接编译为带默认方法的 Java 接口
  2. Lambda 表达式无需生成相应的类,而是用到 invokedynamic 字节码指令(这个是 Java 7 加进来的新指令)
  3. 最方便的功能莫过于终于支持 Java  8 风格的 Lambda,即功能性接口的 SAM(Single Abstract Method)

Scala 的 Lambda 内部实现

这儿主要是体验 Scala 2.12 如何使用 Java 8 风格的 Lambda. 在 Scala 2.12 之前,Scala 对 Lambda 的支持是为你准备了一大堆的 trait 类,有

  1. Function0, Function1, ...... Function22 (接收多个参数,返回一个值)
  2. Product1, Product2, ...... Product22 (函数返回多个值,即 TupleX 时用的)

阅读全文 >>

IntelliJ IDEA 中创建 Maven Scala 项目

Scala 项目看家的构建工具当然是 SBT, 假如我们已习惯于 Maven, 想要用 Maven 来构建 Scala 项目该如何做呢?那首先要找到一个 Maven Scala 相应的 Archetype, 然后用命令 mvn archetype:generate 或是在 IntelliJ IDEA 使用 Maven 项目创建向导来选择一个 Maven Scala Archetype。这里主要介绍 IntelliJ IDEA 中 Maven 向导创建 Scala 项目的方式。

首先确保我们已安装了 IntelliJ IDEA 的 Maven 和  Scala 插件。插件中自带了 org.scala-tools.archetypes:scala-archetype-simple:1.2 的 Maven archetype, 这是一个貌视 Scala 官方的 archetype。我们可以尝试基于它来创建一个 Maven Scala 项目。通过 IntelliJ IDEA 的菜单 File/New/Project..., 在弹出的窗口中选择 Maven/Create from archetype, 然后找到 scala-archetype-simple, 自带版本为 1.2, 当前最新版也不过 1.3, 那还是  2010 年建立,别提有多老了。 阅读全文 >>