`
lookdd1
  • 浏览: 47931 次
  • 性别: Icon_minigender_1
  • 来自: 日照
文章分类
社区版块
存档分类
最新评论
阅读更多
这篇帖子的内容我本来想发到 http://www.iteye.com/topic/806660这里的主贴里去的,想挽回被隐藏的命运,但我写完本贴的内容,却发现为时已晚。好吧,我承认,上一个贴的标题容易引发口水,这次我们实事求是,从代码出发,通过一个小例子较完整的介绍play!framework的开发过程:

就拿play!framwork自带的房间预订(booking)的例子吧:

1、 下载play  解压,配置环境变量
2、 打开命令行:转到合适的目录,输入Play new booking   这样,项目即生成完毕。
3、     进入项目目录中,执行play eclipsify  或者play netbeansify  这样即可将生成的项目导入到eclipse或者netbeans中。

打开项目目录我们可以看到:


解释下各个目录:
  •   app 包含所有的model,controller以及view(模板)。
  •   conf下是一个application.conf 配置文件。 
  •   lib是Play依赖的第三方jar。
  •   logs是日志 
  •   public下包含你引用的js,css以及,images等。
  •   test下所有的测试文件在此。


  这样的一个目录显然与传统的JEE目录完全不一样,事实上,它已经摒弃了servlet,jsp那些东西,而完全自己实现了HTTP,您会问,那它是不是无法正常运行于标准的servlet容器中,请不要担心,我们在开发完成后可以使用命令play war –odir  这个命令生成可以正常运行于servlet容器中的项目目录。
  Play分为开发模式和生产模式两种,而切换的配置在application.conf中:
  Application.mode=dev 生产模式请改为:prod
  主要区别在于开发模式中您无需重启server,每次请求都会查看是否有文件发生改变,改变即编译,这对于传统Java EE开发人员无疑是相当敏捷的。而这种方式同样会导致性能下降,所以生产模式中就不会这样了,而是采用预编译机制。
 
  下面开始coding:
  按照OO的开发模式 首先编写模型层:
  在app包下新建类Hotel.java 继承Model ,如下:
 
@Entity
  public class Hotel extends Model {
    
    @Required
    public String name;
    public String address;
    public String city;
    
    …..省略部分字段

    @Column(precision=6, scale=2)
    public BigDecimal price;

    public String toString() {
        return "Hotel(" + name + "," + address + "," + city + "," + zip + ")";
    }
    
   }

   其中继承Model基类实现了一个富血的Domain Model(这不是比传统的PO更加OO ?),完全基于JPA,上手非常简单

   同样Booking类:
  
   @Entity
   public class Booking extends Model {
    
    @Required
    @ManyToOne
    public User user;
    
    @Required
    @ManyToOne
    public Hotel hotel;
    
    @Required
    @Temporal(TemporalType.DATE) 
    public Date checkinDate;
    
    @Required
    @Temporal(TemporalType.DATE)
    public Date checkoutDate;
    
    @Required(message="Credit card number is required")
    @Match(value="^\\d{16}$", message="Credit card number must be numeric and 16 digits long")
    public String creditCard;
    
    @Required(message="Credit card name is required")
    public String creditCardName;
    public int creditCardExpiryMonth;
    public int creditCardExpiryYear;
    public boolean smoking;
    public int beds;

    public Booking(Hotel hotel, User user) {
        this.hotel = hotel;
        this.user = user;
    }
   
    public BigDecimal getTotal() {
        return hotel.price.multiply( new BigDecimal( getNights() ) );
    }

    public int getNights() {
        return (int) ( checkoutDate.getTime() - checkinDate.getTime() ) / 1000 / 60 / 60 / 24;
    }

    public String getDescription() {
        DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
        return hotel==null ? null : hotel.name + 
            ", " + df.format( checkinDate ) + 
            " to " + df.format( checkoutDate );
    }

    public String toString() {
        return "Booking(" + user + ","+ hotel + ")";
    }

    }


   User类 类似,不再给出。

   编写Controller  在controller包中编写类:Hotels  继承Controller(这儿Application继承Controller)
   
   public class Hotels extends Application {
    @Before//拦截器
    static void checkUser() {
        if(connected() == null) {
            flash.error("Please log in first");
            Application.index();
        }
    }
    public static void index() {
        List<Booking> bookings = Booking.find("byUser", connected()).fetch();//这句是不是更加面向对象?
        render(bookings);
    }

    public static void list(String search, Integer size, Integer page) {
        List<Hotel> hotels = null;
        page = page != null ? page : 1;
        if(search.trim().length() == 0) {
            //分页的代码是不是很简单?链式调用更加方便
            hotels = Hotel.all().fetch(page, size);
        } else {
            search = search.toLowerCase();
            hotels = Hotel.find("lower(name) like ? OR lower(city) like ?", "%"+search+"%", "%"+search+"%").fetch(page, size);
        }
        
        render(hotels, search, size, page);
    }
    
    public static void book(Long id) {
        Hotel hotel = Hotel.findById(id);
        render(hotel);
    }
    
    public static void confirmBooking(Long id, Booking booking) {
        Hotel hotel = Hotel.findById(id);
        booking.hotel = hotel;
        booking.user = connected();
        validation.valid(booking);
        
        // Errors or revise
        if(validation.hasErrors() || params.get("revise") != null) {
            render("@book", hotel, booking);
        }
        
        // Confirm
        if(params.get("confirm") != null) {
            booking.save();
            flash.success("Thank you, %s, your confimation number for %s is %s", connected().name, hotel.name, booking.id);
            index();
        }
        
        // Display booking
        render(hotel, booking);
    }
        
    public static void saveSettings(String password, String verifyPassword) {
        User connected = connected();
        connected.password = password;
        validation.valid(connected);
        validation.required(verifyPassword);
        validation.equals(verifyPassword, password).message("Your password doesn't match");
        if(validation.hasErrors()) {
            render("@settings", connected, verifyPassword);
        }
        connected.save();
        flash.success("Password updated");
        index();
    }
    
}


   上面的代码中展示了
1.@before 这个注解基本就是个拦截器的意思,所有访问这个Controler方法的请求都会先执行@before方法。
2、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)方法。
  上面没有展示文件上传的代码:我再贴一个文件上传的代码:
  
  public static void save(Picture picture,File pic){
	
        File uploadFile=new    File(Play.applicationPath.getAbsoluteFile()+”/public/uploads”); 
	play.libs.Files.copy(pic,uploadFile);
	picture.url =path;
	picture.save();
	QZ_Admin.pictures();
}


  其它的Controller不再给出

  这儿会有同学问,我没有配置和URL映射规则啊。事实上,play借鉴rails默认大于配置的思想,默认的映射规则是/Controller/method?params  这种。当然您也可以在配置文件routes中重新设定您所需要的映射规则。同时模板的位置默认也和Controller的名字有很大关系,比如这人我们Controller的名字叫Hotels  方法名是Index  那如果您不指定渲染模板的话默认play会去views 下面的Hotels文件夹下找index.html模板。这种约定是不是限制了很多东西?会不会对开发造成一些影响,我个人认为是有的,由于和Controller,method的名字关系密切,这需要你良好的规划,以保证你的项目目录的合理,以及URL的优雅。

   最后是编写模板:
   在views  下面建立文件夹 Hotels  新建文件index.html

  
   #{extends 'main.html' /}///在views文件夹下面编写main.html一般为网站所有页面的公共部分,比如header和footer
   #{set title:'Search' /}//为每一个页面设置title  在Main.html有变量title
    <table>
       <thead>
           <tr>
               <th>Name</th>
               <th>Address</th>
               <th>City, State</th>
               <th>Check in</th>
               <th>Check out</th>
               <th>Confirmation number</th>
               <th>Action</th>
           </tr>
       </thead>
       <tbody>
           #{list bookings, as:'booking'}  //遍历
               <tr>
                   <td>${booking.hotel.name}</td>
                   <td>${booking.hotel.address}</td>
                   <td>${booking.hotel.city},${booking.hotel.state}, ${booking.hotel.country}</td>
                   <td>${booking.checkinDate.format('yyyy-MM-dd')}</td>
                   <td>${booking.checkoutDate.format('yyyy-MM-dd')}</td>
                   <td>${booking.id}</td>
                   <td>
                        #{a @cancelBooking(booking.id)}Cancel#{/a}
                   </td>
               </tr>
           #{/list}
       </tbody>
   </table>


  这样,一个简单的模板页面就编写完成了。Play的模板相较于jsp或者JSTL以及struts2标签啥的都更加简单,也没有freemarker 空指针异常(可能有童鞋喜欢这个)这些问题。具体其它的用法可以参看play的帮助文档。


以上基本上就把play的大体用法说完了,现在我再写下play其它让人心动的地方:
1、 缓存支持:
2、	public static void showProduct(String id) {
3、	    Product product = Cache.get("product_" + id, Product.class);
4、	    if(product == null) {
5、	        product = Product.findById(id);
6、	        Cache.set("product_" + id, product, "30mn");
7、	    }
8、	    render(product);
9、	}


而您可以使用EhCache或者Memcached作为缓存的实现。使用起来非常方便

2、 JOB支持:
3、	@Every("1h")
4、	public class Bootstrap extends Job {
5、	    
6、	    public void doJob() {
7、	        List<User> newUsers = User.find("newAccount = true").fetch();
8、	        for(User user : newUsers) {
9、	            Notifier.sayWelcome(user);
10、	        }
11、	    }
12、	    
13、	}

这段代码即会每1小时运行一次。

3、 Email支持:
4、	Template t =TemplateLoader.load("UserCenter/mailTemplate.html");//邮件模板  
5、	Scope.RenderArgs templateBinding = Scope.RenderArgs.current();  
6、	templateBinding.put("url","http;//url"));  
7、	String result =t.render(templateBinding.data);        
8、	Mail.send("from@163.com", "to@163.com", "",result,"text/html")  

以上即是使用模板发送邮件的例子。当然您需要在application.conf指定发邮件的一些参数

4、非常多的好用的module:比如支持lucene的search-module ,MongoDB module,GAE module,Excel Module,GWT Module,PDF Module等等。


以上大体介绍了play!framework的开发示例以及一些基本特点。大家可以讨论下你对Play!framework看法,但请勿鄙视一把走人,或者发表带有人身攻击的言论,谢谢!






  • 大小: 23 KB
分享到:
评论
59 楼 Spirit_eye 2013-06-07  
我是来看评论的
58 楼 C_J 2011-03-15  
1.我还是觉得痛苦。

2.ThreadLocal貌似是各自的Thread用map存储Object的副本,难道对于Class.xxx有用?
57 楼 lookdd1 2011-03-14  
C_J 写道
看完之后就2点体会:

1、编写index.html模版,以前用struct的标签来写,现在又得重新学习Play的语法?我觉得有点痛苦。

2、继承xxx,无所谓,不继承你的xxx,估计我也得继承我的xxx,那么Controller里的static如何来保证线程安全呢?

谢谢



这么长时间的帖子也被你扒拉出来了。呵呵。。看来关注play的人还是有滴。。。

第一个:搞我们这行,怕学习的"痛苦"就么法进步。。。当你学习完play的模版标签你会感叹struts标签那是搞的些啥玩意啊。。况且,学习play模版的标签估计用不了一天时间吧,看一遍官方的帮助文档基本就OK了。。

第二个:涉及全局数据存取(如在request,response,flash,session等)这些中是使用的TreadLocal实现的线程安全。而我们不会定义其它的全局变量。这样就没有什么问题了。具体可以看看Play Controller的源代码。呵呵。不知道表述的是否正确 
56 楼 C_J 2011-03-14  
看完之后就2点体会:

1、编写index.html模版,以前用struct的标签来写,现在又得重新学习Play的语法?我觉得有点痛苦。

2、继承xxx,无所谓,不继承你的xxx,估计我也得继承我的xxx,那么Controller里的static如何来保证线程安全呢?

谢谢
55 楼 okjacky 2010-11-19  
还不太明白继续学习中。
54 楼 zdmcjm 2010-11-12  
play!的定位是快速开发网站,是开发诸如企业首页吗?那用asp,php,rails都比这四不像好呀。
53 楼 tapestry1122 2010-11-12  
store88 写道
thinkx 写道

play!在model中用hack的方式生成getter和setter,除了能少敲点代码,看不出有什么好处,现在任何一个java ide都可以生成getter/setter


直接public了, 没有用getter setter哦
呵呵

你看play的源代码就知道了,他在运行的时候通过cglib生成的
包括你的model类,很多都是运行时通过bytecode动态注入的

play的定位就是快速开发网站的而不是啥企业级开发
52 楼 store88 2010-11-12  
thinkx 写道

play!在model中用hack的方式生成getter和setter,除了能少敲点代码,看不出有什么好处,现在任何一个java ide都可以生成getter/setter


直接public了, 没有用getter setter哦
呵呵
51 楼 zcq100 2010-11-12  
做互联网应用还是需要快捷,Java更适合企业项目用,觉得这个框架别扭的可以直接来学习rails
50 楼 thinkx 2010-11-12  
每种语言都有各自的特性,java这种鼓励OO的静态语言中,模仿太多动态语言的东西的确没好处。
play!在model中用hack的方式生成getter和setter,除了能少敲点代码,看不出有什么好处,现在任何一个java ide都可以生成getter/setter;在controller中使用static倒是没大问题的,很简洁;至于充血和贫血倒是各有好处。我的感觉是play!的定位是用java简单的开发web应用,甚至是不用IDE只用Editor开发。不过话说在web开发领域java比动态语言唯一的优势就是执行效率了,但那东西真的这么重要么。java开发web应用还是活在企业领域里更合适吧。
49 楼 vb2005xu 2010-11-12  
请大家明确一点,Play确实不是用来做企业应用的好东西,但是在快速web网站开发,专指网站这块,确实很棒.... play做且做好了一件事情,就是web网站开发...

做企业应用的就不咋的...

48 楼 vb2005xu 2010-11-12  
http://vb2005xu.iteye.com/blog/795607 我写的 play入门基础
47 楼 yangguo 2010-11-12  
pangbuddy 写道
为什么log文件夹要用复数logs, 而其他文件夹没有同样命名?


can't you see webapps?
46 楼 pangbuddy 2010-11-12  
为什么log文件夹要用复数logs, 而其他文件夹没有同样命名?
45 楼 finalfanny 2010-11-11  
讲的不错,正在学习play!中,觉得蛮不错的,谢谢
44 楼 skyfen 2010-11-11  
艹,从来就不看好java,ADODB,以前是漏洞大王,现在java却成了漏洞大王。真是世事难料啊。SUN的落幕,Orcale能撑起Java的天空吗?
43 楼 ray_linn 2010-11-11  
易卡螺丝君 写道
请问什么是duck type

c++算你妹的动态语言?


扯犊子吧你,人家说mixin,你扯到鸭子类型。。。。


mixin就是等同于多根继承,难不成还是新的创造啊?


鸭子类型--》传个函数指针就完事了呗,嘛事不能用一根指针搞定? void** 万能无敌
42 楼 ray_linn 2010-11-11  
night_stalker 写道
C/C++ 程序静态数据区大小有限制,所以有 static 内容太多会把栈空间压小的说法。
但是 java 程序里写多少 static 关系不大的,static 内容往往不存在静态数据区而是驻留在 perm gen 里 …… 另外 C/C++ 程序也是可以调栈大小的 ……

java 可以做元编程但是繁琐得要命,所以,就和不能元编程没什么区别。



静态语言里元编程超强的当属nemerla了,.NET家族的,函数和oo双吃,不但能造词,还能轻松造句,ruby也只能望尘兴叹。。


热切等待nemerla 1.0啊
41 楼 易卡螺丝君 2010-11-10  
mathgl 写道
logicgate 写道
yangguo 写道
易卡螺丝君 写道
没有mixin 不支持元编程的单根继承 就是在自寻死路


盲目mixin就是盲目迷信,才是真的自寻死路。
C++er,请你们到csdn去自我感觉良好。


人家是rubyer.
metaprogramming用起来极爽,可以开发出非常强大的框架。


那mixin 和 c++里面的multiple inheritance 类似的东西。。不过这玩意在c++里面也不是都用。。

也就在qt里面用得比较多....其他的时候 更多是作为interface来处理的。


又一个不懂装x的 动态语言 要你妹的interface 要你妹的多继承
请问什么是duck type

c++算你妹的动态语言?
40 楼 mathgl 2010-11-10  
night_stalker 写道
C/C++ 程序静态数据区大小有限制,所以有 static 内容太多会把栈空间压小的说法。
但是 java 程序里写多少 static 关系不大的,static 内容往往不存在静态数据区而是驻留在 perm gen 里 …… 另外 C/C++ 程序也是可以调栈大小的 ……

java 可以做元编程但是繁琐得要命,所以,就和不能元编程没什么区别。


java的meta programming不是繁琐。。是萎缩...

相关推荐

    Learning Play!Framework 2

    ### 学习Play! Framework 2 的核心知识点 #### 一、Play! Framework 2 概述 Play! Framework 2 是一个用于构建现代 web 应用程序的高性能、轻量级框架。它由 Java 和 Scala 支持,并且特别强调开发者的生产力。...

    play framework api,play! framework api,play api

    在描述中提到的"play framework api,play! framework api,play api"都是指Play Framework的API文档,它包含了框架的所有公共类、方法和接口,供开发者在编写代码时查阅和引用。API文档是理解框架工作原理、学习如何...

    play!framework框架——japid源码

    **Play! Framework框架与Japid源码解析** 在软件开发领域,使用高效的框架可以极大地提升开发效率和代码质量。Play! Framework是一个流行的Java Web应用程序框架,它采用模型-视图-控制器(MVC)架构模式,支持敏捷...

    play!framework_api

    一个优于RoR的快速开发框架playframework,完全面向对象,基于jvm的REST框架,文档非常少,上手很容易,从名字上可以看出play就是玩,可以当作游戏一样轻松的玩的框架,这是它的API文档,网页格式.

    让Play!Framework运行在OpenShift上

    NULL 博文链接:https://modun.iteye.com/blog/1595857

    Play Framework2本教程

    Play Framework2是一个强大的Java和Scala应用开发框架,它以其简洁的API、快速的开发周期以及对Web标准的紧密集成而闻名。本教程旨在为初学者和有经验的开发者提供全面的指导,帮助他们掌握Play Framework2的核心...

    play1-maven-test-projects:玩! Framework 1.x Maven插件-测试项目

    在本例中,"play1-maven-test-projects"是一个针对Play! Framework 1.x版本的Maven插件测试项目。 Play! Framework是一个开源的应用程序框架,用于快速开发基于Java和Scala的Web应用。它提供了模型-视图-控制器...

    LearningPlayFramework2.pdf 英文原版

    Learning Play Framework 2

    playframework中文教程.zip

    Play Framework 是一个开源的Web应用框架,主要针对Java和Scala开发者设计,它的核心理念是简化开发流程,提高开发效率,并且特别强调了RESTful架构风格。这个“playframework中文教程.zip”压缩包很可能是为了帮助...

    Play Framework Cookbook.pdf

    ### Play Framework Cookbook 知识点解析 #### 一、Play Framework 概览 - **框架简介**:Play Framework 是一个开源的 Web 开发框架,基于 Java 和 Scala 编程语言。它采用轻量级、非阻塞的服务端架构,特别适合...

    Play framework框架

    Play Framework框架 Play Framework框架是一种基于Java的软件框架,旨在提高开发效率和提供REST式的架构风格。该框架可以让开发者继续使用他们喜欢的开发环境或繻库,不需要切换到另一种语言、IDE或者其他繻库。 ...

    Play-Framework-ElasticSearch-Module

    对于使用Play! Framework 1.1.1或更早版本的开发者,安装过程分为两步: 1. **模块安装**:通过Play的模块仓库安装elasticsearch模块。 ``` play install elasticsearch ``` 2. **配置添加**:在`conf/...

    play,play framework资料大全

    其次,是《对play!的CRUD的一次改造MyCRUD.java》。CRUD(创建、读取、更新、删除)是任何数据库驱动的应用程序中最基本的操作。这个文件可能是展示如何在Play Framework中自定义和优化这些操作的一个示例。开发者...

    play1-maven-plugin:玩! Framework 1.x Maven插件

    Framework 1.x版本的构建工具,它使得在Maven环境下管理、构建和部署Play!应用变得更加便捷。Maven是一个广泛使用的Java项目管理工具,它通过XML配置来管理项目依赖、构建过程以及发布工件。将Play! Framework与...

    play framework2.01 part1

    play framework2.01上半部分。

    对play!的CRUD的一次改造

    对play!的CRUD 进行改造,改代码还会持续重构,并不完善。 1.将create,show,delete,list都改成@Util方法,可以类似 public static void show(String id){ MyCRUD.show(id); } 的方式调用。更通用。 2.增加@...

    Play Framework

    1. Play Framework 介绍 2. 创建和发布 Play 应用 2.1 创建 Play 的工程 2.2 Play 常用指令 2.3 Play 应用的 JVM 调优 3. 如何读取静态资源 4. Play框架的配置文件 5. 使用 Play 框架开发 Java 应用 5.1 HTTP...

Global site tag (gtag.js) - Google Analytics