使用 Eclipse 在 Google App Engine 上创建 mashup,第 1 部分: 创建应用程序

来源:developerWorks 中国 作者:Michael Galpin
  
进军社会软件是为应用程序增值的好方法。使用社会网络可以更轻松地获得并聚合数据,从而创建富有革新精神的新 Web 应用程序。但是,仍然必须处理创建可伸缩 Web 应用程序的所有常见问题。现在,使用 Google App Engine (GAE) 也可以简化工作。使用 GAE,可以不必考虑管理应用服务器池的所有事务。您不必担心存储大量静态内容和动态数据。相反,您可以将精力集中在创建优秀的 mashup 上。本文是共分三部分的系列文章 “使用 Eclipse 在 Google App Engine 上创建 mashup” 的第一部分,将了解如何开始开发 GAE 应用程序,以及如何使用 Eclipse 简化 GAE 开发。

关于本系列

在本系列中,将了解如何开始使用 Google App Engine (GAE)。在第 1 部分中,将了解如何设置开发环境,以便可以开始创建运行在 GAE 上的应用程序。了解如何使用 Eclipse 简化应用程序的开发和调试。在第 2 部分中,将使用 Eclipse 构建一个 Ajax mashup 并将其部署到 GAE 中。最后,在第 3 部分中,通过为应用程序创建 RESTful Web 服务返回到生态系统,这样其他人就可以使用它创建自己的 mashup。

GAE 是创建 Web 应用程序的平台。使用它的最重要的先决条件是具备 Python 知识,因为要在 GAE 中使用 Python 作为编程语言(目前为 Python V2.5.2)。对于本系列,具备一些典型的 Web 开发技能将会有帮助(例如,HTML、JavaScript 和 CSS 知识)。要针对 GAE 进行开发,需要下载三个软件包。

Eclipse Classic
我使用的是 Eclipse Classic V3.3.2。更新的版本也可以使用。
Google App Engine SDK
阅读 GAE 站点中的官方文档并查找下载 SDK 的链接。
PyDev
使用更新站点 http://pydev.sourceforge.net/updates/ 从 Eclipse 内下载 PyDev,它可以将 Eclipse 转换为一个 Python IDE。

下面详细讨论了后两个软件包的安装。如果您刚开始使用 Eclipse,请参阅 参考资料 获得入门。





设置 GAE

如果曾经花大量时间开发过 Web 应用程序,则很可能在想要开始使用新应用程序堆栈时习惯下载库、Web 服务器和数据库。有时,可以将所有这些包绑定到优秀的安装程序中,从而可以更轻松地使用所有活动部分。一切就绪后,通常需要进行更多的设置,才能正常使用所喜爱的开发环境。幸运的是,使用 GAE 时不会遇到这种情况。让我们看看如何设置它以及如何将它和 Eclipse 结合起来。

设置 GAE 首先需要做的是下载 SDK,可用于 Microsoft® Windows®、Mac OS X 和 Linux®。对于 Windows 和 Mac OS X,SDK 是以安装程序出现的,不但要在系统中安装 SDK,而且要在路径中放置几个关键的可执行脚本以便使用。图 1 显示了 SDK 的目录结构图。


图 1. GAE SDK 目录结构
Google App Engine SDK 目录结构

在根目录中,您应当会看到两个 Python 脚本:appcfg.py 和 dev_appserver.py。dev_appserver.py 脚本用于启动开发应用服务器。没有独立安装,也不需要为开发和测试应用程序进行部署。当您准备好将应用程序部署到 GAE 中时,将使用 appcfg.py 脚本。

您可以在 Google 目录中查找构成 GAE 平台基础的所有 API。您将不可避免地使用和扩展该目录中的类。因此,如果需要运行 GAE 应用程序代码,则需要知道该目录,因为需要了解应用程序代码所使用的 API。作为示例,让我们看一看如何设置用于开发 GAE 代码的 Eclipse。





设置 Eclipse

