Play2 自定义模板类型 (Java&Scala)

Play2 默认支持的模板类型是 html, txt, xml 和 js,不在这些支持之列的模板文件即使放到 app/views 目录中,也不会被编译的。如果要支持自定义的模板类型就要些定制了,这比 Play1 复杂些。模板的定制包括在 Build.scala 或 build.sbt 中加上 templatesTypes 配置,并需创建 BufferedContent 和 Format 实现类。下面以增加 json 模板类型为例,兼顾 Scala 和 Java 的实现类,是基于 Play2.2 的,在 Play2.3 中又略有不同。

官方有相关的文档,参考:Custom formats on Scala, Custom formats on Java模板定义参考.

在较新一些的 2.2 的 PlaySettings 中,可以看到

弄清了上面的原理后,开始我们的步骤

第一步:修改项目构建文件

在构建文件 build.sbt 或 Build.scala 中增加下面的内容作为项目的 setting 阅读全文 >>

如果要给 RESTful 每种 HTTP Method 类型指示一种颜色

RESTful 时需要考虑每种 HTTP Method 操作的业务含义,再也不是 GET 使用 URL, POST 提交表单这样简单的区别。http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html 定义有 GET, POST, PUT, HEAD, DELETE, PATCH, OPTIONS, TRACE, CONNECT 九种类型的 HTTP Method。

关于它们可能针对的业务含义就不多说了,而是如果要对每一种操作方法赋予一个颜色应该怎么去对应呢,比如一般 GET 不会有边际效应的操作可以选择绿色,或者蓝色。幸好我也不用多想,这里参考了 Swagger 的颜色方案,它支持除 OPTIONS, TRACE 和 CONNECT 之外的颜色配置,其实我也没用过这两种方法。

从 Play2 Swagger 中截图如下: 阅读全文 >>

Java 的匿名类初始化块中如何访问同名参数?

因为写过类似下面的一段代码来实始化一个匿名实例

看上面的 buildTest() 方法中的 this.name = name 希望能把方法参数 final String name 中的 name 值赋值给 this.name, 但是无效,this.name = name 是在把自己赋给自己。 阅读全文 >>

代码中如何获得 Java 方法的形式参数名

对于一个 Java 方法 foo(int id, String name); 我们如何能在代码中获得形式参数名 id 和 name 呢?

我们知道通过反射 API Method.getGenericParameterTypes() 可以获得方法的参数类型,但是对于参数名一般就是 arg0, arg1, arg2 ..., 因为 Java 编译时把形式参数名擦除了。所以对完全擦除了形式参数名的字节码应该是没办法了,但我们自己写的类还是有能力去管控的。

对于自己写的类,有两种办法获得形式参数名,分别是

1) Java8 的 -parameters 编译参数,然后用 Java8 新引入的反射 API Parameter

我们先在 Java8 下运行下面的代码 阅读全文 >>

Mac OS X 下吾所倾爱的三个程序员编辑器

作为编程,讲救效率自然是用各种 IDE,诸如 Idea, Eclipse, NetBeans 等。但平时总也离不开一款趁手的纯文本编辑器,如阅读各种语言的代码,简单编辑。我就经常会用 Sublime 这类工具的列编辑功能,奇怪于为何 IDE 们鲜有提供列编辑的特性的。

在 Mac 下的 TextEdit 其实是一款富文本编辑器,且未给编程带来任何便利。根据本人从开始扑向 Mac OS X 平台起到现在,选择过三款程序编辑器,它们分别是 TextMate, Sublime 和 Atom,前两为付费的,最后一个是免费的。

1. TextMate

最早听说很多人喜欢用它写 Ruby 程序,也不知是不是真的. TextMate 以其卓越的 Bundle 们驰行于天下。只是最近几年来它却裹足不前了,似乎失去了前进的方向,一直稳定在 1.5.11 版本上,2.0 已经 alpha 很久了. 其间好像思考过开源,出现在了 GitHub 上 https://github.com/textmate/textmate,少有维护。 阅读全文 >>

Java 和 Scala 调用变参的方式

Java 和 Scala 都支持变参方法, 写在最后的位置上,最基本的调用方式也都是一样的,一个个罗列过去。也可以传入数组参数,因为变参本质上就是一个数组,就是把 ... 开始位置到最后一个参数都收纳到数组中去,所以变参之所以要放在最后的位置上,且一个方法中最多只能有一个变参类型。

这里主要是对比 Scala 对变参方法的调用,基本调用法当然是没问题的,但是在传入数组作为变参的参数列表与 Java 相对时就稍有变化了。

另外提一下,如果想传入 List 作为变参列表,而不是整体作为变参的第一个元素就是调用集合的 toArray() 方法转换成一个数组传入。

