play笔记
?
注:此为个人学习笔记,内容可能有些杂乱,仅供参考。以下内容使用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);
Play?session只能保存字符串
“无共享”架构
7、模板
一个基于Groovy的强大的模板引擎,具有多层继承,定制用户标签的能力,Play框架认为JSP?&?Expression?Language模板机制很好,但是需要太多配置,吸收其模板设计,剔除配置。
8、RESTFul
众所周知的Servlet?API?和Struts其实是扭曲的,使用奇怪的API将Http协议隐藏起来,Play框架认为一个Web应用框架应该给用完整的?直接的对Http调用和使用,这其实就是RESTFul精神。
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、Render渲染页面
默认渲染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
Play描述有误?测试结果,无论继承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