Play framework横空出世

颠覆臃肿的JavaEE开发框架(bloated Enterprise Java stacks)的Play框架1.0发布,它在很多方面有其革命性的独创,也有助于我们了解现在JavaEE框架的不足。

Play框架吸收PHP RUBY动态语言的特点,采取即时源码编写,即时激活,框架本身融合了编译器和服务器。取代了 compile-package-deploy 过程,提高产品的开发效率。Play框架甚至提供在线编辑器,在线修改BUG后即时投入应用。

其架构有如下特点:
1. Simple stateless MVC architecture 简单的无状态MVC架构

Play框架认为一边是数据库保存状态,一边是浏览器也可以保存状态,那么还要中间件MVC保存Session状态干什么呢?

HttpSession有很多问题,虽然可以处理针对某个用户的状态,但是万一用户中途离开怎么办,HttpSession对资源消耗,以及在可伸缩性方面是有问题的。

Play框架秉承share nothing架构思想,不再象黑客那样破解原本自然正常Http模型,然后强行植入状态,无状态架构可以并行同时输出多个页面,提高Web性能。

2 。HTTP-to-code mapping
众所周知的Servlet API 和Struts其实是扭曲的,使用奇怪的API将Http协议隐藏起来,Play框架认为一个Web应用框架应该给用完整的 直接的对Http调用和使用,这其实就是RESTFul精神。

这样 URI是play framework的主要概念。

对一个Java对象的调用,不是写Java语句,而是使用URI就可以,如下:
GET /clients/{id} 实际是调用Clients对象的show方法。

3.Efficient templating engine
Play框架认为JSP & Expression Language模板机制很好,但是需要太多配置,吸收其模板设计,剔除配置。对于一个有无Email的显示页面,使用JSP大概需要以下很多语句实现:


<c:choose>
<c:when test="${emails.unread != null && fn:size(emails.unread)}">
You have ${fn:size(emails.unread)} unread email(s)!
</c:when>
<c:otherwise>
You have no unread emails!
</c:otherwise>
</c:choose>

而是要Play框架则可以如下:
You have ${emails.unread ?: 'no'} ${emails.unread?.pluralize('email')} !

4.JPA on steroids
Play框架采取JPA作为持久化,并且使其更方便使用。


public void messages(int page) {
User connectedUser = User.find("byEmail", connected());
List<Message> messages = Message.find(
"user = ? and read = false order by date desc",
connectedUser
).from(page * 10).fetch(10);
render(connectedUser, messages);
}

个人意见:这段代码倒是直接将持久层和表现层直接耦合在一起,没看到Domain Model了。看来DDD需要普及到每个角落不容易啊。

5.Integrated Cache support, with easy use of the distributed memcached system if needed.
整合了缓存支持,可以使用memcached作为分布式缓存。

6.融入了OpenID 这样单点登录SSO技术。

7.提出Application modularization,可以重用各种组件,包括CSS Javascript

个人点评:总体来说,Play框架是一个与Struts2 JSF Tapestry竞争的框架,但是又整合了持久层和服务器,它的强项在其前半部,也就是展现层,作为一个打包整合的框架,没有强大的Domain层,是非常令人失望的。


Play框架网站:
http://www.playframework.org/
[该贴被banq于2009-10-21 10:23修改过]

java不需要新框架了,只需要好框架。框架的增多,只会增加学习的难度,让Java更快的走向死亡。

同道们测过play的性能吗?

浏览了一下tutorial,感觉比Grails还省事。
如果性能好的话,大家就可以跟进了(Rails开发虽省心,布署太烦了,语言应用范围也有限)。

至于Domain层不强大,这个是迟早的问题~~

框架框架框架框架框架框架
框架                      框架
框架       程序员        框架
框架                      框架
框架框架框架框架框架框架

[该贴被lazytalent于2009-10-23 13:11修改过]

用Play还不如用脚本语言去.我的观点是Java就应该用在适合的地方,而不需要让Java去追求ROR.其实Java要做到ROR的开发速度也不难,Java提供的反射,性能已经足够好了,简单的几个Java类实现约定大于配置也不难.问题在于,Java的优势是做大一点的项目,如果用脚本类的语言去做足够大的项目,维护过程会让人头疼.

Java的分层,领域模型才是更好的方式.

当然,Play这一类的,我想也包括Grails,适合只懂Java,对其他脚本没兴趣的程序设计师去开发小一点的东西.

个人觉得Play最大的特点是很容易上手,RESTFul的精神,无状态(Share nothing)的理念。banq说没有强大的Domain层,我不是太理解,因为Play里是有Model的,可以继承它提供的Model,然后就会有很多现成的静态方法可以用,如User.save()等,也不算贫血模型,不过另外有个贴子说Play的背后实现机制有点“暴力”,这个我没有看源码也不是很清楚,但这种实现绝对是用户所喜欢的,如果不得已用了“暴力”,那是因为Java的本身的不足,只要不影响系统稳定性和执行效率,封装好地“暴力”一下也可以接受。

而且,现在新的版本将支持Scala语言特性,也就是说有了函数式编程的很多优势,这样使得代码更加简洁和高效,或者你也可以选择支持LambdaJ,也是同样的简洁和高效。