Eclipse 被称为开发 Java™ 编程语言应用程序的首要 IDE。但是,它不但适用于 Java 开发人员,而且还可以用于许多其他语言,包括 C++、PHP、Ruby 和 Python。实际上,有多个 Eclipse 插件可用于将 Eclipse 转换为 Python IDE。这些插件中最常见的是 PyDev。可以使用更新站点 http://pydev.sourceforge.net/updates/ 从 Eclipse 中安装该插件。

安装 PyDev 之后,需要配置它。打开 Eclipse 并转到 Preferences > PyDev。


图 2. 配置 PyDev
配置 PyDev

您需要把 Python 安装位置告诉 PyDev。转到 Interpreter > Python 并单击 New,如上所示。只需浏览到 Python V2.5+ 安装,然后 Eclipse 应当会执行剩余操作。单击 OK,然后您将准备好从 Eclipse 中开发 Python。





创建应用程序

首先在 Eclipse 中创建一个新 PyDev。通过选择 Windows > Open Perspective > Other 并从可用透视图列表中选择 PyDev 切换到 PyDev 透视图。


图 3. 打开 PyDev 透视图
打开 PyDev 透视图

现在应当能够通过选择 File > New > PyDev Project 创建新应用程序。在本例中,我们将为源代码创建一个单独的 src 文件夹,但这是可选的并且主要取决于个人习惯。到目前为止,所做的一切都是在 Eclipse 上进行的一般的 Python 开发。现在将开始执行一些特定于 GAE 的操作。





GAE 模板项目

GAE 项目的布局十分简单;只有一个没有子目录的目录。一定有三个文件:app.yaml、index.yaml 和 main.py。下面显示了第一个文件 app.yaml。


清单 1. app.yaml
application: aggrogator
version: 1
runtime: python
api_version: 1

handlers:
- url: .*
  script: main.py

这是 GAE 应用程序的主要配置文件。该文件中的大部分内容只需要设置一次,例如应用程序名称、版本和构建该应用程序所使用的 GAE API 的版本。需要更多处理的部分是 handlers 部分。这是 HTTP 请求 URL 和项目中的 Python 脚本之间的映射。在以上情况下,我们将把所有内容都映射到同一个 main.py 脚本中。该文件随后可以执行额外的路径以将 URL 与方法匹配在一起。

另一个 YAML 文件 index.yaml 用于帮助 GAE 高效地获取数据。实际上,即使没有这样一个文件也没有关系,因为如果遗漏了该文件,GAE 也会为您生成一个。现在无需对该文件进行任何操作,清单 2 显示了一个空的 index.yaml。


清单 2. index.yaml
indexes:

# AUTOGENERATED

# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run.  if you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED").  If you want to manage some indexes
# manually, move them above the marker line.  The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.

最后,我们将接触到应用程序的核心:main.py 脚本。实际上您可以给该脚本任意命名,只要它是与 app.yaml 同步的。通常都使用 main.py 名称,因此我们在这里也使用这个名称。在查看该文件之前,让我们先描述一下编写的应用程序的类型。





aggroGator

我们的应用程序名为 aggroGator。它将允许用户关联已经使用的各项 Web 服务。然后将从这些服务中获取数据提要并按时间顺序聚集这些数据提要。对于我们的应用程序,将使用常见的 FeedParser 库来解析提要。还将通过 Google 使用 GAE 的内置身份管理,因此无需编写自己的注册/登录/退出特性。用户将只使用 Google 身份进行登录。记住这一切之后,让我们看一看 main.py。


