原贴地址:[url]http://www.infoq.com/cn/articles/case-study-grails-parti[/url]

作者 侯雍容 发布于 2009年2月5日 上午2时29分
社区 Ruby, Java 主题 Web框架 标签 案例研究, Grails
Feedlr和Grails
Feedlr:feed驱动的多平台微博客机器人平台

微博客是由Twitter 创造出的一种web 2.0时代的新事物。在微博客上,人们使用简短的语言随时随地的发表消息,并可以即时地受到好友的消息。由于易用,实时等特点,Twitter在06年推 出至今逐步升温,已经拥有超过300万用户。特别在08年中,Twitter一改起步阶段geek玩具的角色,明显地向主流进化。随着Twitter的兴 起,也出现了非常多其他的微博客。仅国内就有叽歪、饭否、以及做啥等等。微博客的兴起提供了一种全新的在线沟通方式。

相关厂商内容

Adobe开发者技术日,7月16日上海,免费报名!
Twitter作为微博客的 鼻祖和最成功的例子,其优秀的API接口功不可没。通过Twitter API,开发者们开发出了众多新奇又好用的Twitter第三方应用。我开发Feedlr的出发点是建立一个让用户可以自行定制feed机器人的服务,核 心功能类似Twitter上颇受欢迎的twitterfeed,并且可以同时Twitter,叽歪,饭否以及做啥共4种微博客平台。

通过 Feedlr,用户可以建立微博客广播帐号,来随时追踪自己感兴趣的RSS/Atom Feed内容。一旦有更新,Feedlr就会自动把新的内容发送到指定的微博客平台上。Feedlr上线至今,用户们建立了自定义的新闻播报机器 人,DIY的免费天气预报机器人,不同微博客之间的消息同步机器人,甚至国内地震情况实时监控机器人等等。而通过国内微博客服务的短信通知服务,以上所有 的Feed内容国内用户都可以免费在手机上通过短信接收到。

Grails框架的选择

Grails是一个崭露头角的基于 Groovy语言,运行与JVM之上,设计上类似于Rails的快速web开发框架,在08年初刚推出1.0版。通过Groovy语言和创新的架 构,Grails把成熟的企业级JEE开源组件Spring,Hibernate等巧妙地整合起来,使用类似Rails的“按约定设计”(design by convention)理念捆绑成一套完整的web开发框架。JEE开发过程的繁琐被Groovy灵活多变的动态特性和按约定设计带来的精简配置所取代, 而又保留了企业级组件在稳定和性能方面的优势,可以说是把Rails式的快速开发带给了水深火热中的JEE开发者们。我来自JEE背景,对Groovy语 言也有一定基础,选用Grails搭建Feedlr是比较自然的选择,同时也是为了在一个没有过多约束的真实项目中体验Grails的完整开发过程。

如何用Grails实现Feedlr的核心功能
Feedlr的核心功能

Feedlr的核心功能主要包括定时查询用户提供的feed的更新,把更新的feed内容发布到微博客,再加上用来增强用户体验的多处AJAX实现以及OpenID登录等。这里逐一对这些功能的实现做一下介绍。

定时查询feed更新

Feedlr 最核心的功能就是定时轮询用户提交的feed,发现新增的条目,从而通过微博客API发送到微博上去。只要使用Grails的Quartz插件就可以非常 方便的实现这一功能。Quartz是一个用途广泛的开源Java库,用于精确地控制定时任务。由于兼容Unix Cron语法,Quartz的功能非常强大。而在Grails中,Quartz是框架自带的核心插件之一,通过Quartz插件来执行定时任务非常方便。 新建一个Quartz定时任务,只需要在Grails项目根目录下执行

grails create-job

[b][color=red](注意:前提是需要安装Grails插件quartz)[/color][/b]

根 据提示输入job名称,Grails就会自动在grails-app/jobs/目录下生成一个新的job程序文件。Grails job都是以XXXJob.groovy命名,存放在grails-app/jobs目录下,Grails启动时会自动遍历jobs目录,定时执行每个定 义好的job。一个job文件用来定义一种定时执行模式,通过Unix Cron语法来定义定时逻辑。例如,Feedlr用于轮询feed的job大致是这样的:

class UpdateFeedsJob {    def feedService        def cronExpression = "0 * * * * ?" //每分钟执行一次     def execute() {            feedService.updateFeeds()    }}

Cron 表达式“0 * * * * ?”表示每分钟执行一次。需要执行的逻辑通过定义一个execute()方法来指定。其中feedService是已经定义好的用来查询feed更新的一 个Grails Service类,使用Rome来解析feed。注意此处不需要实例化feedService变量,只要通过按约定设计的规则定义需要使用的 Service的变量名,Grails会自动找到FeedService这个Service类,注入到UpdateFeedsJob中,并把 Service实例付给feedService变量,听起来很神奇吧。这样,Grails就会每分钟触发一次UpdateFeedsJob,来查询 feed更新了。

发布feed更新到微博客

目前流行的微博客API都是已REST风格设计,通过GET和POST方法来得到或者更新内容的。例如发布一条消息到Twitter,就是通过POST方法发送到Twitter指定的API地址,简化的代码实例如下:

def conn = new URL('http://twitter.com/statuses/update.xml').openConnection()conn.setRequestProperty ('Authorization', 'Basic ' + 'username:password'.bytes.encodeBase64())conn.requestMethod = 'POST'conn.doOutput = truetry{    conn.outputStream.withWriter('UTF8'){                       it << "status=" << newMessage    }}catch(Exception e){    ...}

以上Groovy代码很清晰易读。通过Twitter RESTful API发布新消息需要使用Http Basic验证用户登录信息,所以这里按照Basic验证规范在请求中加入了验证数据。其中encodeBase64()方法是Grails提供的神奇的 动态方法,对于合适类型的对象在Grails程序中直接就可以使用这些动态方法,其他的编码方法还包括encodeAsURL()等。

Ajax

在web 2.0时代没有Ajax的网站是不完整的。幸运的是,在Grails中使用Ajax非常方便。通过Grails内建的多才多艺的render方法,就可以轻松地给前端Ajax请求返回任何形式的输出。例如,

直接返回简单的纯文本字串

class FooController{...    def ajaxResponse = {        ...        render("This is an Ajax response.")    }

指定返回内容的格式和编码

render(text:"<xml>some xml</xml>",contentType:"text/xml",encoding:"UTF-8")

返回模板内容

render(template:"feeds", model:[feeds:feeds], contentType:"text/html", encoding:"UTF-8")

返回JSON,直接自动转换一个object为JSON

import grails.converters.*...def jsonObj = [object:[collection:[[name:‘value1′],[name:‘value2′]]]]render jsonObj as JSON

返回JSON,通过JSON builder DSL直接构造JSON数据

render(contentType:‘text/json’, , encoding:'UTF-8'){        studio(name:‘Pixar’,website:‘pixar.com’)        films{                film(title:‘Toy Story’,year:‘1995′)                film(title:‘Monsters, Inc.’,year:‘2001′)                 film(title:‘Finding Nemo’,year:‘2003′)        }}

OpenID支持

Feedlr支持使用OpenID登录。由于Grails社区已经提供了OpenID插件,通过Grails的插件机制,实现OpenID支持也是一件轻松的事情。

首先,安装OpenID插件,在Grails应用根目录执行命令:

grails install-plugin openid
然后,使用openid插件提供的taglib来编写openid登录表单

<openid:form success="[controller:'login',action:'openidSuccess']" error="[controller:'login',action:'openidError']">                <openid:input size="30" value="http://" class="input-text"/>...</openid:form>

OpenID 插件代为处理了具体的OpenID登录验证过程,在<openid:form>中,通过success参数和error参数指定登录成功或失 败以后重定向到哪个controller action。登录成功后,就可以在controller中直接得到当前登录的openid信息。

def openid = session.openidIdentifier

当然,需要实现完整的OpenID和普通帐号的整合还有更多工作要做,包括把登录的OpenID和已有的普通帐号关联起来,从普通帐号添加OpenID信息等。这些都是需要开发者根据自己的情况自行实现的。

测试
测 试是开发一个完整项目不可缺少的部分,幸运的是Grails已经为开发者考虑到了这点,测试Grails程序也能像开发一样轻松。Grails中的测试建 立在Groovy testing的基础上,通过使用Groovy来编写JUnit测试代码,减轻程序员的负担。Grails中的测试分为unit test和integration test两种,两者的区别主要在于unit test是相对独立的测试,而integration test执行的时候Grails会按照实际运行的方式启动框架程序。建立一个unit test或者integration test各自只需要一条命令即可。

grails create-unit-testgrails create-integration-test

Grails 会自动在grails-app/test/unit或者grails-app/test/integration下面建立相应的 XXXTests.groovy文件。具体的test case定义在XXXTests.groovy里,通过定义继承groovy.util.GroovyTestCase的类来实现,这些其实都是 Groovy测试的内容,通过JUnit方式编写测试代码即可。

准备好了test case之后,Grails同样已经为你准备好的命令来自动执行测试。

grails test-app

执行这条命令,Grails就会自动按照unit test到integration test的顺序来执行定义好的所有test case,并将测试结果整理成HTML格式展现出来。test-app命令还有更多具体用法,可以参考Grails文档。

Feedlr的部署
使用Grails的开发过程是很令人感到愉快的。那么,一切都搞定以后,怎么部署呢?

Grails 文档中说明Grails经测试可以部署到大多数常用的Java应用服务器上,但是具体有关部署的资料文档比较缺乏。Feedlr选择的是Tomcat 6,相对来讲比较常用,资料也比较丰富。准备部署Grails应用的时候,首先通过Grails把项目打包成war文件。

grails prod war feedlr.war

这里,"prod"参数用来指定打包的时候使用Config.groovy里针对生产环境的配置。部署环境的配置在Config.groovy中设定,包 括"prodcution",“development"和"testing"三种,主要用于对不同环境指定不同的数据源和特定的环境变量。具体用法可以 参考Grails文档。war命令默认的打包环境就是"prod",所以次数"prod"也可以省略。如需指定其他环境只需要将"prod"替换 成"dev"或者"test"即可。

最后指定war文件的文件名是可选的。在Tomcat下如果想让应用跑在URL根路径下,可以指定文件名为ROOT.war。打包完成后,把war文件复制到Tomcat应用目录下,启动Tomcat,正常的话Grails应用就能跑起来了。

在 系统性能和伸缩性方面,我其实没有花太多力气去优化。最主要的优化工作就是在内存占用方面。Feedlr目前使用的是一台540MB内存的VPS服务器, 在初期曾使用340MB内存的配置,遇到了内存资源紧张的问题,导致JVM性能底下。由于Feedlr的特定用途,需要解析大量feed内容,所以在内存 方面要求不低。后来经过一系列的优化措施,目前在这个环境下运行的相对比较稳定了。我之前也总结过一些Grails服务器优化的经验,有兴趣的朋友可以参考我的这篇博客文章。

实际开发中的一些困难
在Feedlr的开发中,可以体会到目前阶段使用Grails进行完整Web项目开发的一些困难和问题。

开发环境的不完善

Feedlr 是在Eclipse加上Groovy插件的环境下开发的。但是这个环境目前还非常不完善,主要是Groovy插件的可用程度还比较低,而且没有 Grails支持,不支持GSP语法等,只是能够支持Groovy语言,加上Eclipse本身的强大功能,能够给开发提供一定帮助。不过好在使用 Groovy语言开发比Java要省力不少,所以不需要非常强大的IDE也可以不错的完成任务。IDE方面另外的选择主要包括IntelliJ IDEA和NetBeans。简单来讲收费的IDEA对Groovy/Grails的支持最为完整强大,但是代价也不菲。开源方面的选择,Eclipse 方面还是比刚刚开始支持Groovy的Netbeans好过不少。

Grails本身尚不够成熟

在开发过程中也遇到过若干 Grails的bug,有的bug甚至导致某功能无法正常运行。使用一个尚不成熟的框架,遇到bug也是正常的事情。解决bug的话基本上可以先到 Grails邮件列表里提问和寻找答案,需要的话提交bug报告到Grails官方JIRA,提供bug数据等待修复。不过如果遇到紧急问题,还是自己动 手更好。可以从Grails主页下载带源码的Grails安装包,就可以直接调试bug并编译修改代码,这样不用等官方发布下一个小版本就可以直接解决问 题了。在Feedlr开发过程中遇到过若干比较紧急的bug,我随着bug报告也提供过若干补丁程序,在最新的Grails 1.0中都已被集成。在这里也要建议大家在使用过程中多多提交bug报告和提供补丁程序,这是良好的参与建设开源社区的方式。

总结
要 完整地实现Feedlr显然还有很多工作要做,但Grails确实大大减轻了程序员编码工作的负荷。通过grails stats命令可以看到,除去测试代码,feedlr最终的代码规模约是1.9kloc。对于一个完整地具备了包括全文检索,RSS/Atom feed生成(Feedlr提供最新机器人服务列表的feed),Tag标签功能,OpenID+普通登录方式整合等功能的web 2.0网站来说,这确实意味着我省去了不少打字的工夫,避免了传统JEE繁琐的开发方式。

那么,Grails到底是不是JEE世界的圣杯呢?我将在本系列的下篇文章中进一步进行分析。

参考资料
Grails:http://grails.org
Grails文档:http://grails.org/doc/1.0.x/
Groovy:http://groovy.codehaus.org/
Mastering Grails系列文章:http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=mastering+grails
作者简介
侯雍容,毕业于复旦大学计算机专业,毕业后在IBM中国开发中心从事软件开发工作,目前创立了上海睿谷信息科技有限公司,从事软件开发和咨询工作。对于敏捷Web开发、动态程序语言、云计算等方面都有特别的兴趣和经验。可以从这里看到关于他的详细资料:http://www.linkedin.com/in/houyr,也可以访问他的个人博客:http://damienh.org。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家加入到InfoQ中文站用户讨论组中与我们的编辑和其他读者朋友交流。

案例研究:利用Grails搭建Feedlr.com网站相关推荐

