在前天的珠三角技术沙龙上,有朋友问到Play!framework是否修改了Java的类编译器,实现动态的编译,这块确实没有仔细去研究过。当时可能把Play!和一个国内牛人开发的类似项目douyu搞混了,douyu确实是通过修改javac编译器来实现的动态编译。恩,作者的说明在这里:http://zhh2009.iteye.com/blog/540417。所以模糊的回答“是修改了”,现在看来,可能误导人了,如果哥们能在这里看到,请接受俺的道歉。

Play!关于编译的代码这里: https://github.com/playframework/play/blob/master/framework/src/play/classloading/ApplicationCompiler.java ,可以清楚的看到,Play!是使用了Eclipse JDT来实现实时编译。就像我们在eclipse里编写代码时,eclipse可以实时检测到错误一样,Play!其实是利用了JDT的这个特性。使用自定义的classloader来检测源文件修改,然后使用JDT进行实时的编译和替换,并没有修改javac编译器。同时,由于Play!具有无状态的特性,可以直接卸载controller类,然后重新载入,与基于传统MVC框架使用JRebel来实现的动态编译相比,可以获得更好的用户体验。

另外,当时现场有位帅哥补充的,关于使用javassist来实现字节码增强,比如为model类增加setter/getter实现javabean规范,Play!确实是这么干的,也是其实现动态编译的一部分。

 

通过5个实例来体现Play框架背后的哲学

1.绑定HTTP参数到java方法参数

在Play框架中,获取http参数是非常容易的事情。只需要将方法参数名与HTTP参数名一致就行了。
比如下面的HTTP请求:

/articles/archive?date=08/01/08&page=2

只需要在java方法中定义两个名为date和page的参数就可以了

public static void archive(Date date, Integer page) {
    List articles = Articles.fromArchive(date, page);
    render(articles);
}

Play会自动将HTTP参数转换为方法参数的类型
同样,还可以绑定到java对象类型,比如这样一个对象:

public class Person {
    public String name;
    public Integer age;
}

一个保存人员的方法只需要这样写:

public static void add(Person p) {
    p.save();
}

相应的HTML表单代码:

<form action="/Directory/add" method="POST">
    Name: <input name="p.name" type="text" />
    Age: <input name="p.age" type="text" />
</form>

2.通过调用相应的java方法实现操作跳转

在Play里面没有JavaServlet的forward方法,但跳转到其他的方法仍然是十分简单。只需要调用相应的java方法,Play会自动生成HTTP跳转的响应。

public static void show(Long id) {
    Article article = Article.findById(id);
    render(article);
}
 
public static void edit(Long id, String title) {
    Article article = Article.findById(id);
    article.title = title;
    article.save();
    show(id);
}

在edit方法的最后,调用了show方法,这会产生一个HTTP 302跳转,可有效的避免表单重复提交。
在任何模板文件中,可以使用相同的语法来生成这个链接:

<a href="@{Article.show(article.id)}">${article.title}</a>

生成的HTML代码如下:

<a href="/articles/15">My new article</a>

3.传递java对象到模板中

在大多数的Java框架中,需要类似下面方法来传递Java对象到模板中:

Article article = Article.findById(id);
User user = User.getConnected();
Map<String, Object> model = new HashMap<String,Object>();
model.put("article", article);
model.put("user", user);
render(model);

使用Play框架,你只需要这样写:

Article article = Article.findById(id);
User user = User.getConnected();
render(article, user);

模板中可以直接使用变量名称来获取对象值,减少大量无用的代码

4.增强的JPA支持

JPA可以说是Java里面最好的的对象-关系映射(ORM)API,Play更是将JPA的支持简化到了极致。不需要任何的配置,Play就会自动启动基于Hibernate的JPA实体管理器,而且在代码重载的时候自动神奇的同步。
如果你使用框架提供的play.db.jpa.Model基类,将会使代码更加简洁:

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

4.文件上传

直接上代码吧!
表单:

#{form @uploadPhoto(), enctype:'multipart/form-data'}
    <input type="text" name="title" />
    <input type="file" id="photo" name="photo" />
    <input type="submit" value="Send it..." />
#{/}

Java代码