清单 3. main.py
def main():
  application = webapp.WSGIApplication(
                                       [('/', MainPage),
                                        ('/add', AddService)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()

因此这实际上只是脚本的主要方法。该方法所做的是设置更多路径。在这种情况下,它将把 “/” 的请求发送到名为 MainPage 的类中,并把 “/add” 的请求发送到名为 AddService 的类中。现在让我们看一看 MainPage 类。


清单 4. MainPage
class MainPage(webapp.RequestHandler):
  def get(self):
    user = users.get_current_user()

    if users.get_current_user():
      url = users.create_logout_url(self.request.uri)
      url_linktext = 'Logout'
    else:
      url = users.create_login_url(self.request.uri)
      url_linktext = 'Login'
      
    updates = []
    account = None
    if user:
        account_query = Account.all()
        account_query.filter('user = ', users.get_current_user())
        result_set = account_query.fetch(1)
        if len(result_set) > 0:
            account = account_query.fetch(1)[0]
        
        if account:
            updates = []
            for service in account.dynamic_properties():
                url = getattr(account, service)
                feed = GenericFeed(url, service)
                updates.extend(feed.entries())
        else:
            account = Account()
            account.user = user
            account.put()
        updates.sort(key=attrgetter('timestamp'), reverse=True)

    template_values = {
      'account': account,
      'updates': updates,
      'url': url,
      'url_linktext': url_linktext,
      }

    path = os.path.join(os.path.dirname(__file__), 'index.html')
    self.response.out.write(template.render(path, template_values))

该类执行了很多操作,因为它是应用程序的主要控制器。首先需要注意的是它只有 get 方法。那意味着它只支持 HTTP GET 请求。对 “/” 执行 POST 将导致错误。接下来,它将检查身份。users 类是来自 GAE SDK 的 API。它将利用 Google 的身份管理。我们将使用它检查用户是否已登录。如果用户已登录,就会知道用户的身份(其 Google ID)。然后创建登录链接或者退出链接,这取决于他是否已登录。如果没有登录,则只显示登录链接;否则,继续查找帐户。下面是已经编写的另一个类:


清单 5. Account 类
class Account(db.Expando):
    user = db.UserProperty()

该类将利用 Google 的数据存储 API(Google 的著名 Bigtable 数据库)。Account 实体拥有 User 属性并且是 Expando Model。这将允许我们创建动态属性 — 用于每项服务的 URL。对于每项服务,将使用 GenericFeed 类检索条目列表,如下所示:


清单 6. GenericFeed 类
class GenericFeed:
    def __init__(self, url, name):
        self.url = url
        self.name = name
    def entries(self):
        result = urlfetch.fetch(self.url)
        updates = []
        if result.status_code == 200:
            feed = feedparser.parse(result.content)
            for entry in feed['entries']:
                x = Entry()
                x.service = self.name
                x.title = entry['title']
                x.link = entry['link']
                if entry.summary:
                    x.content = entry.summary
                else:
                    x.content = entry['title']
                x.timestamp = entry.updated_parsed
                updates.append(x)
        return updates 

这是使用 FeedParser 库的类。在使用该库之前,我们将使用另外一个 GAE API:urlfetch 类。该类将允许 HTTP 请求,但只是 80 端口和 443 端口(用于安全请求)。只使用它对存储的 URL 执行 HTTP GET,然后将结果传递给 FeedParser 库。接着创建 Entry 类的实例,如下所示:


清单 7. Entry 类
class Entry:
    def __init__(self=None, title=None, link=None, timestamp=None, 
content=None, service=None):
        self.title = title
        self.link = link
        self.content = content
        self.service = service
        self.timestamp = timestamp
    def printTime(self):
        return strftime('%B %d,%Y at %I:%M:%S %p',self.timestamp)  

该类几乎只是一个简单的数据结构。它惟一的逻辑是拥有一个输出时间戳的方法。GenericFeed 类将返回与该用户相关的每项服务的 Entry 实例列表。然后按降序根据时间戳排序 Entries(第一个是最新的 Entry)。返回到 MainPage,然后将若干个对象、用户的 Account、排序后的 Entries 列表及登录/退出链接传递给模板。GAE 使用的模板系统类似于常见的 Python 框架 Django 所使用的模板系统。在本例中,将把数据传递给名为 index.html 的模板。


清单 8. index.html 模板
<html>
  <body>
    <a href="{{ url }}">{{ url_linktext }}</a>
    <ol>
    	{% for update in updates %}
    		<li>
    			From {{update.service}}: 
    			<a href="{{update.link}}">{{update.content}}</a>
    			posted at: {{update.printTime}}
    		</li>
    	{% endfor %}
    </ol>
    {% if account %}
	    <form action="/add" method="post">
	    	<label for="service">Service: </label>
	    	<select name="service">
	    		<option>twitter</option>
	    		<option>del.icio.us</option>
	    		<option>last.fm</option>
	    		<option>YouTube</option>
	    	</select><br/>
	    	<label for="username">Username: </label>
	    	<input type="text" name="username"/>
	    	<input type="submit" value="Add"/>
	    </form>
    {% endif %}
  </body>
</html>

这是一个简单的模板。它大部分只是 HTML,其中带有几个动态部分。首先,它将创建相应的登录/退出链接。接下来,它将遍历条目列表以将其显示给用户。最后,如果用户已登录,则创建允许用户添加服务的表单。该表单将对 /add URL 执行 HTTP POST。如清单 3 所示,该请求将被发送到 AddService 控制器类中。


清单 9. AddService 控制器
class AddService(webapp.RequestHandler):
    def post(self):
        # check if user already exists
        account_query = Account.all()
        account_query.filter('user = ', users.get_current_user())
        result_set = account_query.fetch(1)
        if len(result_set) > 0:
            account = account_query.fetch(1)[0]
        else :
            account = Account()
            account.user = users.get_current_user()
        service = self.request.get('service')
        username = self.request.get('username')
        if service == 'twitter':
            service = 'http://twitter.com/statuses/user_timeline/'+username+'.rss'
            account.twitter = service
        if service =='del.icio.us':
            service = 'http://del.icio.us/rss/' + username
            account.del_icio_us = service
        if service == 'last.fm':
            service = 'http://ws.audioscrobbler.com/1.0/user/'+username+
			                                           '/recenttracks.rss'
            account.last_fm = service
        if service == 'YouTube':
            service = 'http://www.youtube.com/rss/user/'+username+'/videos.rss'
            account.you_tube = service
        account.put()
        self.redirect('/')

该类将查找用户的帐户。然后根据使用的服务创建相应的 URL。使用 Expando 属性把该 URL 添加到帐户的服务中,并且把所有内容保存回 Bigtable 中。最后,重定向到 MainPage。

现在已经看过应用程序的所有代码,并且已经准备好运行。但是如何运行?Eclipse 将再次帮您轻松运行。





在本地进行测试

GAE SDK 将提供在本地运行项目的命令行工具。但是,我们希望利用 Eclipse,因此需要从 Eclipse 中运行所有内容。这将允许我们调试应用程序,稍后我们将看到。运行应用程序的第一步是编辑项目的 PYTHONPATH。完成此操作的最简单方法是在项目上右键单击并选择 Properties。这将打开项目属性。


图 4. 项目属性
项目属性

正如您所见,需要在左侧菜单中选择 PyDev - PYTHONPATH。然后需要选择 Add source folder 并浏览到 GAE SDK 的安装位置。该位置将根据 OS 的不同而有所变化,并且可以自定义。对于 Windows,默认值(由安装程序设定)为 C:\Program Files\Google\AppEngine,而对于 OS X,默认值为 /usr/local/google_appengine。如果位于 Linux 中或者下载了 ZIP 而不是特定于 OS 的安装程序,请选择放置 SDK 的位置。可以是任意位置,但是需要让 Eclipse 知道该位置。该位置将称为 $APP_ENGINE_HOME。

现在,运行项目还需要做最后一件事:需要为它创建一个 Run 配置文件。为此,选择 Run > Open Run 对话框。


图 5. Run 对话框
Run 对话框

该 Run 配置文件被称为 aggroGator。在 Main Module 下,浏览到 $APP_ENGINE_HOME 并选择 dev_appserver.py 脚本。这是模拟 GAE 生产环境的 Python 应用服务器。接下来,转到 Arguments 选项卡,如图 6 所示。


图 6. Arguments 选项卡
Arguments 选项卡

在 Program arguments 框中,输入 ${project_loc}/src。Eclipse 变量 ${project_loc} 仅指向当前项目的物理位置。需要将应用程序目录传递给 dev_appserver.py 脚本,因而传递给 /src。如果不把代码放到 src 目录中,则需要相应地调整实参。

现在已经准备好运行应用程序。如果单击 Run,则应当会在 Eclipse 控制台中看到清单 10 中的输出。


清单 10. 控制台输出
INFO     2008-06-08 05:00:29,236 appcfg.py] Server: appengine.google.com
INFO     2008-06-08 05:00:29,283 appcfg.py] Checking for updates to the SDK.
WARNING  2008-06-08 05:00:29,581 datastore_file_stub.py] Could not read datastore data 
 from /var/folders/oo/ooKE4ln2HqC9exSMWxwprk+++TI/-Tmp-/dev_appserver.datastore