  1. 【Python案例】——利用Django搭建一个钓鱼网站【轻松入门】

    目录 (1)最终实现效果​编辑 (2)安装Django模块 (3)创建Django项目 (4)查看项目是否环境配置成功 (5)点击进入settings.py文件,进行定制化修改 (6)导入所需文件 ( ...

  2. 利用 GitHub 搭建独立 Web 网站

    Hugo 是一款快速搭建网站的主题框架,相对于 Hexo 来说, Hugo 的主题以及性能更加出色,并且类型上更加多元化,下面我们试着用 Hugo 来搭建网站.详情可以去 Hugo官网 查看. Hug ...

  3. SWAPIDC服务器销售模板,记录利用swapidc搭建IDC销售网站教程

    现在免空泛滥,所以写这么一篇教程吧 一.准备工作 首先你要准备一台服务器,其中推荐使用国外的Vultr(系统使用Centos6,方便实验),也可以用我的IDC服务器,不推荐使用国内的,因为域名需要备案 ...

  4. 从零开始利用vue-cli搭建简单音乐网站(四)

    上一篇文章中说到这一篇博客会实现音乐播放功能,只是令我意外的是,如果利用h5的audio标签,几行代码就实现了......先来看一下最终效果吧. 这里直接用了audio标签,样式没有怎么管,能获得音乐 ...

  5. 如何利用github搭建一个个人网站

    一.Github Pages的使用 1.首先你得有一个Github账号,没有的话去github.com注册一个: 点击Sign up for Github进入注册页面 2.有了账号以后登录到Githu ...

  6. 用户体验改善案例_用户体验案例研究:建立更好的体验(重新设计“和平航空”网站)...

    用户体验改善案例 by Peace Ojemeh (Perrie) 由Peace Ojemeh(Perrie) 用户体验案例研究:建立更好的体验(重新设计"和平航空"网站) (A ...

  7. 如何利用wordpress搭建自己独立的博客(个人网站)

    原址:http://blog.csdn.net/edroid1530/article/details/51136896 如何利用wordpress搭建自己独立的博客(个人网站) 搭建博客的方式多种样, ...

  8. 如何用个人电脑利用ipv6搭建网站

    如何用个人电脑利用ipv6搭建网站 需要的工具 写在前面的话 第一步 第二步 需要的工具 一台拥有ipv6地址的个人电脑(Windows版) 没啦 ^ - ^ 写在前面的话 小白文章,请大佬指正 随着 ...

  9. 如何利用教育网站源码成功搭建在线教育网站

    如今是一个信息化时代,人们都想接受各种各样的教育,在线教育也就因此发展了起来,并且逐渐成为了一种趋势.而成熟的在线教育网站皆是由高质量的教育网站源码搭建而成的.如何利用教育网站源码成功搭建在线教育网站 ...

最新文章

  1. 「机器学习速成」过拟合的风险和泛化
  2. 2021年春季学期-信号与系统-第十一次作业参考答案-第七小题
  3. nebual的图数据结构
  4. 收藏 | 机器学习、深度学习调参手册
  5. 高校战役结束,中小学市场战斗吹响号角
  6. 适合上班族的两种兼职
  7. python2.7卸载出问题原因分析_怎么卸载python2.7
  8. oracle like 前缀,algorithm – 在ORACLE中搜索最长前缀的最快方法
  9. 实现Servlet接口来开发Servlet程序
  10. 衡量高分辨率图片生成效果的指标PSNR/SSIM
  11. Oracle之学习if条件选择语句
  12. java核心技术卷I 第4-5章
  13. 微信小程序获取二维码报错:{“errcode“:47001,“errmsg“:“data format error hint:“}
  14. ansys linux运行_ANSYS2020R1 产品Linux平台安装
  15. windows编程经典书籍+VC++学习路线资料
  16. echars x轴单位_ECharts xAxis配置 x坐标轴刻度设置
  17. 宏基因组分析教程-Analysis of Metagenomic Data
  18. ThinkPad-T480-OpenCore0.7.5-黑苹果EFI
  19. 使用sklearn实现birch聚类分析
  20. java 组织机构代码_JAVA实现社会统一信用代码较验

热门文章

  1. 如何优雅地给妹子优化电脑?(技巧篇)
  2. 接口自动化测试(一)---接口及接口自动化测试概述
  3. Mybatis——foreach用法
  4. https证书申请是如何收费的
  5. 【Dubbo】扩展 etcd 注册中心
  6. 疫情当前,各互联网公司的开工时间
  7. Xcode6.1 OS X 10.10 打越狱包和免证书测试方法
  8. 3、序列化(什么是 java 序列化?什么情况下需要序列化?)
  9. 机器学习在股票交易中难点分析
  10. 如何检测网站是否存在XSS跨站漏洞