面向函数编程

Play框架入门使用

  Play 是一个开源高性能Web框架,能够基于Java或Scala编写可扩展可伸缩的应用系统,它能自动刷新源码的变动从而具有快速开发产品的能力,它还是一个无态非堵塞的框架,易于横向扩展。

  Play!框架有如下特点:

  • 高开发效率:Java EE和Spring框架并不适合快速原型开发,Play框架参考动态语言的快速开发能力,它支持热重载所有的Java代码和模板等,让你更快地迭代。基于Netty构建非堵塞异步机制。
  • REST JSON 支持:非常容易编写RESTful应用,非常适合支持HTTP路由。

  本教程将向您展示这两个特点。

安装

首先确认安装了Java环境,下载最新版本Play binary package ,注意不是Typesafe Activator。

将解压后的Play目录加入环境,windows是在环境设置中,如同Java一样加入path,Linux是:

export PATH=$PATH:/relativePath/to/play

检查是否正常安装:

play help

出现如下界面表示正常:

 

创建一个新的应用

   在命令行输入,将提示你应用名称,然后选择创建Scala还是Java应用程序。

$ play new myFirstApp

通过下面命令启动自己的应用:

$ cd myFirstApp  
$ play
当出现[myFirstApp] $ 表示已经进入play控制台。

标准PLAY项目结构

app                      → 应用源码
 └ assets                → 编译后的 asset资源源码
    └ stylesheets        →CSS sources
    └ javascripts        → CoffeeScript sources
 └ controllers           → 应用控制器
 └ models                → 应用业务层
 └ views                 → Templates模板
conf                     → 配置其他非编译资源(on classpath)
 └ application.conf      → 主配置文件
 └ routes                → 路由定义
public                   → 公共资源assets
 └ stylesheets           → CSS files
 └ javascripts           → Javascript files
 └ images                → Image files
project                  → sbt 配置文件
 └ build.properties      → Marker for sbt project
 └ Build.scala           → Application build script
 └ plugins.sbt           → sbt plugins
lib                      → 未管理的库包依赖
logs                     → Standard logs folder日志
 └ application.log       → Default log file
target                   → Generated 编译产生的文件
 └ scala-2.10.0           
    └ cache             
    └ classes            → Compiled class files
    └ classes_managed    → Managed class files (templates, ...)
    └ resource_managed   → Managed resources (less, ...)
    └ src_managed        → Generated sources (templates, ...)
test                     → source folder for unit or functional tests

 

play控制台

   前面已经进入我的第一个应用控制台,键入

$ help play

获得帮助,运行命令如下:

$ run

在这种模式下,服务器将被启用自动重载功能启动,Play将检查您的项目,需要重新编译源代码。如果需要该应用程序会自动重新启动。

当出现:

[info] play - Listening for HTTP on /0.0.0.0:9000

(Server started, use Ctrl+D to stop and go back to the console...)

表示启动服务器在9000端口,在浏览器键入http://localhost:9000/ 看到:

Your new application is ready

这是在项目app/controller目录下有一个Application.scala:

package controllers

import play.api._
import play.api.mvc._

object Application extends Controller {

  def index = Action {
    Ok(views.html.index("Your new application is ready."))//改为中文
  }

}

我们将输出改为中文:“这是我的项目.”

编译

   Crtl-D回到控制台中断运行,输入:compile,出现如下错误:

[info] Compiling 1 Scala source to E:\temp\myFirstApp\target\scala-2.10\classes.
..
[error] IO error while decoding E:\temp\myFirstApp\app\controllers\Application.s
cala with UTF-8
[error] Please try specifying another one using the -encoding option
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed 2013-12-8 14:49:44

这个错误是Play将我们的模板文件翻译转换为Scala文件在目录myFirstApp\target\scala-2.10\src_managed\main\views\html下面,这些文件将被sbt 编译成.class文件,然后被play运行。SBT以默认的编码方式创建这些中间文件。

解决办法:设置环境JAVA_TOOL_OPTIONS为-Dfile.encoding=UTF8

然后重新再进入Play控制台,会看到picked up输出:

E:\temp>cd myFirstApp

E:\temp\myFirstApp>play
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8

使用Eclipse

   输入$eclipse,将我们的项目生成Eclipse项目,打开Eclipse导入即可。注意,eclipse的windows->preference-->General -->Workspace要设置为Utf-8,如下:

编译正常后,再次运行,浏览器出现:

Eclipse Scala插件

   在http://scala-ide.org下载Eclipse的Scala插件。在eclipse -->install new software输入升级地址,会有很多,选择Scala IDE for scala.

应用案例

   下面我们使用Play的WebServices library实现非堵塞的URL调用:

import play.api.mvc.{Controller, Action, Result}
import play.api.libs.ws.WS
import play.api.libs.json.Json
import play.api.libs.concurrent.Execution.Implicits._
import scala.concurrent.Future
 
object Race extends Controller {
 
  def index() = Action {
    Async {
      val start = System.currentTimeMillis()
      def getLatency(r: Any): Long = System.currentTimeMillis() - start
     
      val googleTime = WS.url("http://www.google.com").get().map(getLatency)
      val yahooTime = WS.url("http://www.yahoo.com").get().map(getLatency)
      val bingTime = WS.url("http://www.bing.com").get().map(getLatency)
 
      Future.sequence(Seq(googleTime, yahooTime, bingTime)).map { case times =>
        Ok(Json.toJson(Map("google" -> times(0), "yahoo" -> times(1), "bing" -> times(2))))
      }
    }
  }
 
}

  这是统计调用三个网址的时间,通过异步获得统计结果。将这个Race加入Route:

GET     /race                       controllers.Race.index()

浏览器调用http://localhost:9000/race ,可能会出现如下错误:

这是因为我们没有导入import play.api.libs.json.Json

重新运行,正常结果如下:

 

调试

  输入$ play debug ,进入调试JPDA 模式。输出:

Listening for transport dt_socket at address: 9999

在Eclipse的debug configuration中,新增:

然后我们在Race的 val start = System.currentTimeMillis() 设置断点,运行run,在浏览器调用,Eclipse将自动在断点暂停,如下:我们可以跟踪当前的变量等。

本项目源码下载

 

Reactive Postgres with Play Framework & ScalikeJDBC

Play框架案例源码下载(包括Java和Scala)  

Play框架专题

NodeJS入门事件编程

vertx入门教程

Netty原理和应用

Scala入门

JavaEE教程

Akka教程