public static void uploadPhoto(String title, File photo) {
   ...
}

还有比这更简单的吗?

原文:http://www.playframework.org/documentation/1.2.1/5things

 

用了有一阵cloudflare服务了,确实是值得推荐的好东东。

你可以把它看做免费的:

  1. DNS管理器:
    首先 CF会要求你在域名注册商那里将DNS服务器设置成CF提供的一组服务器。这个是其他所有服务的基础,当然,也具有所有DNS Server的功能了,你可以在这里配置A记录、MX记录、转发等。而且界面非常好用哦。
  2. 反向代理
    只要在DNS管理界面激活那朵黄色的小云朵,就启动了反向代理服务了(仅对A记录,CNAME转发有效),生效后去ping一下你的域名(以前要24小时才能生效,现在貌似几分钟就OK了),会发现被CNAME到一个特殊的域名去了。比如俺这个就是cf-protected-www.021128.net。
    通过CF的反向代理的域名,至少有两个好处,一是自动缓存,减轻站点的访问压力,在后端主机宕机时,还能自动将缓存的内容提供给用户。二是借助CF的CDN系统,可以减少各地区网速的影响,起到提速的效果。不过CF的CDN都在国外,对国内的网速可能反而有副作用。
    对天朝用户来说,反向代理可能更具有一些独特的意义。比如GAE等被墙的服务就看到希望了,你懂的。。。
  3. 云端防火墙
    由于反向代理的存在,你的主机就不会直接暴露给最终用户了,这可以看做一层防火墙了。而且CF还有入侵检测,对可疑的请求,会使用captcha技术进行验证。还有设置黑名单白名单等功能。
  4. 其他扩展增强
    基于反向代理,CF还做了很多有意思的扩展。比如,自动js/css代码压缩、访问统计分析、与Google analytics集成等
 

有一个多模块的web应用,基本布局如下:

+ app
   - app-web
   - app-core

app-web把app-core作为依赖,并且使用jetty-maven-plugin(7.2.2.v20101205)作为web容器进行调试,并且使用m2eclipse来启动jetty:run任务,启动的同时,选中了resolve workspace artifacts选项,将app-core项目中的最新的代码作为运行时的代码,而不是maven仓库中的最新snapshot版,目的是希望修改app-core后,不需要再install,也可以让jetty载入最新的代码,减少不必要的繁琐操作。

现在遇到的问题是,如果我修改了app-web下面的类,jetty可以及时的检测到,自动重启容器。
如果修改了app-core下面的类,则必须install到本地仓库以后,才能被jetty检测到,很麻烦。

最后找到的解决方法是,使用m2eclipse内置的3.0版本maven,或者使用外部的2.2.1版本maven(BUG,吐血啊。。。。)

相关的讨论在这里:
https://issues.sonatype.org/browse/MNGECLIPSE-2655
https://issues.sonatype.org/browse/MNGECLIPSE-2676

 

Play框架是臃肿的企业Java技术的一个简洁版替代品.基于RESTful架构,关注开发者的生产率.是敏捷软件开发的完美伴侣.

Play框架的目标就是减少使用Java进行Web应用开发时的痛苦.下面来看看是如何做到的.

一个无痛的Java框架

Play是一个纯Java的框架,你可以继续使用喜欢的开发工具和代码库.如果你已经是java平台的开发者,你不需要学习其他的语言、IDE和代码库。只是换成一个更具有生产力的Java环境而已。

修改bug,立刻看到效果

Java平台常以低生产率而被诟病,主要原因是重复而单调的编译-打包-部署过程。

这也是我们考虑重建开发流程,并为Play创造了一个更有效率的开发过程的原因。

框架直接编译你的Java源代码,热重载到JVM中,而无需重启服务。你可以编辑、刷新,即可立即看到你的修改效果了,就像在LAMP或Rails环境中一样。

如果愿意,你可以抛弃臃肿的Java集成开发环境,使用简单的文本编辑器就可以工作了,非常有意思!

如果出现了一个错误,框架将尽最大可能识别这个错误,并用友好的方式将错误信息显示出来。

错误堆栈跟踪被精简和优化过了,解决问题更加容易。看看模板的执行和Java的堆栈跟踪是如何优雅的集成在一起的吧:

简单的无状态MVC架构

既然数据库和web浏览器分别位于网络的两端,那为何一定要在两者之间保持状态呢?

虽然组件化的有状态JavaWeb框架通过自动保存页面状态简化了此需求的实现,但同时也带来了很多其他的问题:当用户打开第二个窗口时会发生什么?如果用户点击浏览器的后退按钮呢?

啥都不共享的架构(Share Nothing architecture)是从PHP、Rbuy、Ruby On Rails、Django等许多Web应用框架所推崇的。由于浏览器端变得越来越强大,现在,通过Ajax或离线存储等客户端技术来维护状态是非常容易的。

我们不需要修改包装HTTP模型来重建一个Web上的伪状态模型。“啥都不共享”架构的另一个好处是,可以更加容易的使页面各部分并发渲染,然后局部刷新(或局部增强)。

HTTP到代码的映射

如果你用过Servlet API或Struts之类的Java Web框架,你已经通过奇怪的Java API和概念使用了其对HTTP协议的抽象。而我们则认为,一个Web应用框架应该提供一个完整、直接的方式来访问HTTP和相关概念。这是Play和其他Java Web应用程序框架在根本上的不同。

HTTP,请求/响应模式,REST架构风格,内容类型协商,URI是Play框架的所有主要概念。

举例来说,绑定一个URI模式到Java调用只需要一行

GET    /clients/{id}        Clients.show

如果你在日常的web开发中经常遇到Ajax,REST、管理页面间的后退/前进等问题,那不妨试一试Play。

高效的模板引擎

我们喜欢JSP和表达式语言背后的思想。但我们为什么需要大量的配置文件才能创建一个标签库?我们为什么不能完全的访问背后的对象模型?JSP有大量的限制而且确实容易让人烦躁。这就是我们创建一个新模板系统的初衷:基于JSP的灵感,但没有JSP的限制。

你可能写过类似下面的代码:

&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;
&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %&gt;
 
        You have ${fn:size(emails.unread)} unread email(s)!
 
        You have no unread emails!

我想你可能更愿意这样写:

You have ${emails.unread ?: 'no'} ${emails.unread?.pluralize('email')} !

Play的模板引擎使用的表达式语言是Groovy,提供了与Java一致的语法。Play主要使用此模板系统来渲染HTML响应,你也可以用它来生成任何其他的文档,比如e-mail信息,JSON响应等。

加强的JPA

Java持久化API(JPA)是Java世界中最清晰的对象-关系映射API。如果你已经知道JPA,你将会惊讶于Play将其变得更加简单。不需要任何的配置,Play就会自动启动JPA实体管理器,并在代码重载时神奇的进行自动同步。
更进一步,如果你使用框架提供的play.db.jpa.Model基类,会使你的代码更加的简洁。比如:

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

测试驱动开发(如果你喜欢)

框架整合的测试运行器让你可以更加容易的开展测试驱动的开发(TDD)。你可以编写各种类型的测试,从简单的单元测试到完整的验收测试,然后使用Selenium直接在浏览器中运行它们。代码覆盖率也被会自动计算出来。

完整的应用框架栈

Play框架受我们已有的Java应用灵感启发。具有创建现代web应用所需的所有工具,包括:

  • 基于JDBC的关系型数据库支持
  • 基于Hibernate的ORM(通过JPA API)
  • 集成缓存支持,如果需要使用分布式memcached系统也非常容易
  • 直接的web service消费支持,包括JSON或XML(我们这里指的是真实世界的web service,而不是SOAP之类的东西)
  • 分布式认证OpenID支持
  • 你的应用可以部署到任何地方(应用服务器、Google App Engine,云,等等…)
  • 图片处理API
  • 模块化架构使你可以和其他人一起组合创建web应用程序。感谢应用模块,你可以通过简单的方式重用你的Java代码、模板和静态资源(例如JavaScript和CSS文件)

原文:http://www.playframework.org/documentation/1.2.1/overview

 

