再说Play!framework http://hsfgo.iteye.com/blog/806974
就拿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看法,但请勿鄙视一把走人,或者发表带有人身攻击的言论,谢谢!
再说Play!framework http://hsfgo.iteye.com/blog/806974的更多相关文章
- http://chenzhou123520.iteye.com/blog/1811340
http://chenzhou123520.iteye.com/blog/1811340
- [转]http://m635674608.iteye.com/blog/1750833
转载地址:http://m635674608.iteye.com/blog/1750833 在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个 ...
- rabbitMq 转自 http://gaoyangang.iteye.com/blog/1566600
rabbitMq 转自 http://gaoyangang.iteye.com/blog/1566600
- http://jinnianshilongnian.iteye.com/blog/1996071
http://jinnianshilongnian.iteye.com/blog/1996071 http://my.oschina.net/jkcui/blog/388400 http://tian ...
- http://jinnianshilongnian.iteye.com/blog/2018936
http://jinnianshilongnian.iteye.com/blog/2018936
- http://jadethao.iteye.com/blog/1926525
http://jadethao.iteye.com/blog/1926525 ————————————————————————————————————————————————————————————— ...
- http://wsj356428476.iteye.com/blog/1655032
http://wsj356428476.iteye.com/blog/1655032 http://jingyan.baidu.com/article/19192ad83ce167e53e570705 ...
- spring mvc入门教程 转载自【http://elf8848.iteye.com/blog/875830】
目录 一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 ...
- 《C和指针(Pointer on c)》 学习笔记(转自:http://dsqiu.iteye.com/blog/1687944)
首先本文是对参考中三个连接的博客进行的整理,非常感谢三位博主的努力,每次都感叹网友的力量实在太强大了…… 第一章 快速上手 1. 在C语言中用/*和*/来注释掉这段代码,这个实际上并不是十分的安全, ...
随机推荐
- MemSQL start[c]up Round 2 - online version C. More Reclamation(博弈)
题目大意 额,写来写去,我还是直接说抽象之后的题目大意吧: 有一个 r*2 的矩形,两个人轮流的在矩形上面减去一个 1*1 的小正方形,要求在减的过程中,不能使矩形“断开”,也就是说,如果一个人减去了 ...
- Linux 下 Shell 命令的分类及用法
当你打算真正操纵好你的 Linux 系统,没有什么能比命令行界面更让你做到这一点.为了成为一个 Linux 高手,你必须能够理解 Shell命令的不同类型,并且会在终端下正确的使用它们. 在 Linu ...
- Android debug时一直处于waiting for debugger解决办法
问题:android 调试卡在:Waiting for Debugger - Application XXX is waiting for the debugger to Attach" 解 ...
- iOS开发工具——网络封包分析工具Charles
简介 Charles是在Mac下常用的截取网络封包的工具,在做iOS开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析.Charles通过将自己设置成系统的网络访问代理服务器,使 ...
- HMM 自学教程(一)引言
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
- Linux - 常见Shell文本处理方法
Common Shell Text Processing 珠玉在前,不再赘言. Linux Shell 文本处理工具集锦:http://blog.jobbole.com/99063/ 数据工程师常用的 ...
- TogetherJS – 酷!在网站中添加在线实时协作功能
TogetherJS是一个免费.开源的 JavaScript 库,来自 Mozilla 实验室,可以实现基于 Web 的在线协作功能.把 TogetherJS 添加到您的网站中,您的用户可以在实时的互 ...
- .net 根据匿名类生成实体类,根据datatable生成实体类,根据sql生成实体类
在开发中可能会遇到这几种情况 1.EF或LINQ查询出来的匿名对象在其它地方调用不方便,又懒的手动建实体类 2.通过datatable反射实体需要先建一个类 ,头痛 3.通过SQL语句返回的实体也需要 ...
- 更加优雅地搭建SSH框架(使用java配置)
时代在不断进步,大量基于xml的配置所带来的弊端也显而易见,在XML配置和直接注解式配置之外还有一种有趣的选择方式-JavaConfig,它是在Spring 3.0开始从一个独立的项目并入到Sprin ...
- SQL Server技术问题之触发器优缺点
优点: 1.强化约束:强制复杂业务的规则和要求,能实现比check语句更为复杂的约束. 2.跟踪变化:触发器可以侦测数据库内的操作,从而禁止数据库中未经许可的更新和变化. 3.级联运行:侦测数据库内的 ...