下面看 Java 中对变参方法的调用,参数列表和数组

阅读全文 >>

为 Jackson 自定义序列化对象的 JSON 格式

伴随着 Play1, 我们原来使用的 JSON 库是 Gson. 回忆下 Gson 是怎么自定义序列化对象的 JSON 格式,大概是这样子的

GsonBuilder()..registerTypeHierarchyAdapter(Cat.class, new Cat());

然后 Cat 需要实现 JsonSerializer 的 serialize() 方法。

来到了 Play2 中,JSON 库变成了 Jackson,那么 Jackson 该如何为对象自定义 JSON 格式呢?

例如,默认时 Jackson 对 Map 类型输出的是一个 JSON 对象

Map("key1"->"value1", "key2"->"value2")     转换成 JSON 是 {"key1":"value1", "key2":"value2"}

当为适应某些客户端,对于 LinkedHashMap 类型,我们想要输出的是一个有序的 JSON 数组: [{"key1":"value1"},{"key2":"value2"}]

我们就应该自定义某些 Map 的序列化格式,实现方法有两种,addSerializer 和 @JsonSerialize,不管哪种方式都需事先具体化 JsonSerializer 类,并实现它的 serialize 抽象方法

所以我先来实现一个能序列化 Map 的 JsonArrayMapSerializer 类 阅读全文 >>

sbt 中自定义的 Task

sbt, 又是一种自动化构建工具,意为 Simple Build Tool,目前还难副其名,它管理依赖也是用的 Ivy。Scala 相关的项目一般会用它,如 Play2,所以需要来研究下它怎么自定义任务。

sbt 项目可以用 build.sbt 或 project/Build.scala 来定义项目,build.sbt 里写些简单的 settings 表达式,而 Build.scala 就强大,可以写 val, object 和方法定义。而且单个 Build.scala 可以定义多个项目,build.sbt 只用来定义当前项目。build.sbt 和 project/Build.scala 能同时存在,它们的内容会编译到一块。还有一个全局的 build.sbt 文件 ~/.sbt/build.sbt,这里控制所有的项目。

所以我们分别看在 project/Build.scala 和 build.sbt 中如何定义自己的 task

首先看 project/Build.scala,分别由两行完成

val mytask = taskKey[Unit]("This is my customized task")
mytask := { println("Execute customized task")}

完整的一个 project/Build.scala 如下 阅读全文 >>

logback.xml 给变量指定默认值

随着通用日志组件转入 Slf4j,logback 也变成了默认的日志实现,像 log4j 一样,logback.xml 中也可以使用系统属性或环境变量,如 ${catalina.home}。在 log4j.properties 中,如果变量在系统属性和环境变量中找不到的话默认为 "" 空字符串,而到了 logback.xml 中如果某个变量找不到默认就是 "变量名_IS_UNDEFINED" 了,这样就比较奇怪了。

那如何在没有配置 catalina.home 系统属性或环境变量时设置一个默认值呢,例如,没有 catalina.home  时取值为 ".",这时值日志文件的路径就是

./logs/unmi-%d{yyyy-MM-dd}.log

了,也就是生成中当前目录下的 logs 子目录中,这样算是很友好的方式。下面就来分析怎么一步步找到答案的,没耐心或是只求结果的话,直接滚屏到下面就行。

我们的问题是,对于下面那样的 logback.xml 配置: 阅读全文 >>

Mac OS X 下安装使用 Docker

前注: 欢迎进到本页, 本篇写时较早, 而 Mac OS X 下 Docker 早不建议用 boot2docker 了, 取而代之的是 docker-machine. 请点击链接 Mac OS X 下安装使用 Docker (新) 查看最新安装过程与体验

云主机可以选择操作系统镜像快速创建主机,这比虚拟机更便捷了,我们本地也可以这么做了,因为有了 Docker 这个东西。它依赖于 LXC(Linux Container),能从网络上获得配置好的 Linux 镜像,非常容易在隔离的系统中运行自己的应用。也因为它的底层核心是个 LXC,所以在 Mac OS X 下需要在 VirtualBox 中跑一个精小的 LXC(这里是一个 Tiny Core Linux,完全在内存中运行,个头只约 24MB,启动时间小于 5 秒的 boot2docker) 虚拟机,构建在 VirtualBox 中。以后的通信过程就是 docker --> boot2docker --> container,端口或磁盘映射也是遵照这一关系。

理解了上面的关系,开始说说 Docker 安装过程

1. 安装 VirtualBox, 不多讲, 因要在它当中创建一个 boot2docker-vm 虚拟机

2. 安装 boot2docker

brew install boot2docker

你也可以手工安装 阅读全文 >>