所有这些,的确让人兴奋啊!

2009年12月15日 17:42 "wind13"的内容
不过另外有个贴子说Play的背后实现机制有点“暴力”

我贴一段它的“暴力”代码:

protected static void renderText(CharSequence pattern, Object... args) {
throw new RenderText(String.format(pattern.toString(), args));
}
/**
* Return a 200 OK text/xml response
* @param xml The XML string
*/

protected static void renderXml(String xml) {
throw new RenderXml(xml);
}
/**
* Return a 200 OK text/xml response
* @param xml The DOM document object
*/

protected static void renderXml(Document xml) {
throw new RenderXml(xml);
}
/**
* Return a 200 OK application/binary response
* @param is The stream to copy
*/

protected static void renderBinary(InputStream is) {
throw new RenderBinary(is, null, true);
}
/**
* Return a 200 OK application/binary response with content-disposition attachment
* @param is The stream to copy
* @param name The attachment name
*/

protected static void renderBinary(InputStream is, String name) {
throw new RenderBinary(is, name, false);
}
/**
* Return a 200 OK application/binary response
* @param file The file to copy
*/

protected static void renderBinary(File file) {
throw new RenderBinary(file);
}
/**
* Return a 200 OK application/binary response with content-disposition attachment
* @param file The file to copy
* @param name The attachment name
*/

protected static void renderBinary(File file, String name) {
throw new RenderBinary(file, name);
}
/**
* Render a 200 OK application/json response
* @param jsonString The JSON string
*/

protected static void renderJSON(String jsonString) {
throw new RenderJson(jsonString);
}
/**
* Render a 200 OK application/json response
* @param o The Java object to serialize
*/

protected static void renderJSON(Object o) {
throw new RenderJson(o);
}

render result都是通过运行时异常抛出。
[该贴被oojdon于2010-01-06 23:08修改过]

请教一个神奇的问题 我用play 然后在action的方法中调用form中的传来VO对象。 如果是public void方法 就会堆栈溢出 如果是private void 就没有问题 。如果有返回类型,就跳转页面到了这个私有的方法=,但是这里是没有页面可以显示的。 这是为什么?

史上最快Java Web framework JFinal横空出世
JFinal 是基于Java 语言的 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python等动态语言的开发效率。

JFinal有如下主要特点:

l MVC架构,设计精巧,使用方便简单

l 遵循COC原则,零配置,无xml

l ActiveRecord支持,使数据库开发极致快速方便

l 自动加载修改后的java文件,开发过程中无需重启web server

l AOP支持,拦截器配置灵活,使用简单

l Plugin体系结构,扩展方便

l 多视图支持,支持FreeMarker、JSP、Velocity

l 强大的Validator后端校验功能

l 功能齐全,拥有struts2的绝大部分功能

l 体积小仅150K,且无第三方依赖

项目首页:http://code.google.com/p/jfinal

以下是一个Blog管理的示例程序:

1:控制器(支持FreeMarker、JSP、Velocity、Json等等以及自定义视图渲染)

01
@Before(BlogInterceptor.class)
02
public class BlogController extends Controller {
03
public void index() {
04
setAttr("blogList", Blog.dao.find("select * from blog order by id asc"));
05
}
06

07
public void add() {
08
}
09

10
@Before(BlogValidator.class)
11
public void save() {
12
getModel(Blog.class).save();
13
index();
14
}
15

16
public void edit() {
17
setAttr("blog", Blog.dao.findById(getParaToInt()));
18
}
19

20
@Before(BlogValidator.class)
21
public void update() {
22
getModel(Blog.class).update();
23
index();
24
}
25

26
public void delete() {
27
Blog.dao.deleteById(getParaToInt());
28
index();
29
}
30
}

2:Model(仅一行代码,且无xml,无annotation,中间的new Blog()代码也可省去)
1
public class Blog extends Model<Blog> {
2
public static final Blog dao = new Blog();
3
}
3:Validator(API引导式校验,比xml配置方便N倍)

01
public class BlogValidator extends Validator {
02
protected void validate(Controller controller) {
03
validateRequiredString("blog.title", "titleMsg", "请输入Blog标题!");
04
validateRequiredString("blog.content", "contentMsg", "请输入Blog内容!");
05
}
06

07
protected void handleError(Controller controller) {
08
controller.keepModel(Blog.class);
09

10
String actionKey = getActionKey();
11
if (actionKey.equals("/blog/save"))
12
controller.render("add.html");
13
else if (actionKey.equals("/blog/update"))
14
controller.render("edit.html");
15
}
16
}
4:拦截器(本拦截器仅输出文字到控制台,仅是用法示例,本程序可以不需要)

view sourceprint?
1
public class BlogInterceptor implements Interceptor {
2
public void intercept(ActionInvocation ai) {
3
System.out.println("Before invoking " + ai.getActionKey());
4
ai.invoke();
5
System.out.println("After invoking " + ai.getActionKey());
6
}
7
}
JFinal QQ群:222478625

下载demo在这里 http://www.oschina.net/p/jfinal 点击“软件下载”按钮即可