注:此为个人学习笔记,内容可能有些杂乱,仅供参考。
以下内容使用 play-1.2.4 版本
1、常用命令
1)、 play new < 项目名 >
2)、 play run < 项目名 >
3)、 play eclipsify < 项目名 >
4)、 play war < 项目名 > -o <war 包名,需加 .war,, 如 webplay.war --zip
生成webplay.war.war
2、在 eclipse 中调试
Play转换eclipse项目时,在eclipse目录中生成了三个启动配置:
1)、 JPDA:连接到已经启动的Play Server,实现alive调试
2)、webplay :本地运行
3)、 Test:测试
选中它们,右键执行Run As ,即可完成相应的任务。
直接Debug As 执行 webplay 会报错:
Error occurred during initialization of VM
agent library failed to init: jdwp
ERROR: Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options.
需要:
打开webplay.launch, 找到
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -Dplay.debug=yes -Dplay.id= -Dapplication.path …/>
将-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n 去掉。
然后Debug As, 即可成功启动调试。附加 Play 源码后,即可调试 Play 本身。
3、 play 模式
Play分为开发模式和生产模式两种,而切换的配置在 application.conf 中:
Application.mode=dev 生产模式请改为 :prod
主要区别在于开发模式中您无需重启server ,每次请求都会查看是否有文件发生改变,改变即编译,这对于传统 Java EE 开发人员无疑是相当敏捷的。而这种方式同样会导致性能下降,所以生产模式中就不会这样了,而是采用预编译机制。
开发模式要有第一次http 请求,才启动 application
4、 controller
controller中的几个作用域 :
1)、 session 这儿的 session 只支持您放里面放 String 类型,而不是和传统 JEE 中任何对象都可以放到 session 中。这儿的 session 和 rails 的类似。
2)、 flash 跨请求的存储对象
3)、 params 基本相当于 request.getParameters();
4)、 renderArgs 渲染到模板的数据 , 上面代码中您看到的 render 里面的就是放到了这个 renderArgs 里面了。还有个 validation 存放验证数据。
基类Controller 里定义了很多好用的方法 : 如果想使用 ajax 返回 JSON ,则使用 renderJSON() play 使用的 json 序列化工具是 gson.jar, 。想返回一个文件流 , 使用 renderBinary(File f,String name) 方法
5、工具包
play.libs.*
6、 play session
Play框架认为一边是数据库保存状态,一边是浏览器也可以保存状态,那么还要中间件 MVC 保存 Session 状态干什么呢?
HttpSession有很多问题,虽然可以处理针对某个用户的状态,但是万一用户中途离开怎么办, HttpSession 对资源消耗,以及在可伸缩性方面是有问题的。 Play 框架秉承 share nothing 架构思想,不再像黑客那样破解原本自然正常 Http 模型,然后强行植入状态,无状态架构可以并行同时输出多个页面,提高 Web 性能。
session.put(String name,String value);
String value = session.get(String name);
P lay session只能保存字符串
“无共享”架构
7、模板
一个基于Groovy 的强大的模板引擎,具有多层继承,定制用户标签的能力, Play 框架认为 JSP & Expression Language 模板机制很好,但是需要太多配置,吸收其模板设计,剔除配置。
8、 REST Ful
众所周知的Servlet API 和 Struts 其实是扭曲的,使用奇怪的 API 将 Http 协议隐藏起来, Play 框架认为一个 Web 应用框架应该给用完整的 直接的对 Http 调用和使用,这其实就是 REST Ful精神。
9、“ / ”
默认Play 认为“ / ”是很重要的,例如下面这个route ,
GET /clients Client.index
会匹配/clients 但是不会匹配 /clients/ ,你可以通过在“ / ”后加上一个问号,告诉 Play 你想让那个 route 匹配到后面的 "/" ,例如
GET / clients / ? Clients.index
URI模式不能有任何可选的部分,除了那个 "/" ( 不理解 )
10、 package
Route的最后一部分是 Java 调用定义,这部分是由一个 action 方法的全名定义的,并且这个 action 必须是一个控制器类中的静态的公共方法,控制器类必须定义在包 controllers 中且必须是 play.mvc.Controller 的子类。你可以在控制器类之前增加一个 Java 包如果它不是直接定义在 controllers 包中,包 controllers 本身是默认包含的,所以你不需要指定它。
例如:
GET / admin admin.Dashboard.index
11、 R ender渲染页面
默认渲染html 文件
views目录下对应 包名 / 类名 / 方法名 .html
在调用 render 方法之前,你可以使用编程的方式设置响应的格式。例如,为了提供一个媒体类型 media type 为 text/css 的层叠样式表,而是以你可以这样做:
request.format = "css";
但不会解析对应的文件类型,如设置request.format= ” jsp ” ,并不会解析 jsp 文件,而是以文本的形式显示出所有的源码 . 。
12、 Route
1) 定 义 一个 URL ,其中 id 指定 为 'home' ,我可以使用静 态 参数定 义 另外一个 route
GET /home Application.page(id:'home')
GET /page/{id} Application.page
当page ID 为 'home' 时,第一个 route 和第二个 route 是等价的,但是,它的优先级要高一些,当你使用 ID 'home' 调用 Application.page 时,它是默认被调用的。
2) 路由优先级
很多路由可以匹配相同的请求,如果有冲突的话,则使用第一个定义
3)长路由配置
去除routes 文件的
# Catch all
#* /{controller}/{action} {controller}.{action}
这路由配置
* /home/{id} jc.JcApplication.bye
匹配
http://127.0.0.1:9000/home/11235
13、 controller
业务逻辑代码通常位于模型(model) 层。客户端(比如浏览器)无法直接调用其中的代码,所以模型对象提供的功能,必须作为资源以 URI 方式暴露给外部。
客户端使用HTTP 协议来操作这些资源,从而调用了内部的业务逻辑。但是,这种从资源到模型之间的映射是单向的:我们可以根据需要提供不同粒度的资源,可以虚拟出一些资源,还可以给某些资源起别名 .
1) 使用@As 注解,我们可以指定日期格式。 例如
archives?from=21/12/1980
public static void articlesSince(@As("dd/MM/yyyy") Date from)
14、视图层
Web 开发框架的使用者都习惯于使用某种模板技术来生成 HTML 页面,这些技术包括常见的 JSP 、 ASP 和 PHP 等。 Play 框架也提供了自己的模板技术,可以用来动态的创建 HTML 、 XML 、 JSON 以及其它文本类型的内容。 Play 框架的模板技术使用的是 Groovy 语言。 Groovy 语言的灵活性和简洁性使得 Play 框架的模板简单而且易用。在模板中可以混用静态内容和生成动态内容的各种元素。
${ … }对一个表达式进行求值
@{ … }和 @@{ … }分别用来调用控制器中动作方法的相对 URL 和绝对 URL
&{ ‘…’ }显示经过 i18n 后的内容
*{ … }*注释
%{ … }%添加复杂的 Groovy 脚本,可以声明变量和添加语句。
#{ … }用来调用 Play 框架或是开发人员自定义的标签
#{extends ‘…’ /}和 #{doLayout /} 实现模板之间的继承
15、 i18n
zh_cn: 简体中文
zh_hk: 繁体中文 ( 中国香港 )
zh_tw: 繁体中文 ( 中国台湾地区 )
en-hk: 英语 ( 香港 )
en_us: 英语 ( 美国 )
en_gb: 英语 ( 英国 )
en_ww: 英语 ( 全球 )
ja_jp: 日语 ( 日本 )
ko_kr: 韩文 ( 韩国 )
16、 Action 链
在play 中没有 Servlet API forward 的等价物。每一个HTTP request 只能调用一个 action 。如果我们需要调用另一个,必须通过重定向,让浏览器访问另一个 URL 来访问它。这样的话,浏览器的 URL 始终与被执行的 action 保持一致,实现 Back/Forward/Refresh 的管理就容易多了 。
17、拦截器 (Interceptions)
一个controller 可以定义多个拦截器方法。拦截器作用于 一个controller 及其所有子类 的所有action 方法上。对于定义一些所有 action 共用的操作时,使用拦截器非常有用 ,这些方法必须为 static ,但不一定是 public 。
@Before
@After
@Finally
@Catch 异常,传递 Throwable 对象
@With 注解在类申明上面,可使用指定的 controller 定义的拦截方法
18、 Session 和 Flash scopes
在多个HTTP 请求之间共用数据,可以把它们保存在 Session 或 Flash 域中。保存在 Session 中的数据,对于整个 user session 都可用,而保存在 flash 域中的数据,则仅仅在下一个请求可用。在 play 中, Session和 Flash 数据并没有保存在服务器端 ,而是通过Cookie 被加入到每一个 HTTP 请求中。所以能保存的数据量非常小 ( 不超过 4KB ),并且 只能保存字符串 。
cookies都使用了一个密钥进行了加密,所以客户端无法修改 cookie 数据(否则该数据将无效)。 Play 的 session 不是用来当作数据缓存。如果我们需要缓存与 session 相关的某些数据,可以 使用Play 内置的缓存机制 Cache ,并使用 session.getId() 作为 key 来保存。
19、持久化
(1)Play当找到一个或一个以上的类有注解 @javax.persistence.Entity 会自动启动 Hibernate entity manager 。
JPA.em().createQuery( “” );
(2)事务, play 会默认自动事务管理,以一个 http 请求至响应为单位。当请求失败或响应出错,事务自动回滚。
手动设置事务管理,
JPA.setRollbackOnly() 强制事务回滚
在控制类的方法上加注解
@play.db.jpa.Transactional(readOnly=true) 设置事务为只读
@play.db.jpa.NoTransaction 不使用事务 ,play 将不会从连接池获得连接,这将提高运行速度。
(3)entites 继承 play.db.jpa.Model 用 Long id 作为主键
entites继承 play.db.jpa.GenericModel 自已使用 @Id 设置主键
@GeneratedValue @GenericGenerator 设置主键生成策略
(4)refresh() 防止实体暗自更新 , ,类似 hibernate 中的 evit(Ojbect)
(5)entites继承自 JPASupport/JPAModel ,没有显式调用 save() 则不会自动保存 ( 不推荐使用 ), 改为继承 GenericModel
P lay描述有误?测试结果,无论继承 Model 或 GenericModel 没有显示调用 save( 没有 update 方法 ) 都不会自动保存或更新
(6)自动生成表结构
继承Model 须显式声明 @Table
继承GenericModel 则只须声明 @Entity
19、 play.libs
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
20、使用 memcached
配置application.conf
# Enable memcached if needed. Otherwise a local cache is used.
memcached=enabled
#
# Specify memcached host (default to 127.0.0.1:11211)
memcached.host=127.0.0.1:11211