WARNING  2008-06-08 05:00:29,582 datastore_file_stub.py] Could not read datastore data 
 from /var/folders/oo/ooKE4ln2HqC9exSMWxwprk+++TI/-Tmp-/dev_appserver.datastore.history
INFO     2008-06-08 05:00:29,606 dev_appserver_main.py] Running application aggrogator 
 on port 8080: http://localhost:8080

注意,这段代码说明应用程序运行在 http://localhost:8080。在浏览器中转到该 URL 并尝试一下,如下所示:


图 7. aggroGator 欢迎屏幕
aggroGator 欢迎屏幕

单击 Login 将显示图 8。


图 8. 登录屏幕
登录屏幕

很明显,这是模拟的登录屏幕。您可以使用任意一个电子邮件地址,因为这不会实际访问 Google 身份验证服务。实际上,test@example.com 可以正常工作。登录后即可以开始添加服务。


图 9. 添加服务
添加服务

现在可以通过添加服务开始玩转应用程序。如果返回到清单 8 的 AddService 控制器,各项服务提要的 URL 都是被硬编码到该类中。当然,这一切可以在将来改变,并且可能得到错误。这时有调试器会方便得多。让我们看一看如何将 Eclipse 调试器与 GAE 项目结合使用。





调试

使用诸如 Eclipse 之类的 IDE 的主要优点是更易于调试应用程序,甚至复杂的 Web 应用程序。首先需要为 GAE 项目做的是创建 Debug 配置文件。该配置文件类似于 Run 配置文件,因此只需选择项目并单击 Run > Open Debug 对话框。


