准备工作
首先下载play http://www.playframework.com/download
解压到任意目录,将play根目录加入到系统的PATH环境变量中
【play解压目录中没有bin目录,直接指定解压目录到Path中即可,也可设置一个PLAY_HOME,然后在Path中引用】
jdk1.6以上
命令:play version 查看play版本
play本地文档 http://localhost:9000/@documentation
Begin
使用play自动创建项目,将生成一个整体的play项目的基础框架出来
注意:不要将自动创建的项目指定到Eclipse的workspace目录中!否则将破坏eclipse的工作环境!
创建一个项目:play new 项目名称
CMD切换到项目路径下,如:cd E:\technology-hqh\proj\play-framework
切换到E盘下的proj/play-framework目录下
在该目录中创建play项目,使用命令:play new Demo
这样,就自动创建好了一个play的项目,项目名称为Demo!
项目结构
运行刚创建好的项目
E:\technology-hqh\proj\play-framework>play run Demo
项目启动后,将监听9000端口
访问项目
http://localhost:9000 显示Play的欢迎界面,解释了程序是如何跳转到这个页面的
将play应用转换为eclipse工程项目
play eclipsify Demo
Eclipse中通过 File/Import/General/Existing project
这样,就能通过Eclipse导入项目了!
项目的wokespace另外指定,不要将eclipse使用的workspace指向play所创建的项目目录!
程序执行流程分析
1.程序入口 conf/routes
- GET / Application.index
告诉Play,当服务器收到来自于/路径的GET请求时要调用Application.index的方法。
Application.index是controllers.Application.index简写,因为controllers包是隐式附加的!
2.控制器 app/controllers
Play程序有多个入口方法,每个URL就有一个。这些方法称为action方法。
定义Action方法的类称为controller。
- package controllers;
- import play.*;
- import play.mvc.*;
- import java.util.*;
- import models.*;
- public class Application extends Controller {
- public static void index() {
- render();
- }
- }
controller 类继承于play.mvc.Controller类,这个类提供了许多controller需要的方法,比如在index action中的render方法。
index action定义为public static void,因为controller类不需要实例化和返回值。
缺省的index动作调用render方法,通知Play渲染一个模板。
使用模板是返回HTTP响应的一个最通用的方式。
模板是在/app/views 目录下的简单文本文件。
模板是app/views目录下一个简单的text文件。
因为这里没有指定一个模板,index action会使用一个默认的模板:Application/index.html。
3.模板 app/views
- #{extends 'main.html' /}
- #{set title:'Home' /}
- #{welcome /}
#{extends /} tag 表示这个模板继承于main.html这个模板。
模板继承可用来创建复杂的web和重用公共部分。
#{welcome /} tag会在浏览器中生成欢迎信息。
main.html模板
- <!DOCTYPE html>
- <html>
- <head>
- <title>#{get 'title' /}</title>
- <meta charset="${_response_encoding}">
- <link rel="stylesheet" media="screen" href="@{'/public/stylesheets/main.css'}">
- #{get 'moreStyles' /}
- <link rel="shortcut icon" type="image/png" href="@{'/public/images/favicon.png'}">
- <script src="@{'/public/javascripts/jquery-1.6.4.min.js'}" type="text/javascript" charset="${_response_encoding}"></script>
- #{get 'moreScripts' /}
- </head>
- <body>
- #{doLayout /}
- </body>
- </html>
#{doLayout /}tag表示index.html插入内容的地方。
请求生命周期
Play是完全无状态的(stateless),且仅面向请求-应答(Request-Response)。所有请求遵循相同路径:
- 框架收到一个HTTP请求
- Router匹配请求和Controller、Action,执行动作方法。
- 应用代码执行
- 绘制模型,呈现视图
- 动作的结果作为HTTP响应返回。
开发生命周期
使用Play开发时没有编译,打包和部署这些阶段。
代之两个不同环境:用于开发阶段的DEV模式和用户部署阶段的PROD模式。
Java源代码在运行时编译和加载,如果Java源文件在应用运行时发生改变,代码会重新编译并热加载(hot-swapped)到JVM中。模板文件也是如此。
关于DEV/PROD模式
通过application.mode配置属性切换DEV或PROD。
DEV模式下,Play会检查并在必要时热加载。
application.mode=dev
PROD模式为产品做了优化:Java源文件和模板仅编译一次。
prod.application.mode=prod
创建Form
编辑Demo\app\views\Application\index.html
- #{extends 'main.html' /}
- #{set title:'Home' /}
- <form action="@{Application.sayHello()}" method="get">
- <input type="text" name="myName"/>
- <input type="submit" value="Say Hello!"/>
- </form>
@{…}符号:请求Play自动产生调用动作--->Application.sayHello方法。
刷新浏览器
上图提示出错了,原因:引用了一个不存在的动作!
在Application.java中创建sayHello()
- package controllers;
- import play.*;
- import play.mvc.*;
- import java.util.*;
- import models.*;
- public class Application extends Controller {
- public static void index() {
- render();
- }
- //play将根据form表单的action属性调用sayHello()!
- public static void sayHello(String myName) {
- render(myName);
- }
- }
刷新页面
文本域中输入name并提交
又提示另一个错误
play.exceptions.TemplateNotFoundException: Template not found : Application/sayHello.html
由于Play渲染此动作的缺省模板(sayHello.html)时,没有找到它。
创建模板文件Demo/app/views/Application/sayHello.html
- #{extends 'main.html' /}
- #{set title:'Home' /}
- <h1>Hello ${myName ?: 'Guest'}!</h1>
- <a href="@{Application.index()}">Back to form</a>
重新输入name并提交
表单提交方式使用GET,路径:http://localhost:9000/application/sayhello?myName=Sail
Play 通过缺省规则对此路径进行捕获并解析
- <strong># Catch all
- * /{controller}/{action} {controller}.{action</strong>}
/application/sayhello Application.sayHello()
定制Rest风格的路径
在Demo\conf\routes文件的缺省规则前面,加上一行
- #Rest style URI ---add by hqh
- GET /hello Application.sayHello
即,如果form表单的action为Application.sayHello,则浏览器地址栏将以hello来标识路径!
重新提交表单
以Rest风格显示路径
http://localhost:9000/hello?myName=Sail+Huang
自定义布局
修改main.html或者创建其它模块文件,然后继承它!
添加验证
给form添加一个验证,要求name字段必填
编辑Demo\app\controllers\Application.java
- package controllers;
- import play.*;
- import play.data.validation.Required;
- import play.mvc.*;
- import java.util.*;
- import models.*;
- public class Application extends Controller {
- public static void index() {
- render();
- }
- //@Required 方法参数不能为空
- public static void sayHello(@Required String myName) {
- //检查参数是否为空
- if(validation.hasErrors()) {
- //提示错误信息,返回到页面共用户参考
- flash.error("please enter your name!");
- }
- render(myName);
- }
- }
编辑index.html,捕获错误提示信息
- #{extends 'main.html' /}
- #{set title:'Home' /}
- #{if flash.error}
- <p style="color:#c00">
- ${flash.error}
- </p>
- #{/if}
- <form action="@{Application.sayhello()}" method="get">
- <input type="text" name="myName"/>
- <input type="submit" value="Say Hello!"/>
- </form>
输入空参数,提交
OK,错误提示显示到页面!
自动化测试 selenium test
在cmd中输入play test Demo
打开浏览器,输入http://localhost:9000/@tests启动测试器
执行测试
Selenium测试用例通常写成一个html文件。
Demo/test/Application.test.html文件:
- *{ You can use plain selenium command using the selenium tag }*
- #{selenium}
- // Open the home page, and check that no error occured
- open('/')
- assertNotTitle('Application error')
- #{/selenium}
编写自己的测试。编辑测试内容:
注意:每一步测试都是基于前一步测试的结果进行的!逻辑性强!
- *{ You can use plain selenium command using the selenium tag }*
- #{selenium}
- // Open the home page, and check that no error occured
- //测试打开home页,确认响应中没有 "Application error"
- open('/')
- assertNotTitle('Application error')
- // Check that it is the form
- //测试表单页面是否存在某些信息
- assertTextPresent('The Hello world app!')
- // Submit the form
- //测试提交表单
- clickAndWait('css=input[type=submit]')
- // Check the error
- //name参数为空,应该提示什么错误信息
- assertTextPresent('please enter your name!')
- // Type the name and submit
- //给name参数赋值并提交表单
- type('css=input[type=text]', 'bob')
- clickAndWait('css=input[type=submit]')
- // Check the result
- //检查提交后的结果应该出现的内容
- assertTextPresent('The Hello world app!')
- assertTextPresent('Hello bob!')
- // Check the back link
- //使用超链接进行页面跳转
- clickAndWait('link=Back to form')
- // Home page?
- //页面跳转后,新页面中没有刚才的结果:'Hello bob!')
- assertTextNotPresent('Hello bob!')
- #{/selenium}
重新执行测试
点击selenium test下面的Application,再点击Start !