自从选择了做java程序猿啊!!!!!!!
于是走上了不归路啊!!!!!!!!!!
一堆的框架要学啊!!!!!!!!!!!
一堆的配置要写啊!!!!!!!!!!
启动个WAS要半小时啊!!!!!!!
改个BUG还要重启啊!!!!!!!!!
RAD、Eclipse动不动就卡得要死啊!!!!!
写个增删改也要一堆的接口实现设计模式啊!!!
看着人家Ruby程序猿羡慕嫉妒恨啊!!!!!
有木有!!!!!有木有!!!!!!!!
做java的程序猿你伤不起啊啊!!!!!!!
大神们终于看不下去了啊!!!!!!!
放出神器来拯救世界啊!!!!!!!!

咆哮完毕,就请我们的神器隆重登场吧~~~~~
我们今天的猪脚就是~~~~~
Playframework~~
像玩一样编程, 传说中有了它,放个猴子在电脑前都会编程了!

先来看看他都有神马本领:

  • 实时编译,不需重启,写好java代码,F5刷新浏览器就能看到结果!
  • 完善的应用框架,从表现层到持久层完整的支持,忘记SSH吧!
  • 约定优于配置,让繁琐的配置文件见鬼去吧!
  • 依赖管理支持,直接使用maven仓库里丰富的第三方组件!
  • 简洁的HTTP数据绑定,终于可以扔掉FormBean这种恶心的东西了!
  • 强大的工具类库,简化一切繁琐的传统问题:XML、WebService、安全认证、定时任务、缓存、邮件、AJAX……
  • 组件支持,安装新的模块,只需要一个命令!
  • CRUD框架支持,不需代码生成即可获得增删改查支持!
  • 丰富文档,与应用一体化!
  • 还不够?!那就自己安装一个慢慢体会吧!

再来五个很酷的片段,展示一下play的哲学:

1.绑定HTTP参数到java方法参数

在Play框架中,获取http参数是非常容易的事情。只需要将方法参数名与HTTP参数名一致就行了。
比如下面的HTTP请求:
/articles/archive?date=08/01/08&page=2
只需要在java方法中定义两个名为date和page的参数就可以了

public static void archive(Date date, Integer page) {
    List articles = Articles.fromArchive(date, page);
    render(articles);
}

Play会自动将HTTP参数转换为方法参数的类型
同样,还可以绑定到java对象类型,比如这样一个对象:

public class Person {
    public String name;
    public Integer age;
}

一个保存人员的方法只需要这样写:

public static void add(Person p) {
    p.save();
}

相应的HTML表单代码:

<form action="/Directory/add" method="POST">
    Name: <input name="p.name" type="text" />
    Age: <input name="p.age" type="text" />
</form>

2.通过调用相应的java方法实现操作跳转

在Play里面没有JavaServlet的forward方法,但跳转到其他的方法仍然是十分简单。只需要调用相应的java方法,Play会自动生成HTTP跳转的响应。

public static void show(Long id) {
    Article article = Article.findById(id);
    render(article);
}
 
public static void edit(Long id, String title) {
    Article article = Article.findById(id);
    article.title = title;
    article.save();
    show(id);
}

在edit方法的最后,调用了show方法,这会产生一个HTTP 302跳转,可有效的避免表单重复提交。
在任何模板文件中,可以使用相同的语法来生成这个链接:

<a href="@{Article.show(article.id)}">${article.title}</a>

生成的HTML代码如下:

<a href="/articles/15">My new article</a>

3.传递java对象到模板中

在大多数的Java框架中,需要类似下面方法来传递Java对象到模板中:

Article article = Article.findById(id);
User user = User.getConnected();
Map<String, Object> model = new HashMap<String,Object>();
model.put("article", article);
model.put("user", user);
render(model);

使用Play框架,你只需要这样写:

Article article = Article.findById(id);
User user = User.getConnected();
render(article, user);

模板中可以直接使用变量名称来获取对象值,减少大量无用的代码

4.增强的JPA支持

JPA可以说是Java里面最好的的对象-关系映射(ORM)API,Play更是将JPA的支持简化到了极致。不需要任何的配置,Play就会自动启动基于Hibernate的JPA实体管理器,而且在代码重载的时候自动神奇的同步。
如果你使用框架提供的play.db.jpa.Model基类,将会使代码更加简洁:

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

4.文件上传

直接上代码吧!
表单:

#{form @uploadPhoto(), enctype:'multipart/form-data'}
    <input type="text" name="title" />
    <input type="file" id="photo" name="photo" />
    <input type="submit" value="Send it..." />
#{/}

Java代码

public static void uploadPhoto(String title, File photo) {
   ...
}

还能更简单吗?

 
以前一直没条件,用过blogger和micolog,今天才真正体验了一把Wordpress,感觉真是不错,不愧是老牌产品.
  1. 管理界面风格很现代,用起来很舒服
  2. 默认的编辑器也是优化过的,而且可以自动保存草稿,很人性化
  3. 主题和插件非常多,而且都是像AppStore一样的,直接在线搜索安装就可以了,牛
  4. 利用迁移功能很方便的就把blogger和micolog上的文章导过来了
 

前两天收到DotCloud发来的邀请码,要不是这个邮件,我差点都忘记曾经申请过这个服务了.

DotCloud应该算是目前支持技术最广泛的PaaS平台了(Amazon EC2不算啊,那玩意和VPS差不多了),目前支持的技术有这么一大堆:java,mysql,nodejs,perl,php,php-worker,postgresql,python,python-worker,rabbitmq,redis,ruby,ruby-worker,smtp,static,而且还在不断扩展中.

目前还处于试用阶段,不需要收费,也没有提到关于quota的问题,估计服务会有些不稳定吧,暂且把他作为一个免费的虚拟主机用用好了,现在这个博客就部署在这个免费虚拟主机上.

DotCloud的文档还是比较好,跟着文档一步步下来就把这个博客部署好了,基本上没什么难度,文档在这里: http://docs.dotcloud.com/tutorials/

说几点感受吧:

  1. 应用的管理和部署都是通过一个基于python的命令行来完成的,习惯*unix环境的同学非常容易上手.
  2. 部署应用可以和git/mercurial结合,还可以添加自定义postinstall脚本和nginx.conf配置
  3. 各种技术可以随意组合使用,支持的技术没有特殊API的限制,这个比GAE爽多了
  4. 简单的使用起来和自己建的VPS上体验差不多,但是省去了部署数据库\中间件等的过程,省了很多事
  5. DotCloud本身也是运行的AmazonEC2上的linux(CNAME自定义域名时发现的), 而且可以ssh连上去做一些操作(又可耻的想到翻墙了,不过还是尽量少用于fuckgfw吧,这么好的服务到时候又被墙了可惜了)
  6. 监控服务还不够完善
  7. 稳定性尚待观察

btw: 前几天VMWare的云计算平台也上线了,现在也是可以申请注册,貌似是和Spring结合得比较好,做java开发的同学有福了~~

 

有些网络环境中,openssh服务端进行dns逆向查找会导致连接速度非常慢,可以通过禁止dns逆向查找解决

修改/etc/ssh/sshd_config:

UseDNS no

 

将maven项目提交到svn时,应该避免将target目录及eclipse配置文件(.project,.classpath,.settings)提交,因为这些文件都是可以从源代码和pom文件重新生成的,没有必要再进行版本控制,如果提交到svn中反而容易引起冲突和不便.

svn提供两种机制来忽略特定文件的提交:

1.全局:这个全局其实是针对每个客户端的,编辑客户端的~/.subversion/config(*unix系统,windows可能不一样)文件,找到倍注释掉的global-ignores配置,改成需要的,如:

global-ignores= .settings .project .classpath target .DS_Store

2.针对目录的配置: 在目录上通过svn:ignore参数进行设置,只针对当前目录有效,子目录无效.

如果只是针对个人使用,那么第一种方法最方便,设置一下就不管了.如果希望其他人不用设置,svn也会忽略这些文件,就要两种方法结合起来用了.

1在自己的客户端配置global-ignores

2.提交代码:

svn mkdir --parents -m "" http://svnserver/svn/portal_proj/uuam/trunk
svn co http://svnserver/svn/portal_proj/uuam/trunk .
svn add * --depth=infinity --force
svn ci --username huzq

3.设置svn:ignore参数

svn propset -R svn:ignore ".settings
.project
.classpath
target" .
© 2012 起死回生 Suffusion theme by Sayontan Sinha

Switch to our mobile site