图 10. Debug 对话框
Debug 对话框

Eclipse 将智能地把默认值设为先前创建的 Run 运行设置。无需修改,并且只需单击 Debug。查看 Eclipse 控制台,并且应当会看到类似于清单 11 的一些输出。


清单 11. 调试输出
pydev debugger: warning: psyco not available for debugger speedups
pydev debugger: starting
INFO     2008-06-08 05:18:37,704 appcfg.py] Server: appengine.google.com
INFO     2008-06-08 05:18:37,755 appcfg.py] Checking for updates to the SDK.
INFO     2008-06-08 05:18:38,196 dev_appserver_main.py] Running application aggrogator 
 on port 8080: http://localhost:8080

前两行显示 pydev 调试器的输出。现在可以在项目中设置断点并且开始调试。在图 11 中,我们将调试 AddService 控制器。


图 11. 调试 AddService
调试 AddService

现在可以开始逐步调试代码并检查变量。如果任何一项服务发生更改,或者需要添加新服务,这将使您可以轻松地找到并修复错误。





结束语

在本文中,很快就实现了一个完整的应用程序。Google App Engine SDK 已经安装并且与 Eclipse 连接在一起。这将允许我们快速编写、测试和调试代码。我们了解了 GAE 项目中的许多关键概念,包括 URL 路由、通过 URL 获取与外部站点进行交互、使用演示模板以及使用 Bigtable。我们的应用程序已经准备好部署到 GAE 中,将在第 2 部分中了解这些内容。(责任编辑:A6)


时间:2008-11-18 09:26 来源:developerWorks 中国 作者:Michael Galpin 原文链接

好文,顶一下
(0)
0%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量