Linux各种文件系统比较

根据一些参考资料:

  1. Comparison of file systems – Wikipedia
  2. Linux File System Benchmarks
  3. Benchmarking Filesystems Part II

对主流的Linux操作系统所使用的文件系统ext2/3、jfs、reiserfs(v3/v4)、xfs作了一些评估,这里得出的结论是,

  • ext2由于没有日志记录功能,所以性能很好——当然也不够强壮和安全。
  • ext3性能最差(期待ext4)
  • jfs的平均CPU占用最低,如果系统运行于一个对CPU占用率有限制的系统中,考虑使用jfs
  • reiserfs的硬盘IO带宽占用率最低,如果系统运行于一个对于硬盘带宽有限制的系统中,考虑使用reiserfs,尤其是reiserfs v4。
  • xfs则是介于jfs和reiserfs之间,各种情况下都是比较好的选择。

JavaScript高级程序设计

profession-javascript-cover.jpg

基本信息

  • 【英文名】Professional JavaScript for Web Developers
  • 【作者】Nicholas C. Zakas
  • 【译者】曹力 张欣
  • 【ISBN】7115152098
  • 【出版时间】2006-9-15
  • 【页码】670
  • 【原出版社】Wrox
  • 【简介】本书从最早期Netscape浏览器中的Javascript开始讲起,直到当前它对XML和Web服务的具体支持,展示了如何充分利用这种功能强大的语言开发自己的应用程序,以解决当今Web开发者面对的商业问题。
  • 活动主页

译者序

继续阅读“JavaScript高级程序设计”

Zend Framework 指南

作者:Chris Shiflett
翻译:ShiningRay

我们邀请了PHP安全专家——兼最新发布的Zend Framework的贡献者——Chris Shiflett来为我们写一篇关于ZF主要特点的文章。

这份完整的、按部就班的教程通过向你展示如何应用框架写出一个简单的新闻管理系统,为你提供了构建实际应用的独特视角。

Zend Framework终于掀开了其神秘的面纱!尽管它尚处于开发过程的早期阶段,但本文将现在所能用的中最好的部分特别呈现给读者,并通过构建一个简单的应用这个过程引导你了解这个框架。

Zend很早就发布了框架并引入社区运作。写本指南只能针对框架今天的情况来列出其特点。因为本指南是在线发布的,所以我会在框架发生变化的时候及时更新本文,这样就能尽可能保持一致。

要求

Zend Framework 要求使用 PHP 5。为了能完全利用本指南中展示的代码,你还需要Apache Web服务器,因为范例应用(一个新闻管理系统)用到了mod_rewrite。

本指南中的代码可以自由下载,所以你可以亲自尝试一下。可以从Brain Bulb的网站上下载到:http://brainbulb.com/zend-framework-tutorial.tar.gz.

下载框架

在开始阅读本指南之前,你还需要先下载一份框架的预览发布版。可以用浏览器察看 http://framework.zend.com/download 并选择 tar.gz 或者 zip 文件手工下载,也可以使用下面的命令行:

清单1

注意

Zend已经计划提供一个独立的PEAR通道来方便下载。

下载了预览发布版之后,将这个库的目录放到一个方便的地方。在本教程中,我将库的目录名改称了lib,以便提供一个简单干净的目录结构:

清单2

www 目录是文档根目录,controllers和views目录为空,是将来要用的,lib目录是来自于下载的预览版。

入门

我第一个要向你展示的组件是Zend_Controller。在很多情况下,它为要开发的应用提供了一个基础,同时它也是令Zend Framework超越了组件集合的一个部分。不过在使用它之前,需要将所有进入的请求引导到某个PHP脚本中。本教程将使用mod_rewrite来完成这个目的。

如何用好mod_rewrite确实是一门艺术,不过还好本文中这个特殊的任务十分简单。如果你对mod_rewrite或者是Apache的一般配置还不是很熟悉的话,可以在文档根目录下创建一个.htaccess文件,并加入一下指令:

清单3

Zend_Controller目前的任务之一就是去掉对mod_rewrite的依赖。为了提供一个预览版可以使用的例子,本教程便使用了mod_rewrite。

如果你直接在httpd.conf中添加这些指令,还必须重新启动Web服务。但是,如果使用.htaccess文件,就不用了,而且这样更好。你可以随便在index.php中写点东西,然后任意请求某些路径来测试一下,比如/foo/bar。例如,如果你的主机是example.org,那么就请求URL http://example.org/foo/bar。

可能你还想在 include_path 中包含框架库的路径。你可以直接在php.ini中配置,或者可以将以下指令放入.htaccess文件中:

清单4

Zend

Zend 类包含了一系列十分通用也十分有用的静态方法。这是唯一一个需要手工进行包含的类:

清单5

一旦引用了Zend.php,就可以访问Zend类中的所有方法了。使用loadClass()方法,载入其他类也变得简单了。例如载入Zend_Controller_Front类:

清单6

loadClass()方法会考虑到include_path,同时它还知道框架的目录组织结构。我就使用它来载入所有其他的类。

Zend_Controller

这个控制器的使用还是比较直观的。实际上,我写这份指南的时候可没有官方文档可用!

现在ZF网站上已经有官方文档了。

首先讲Zend_Controller_Front,这是一个前端控制器。你可以将下面的代码放入index.php中来理解它是如何工作的:

清单7

如果你更希望使用对象链方式,可以如下改写:

清单8

现在,当进行/foo/bar的请求时,就会出现一个错误。这很好!它至少能告诉你有动作了。主要的问题是未发现IndexController.php

在创建这个文件之前,最好首先了解框架组织东西的方式。框架会将一个请求分解成几个部分,在这个例子中,请求/foo/bar,foo是控制器,bar是动作。两者的默认值都是index。

当foo作为控制器时,框架首先在控制器目录中查找名叫FooController.php的文件。因为不存在这个文件,于是框架退一步查找IndexController.php。如果还是没有发现,就报告错误。

下面,在controllers目录(可以使用setControllerDirectory()自己设置)中创建IndexController.php

清单9

IndexController类处理控制器为index的请求或者指定的控制器不存在的请求,就像刚才所说的。indexAction()方法将处理动作为index的请求。记住无论是控制器还是动作,默认的值都是index,前面也说过了。如果尝试请求/、/index或者/index/index,都会执行indexAction()方法(结尾的斜杠不会改变这种行为)。对任何其他资源的请求都可能会产生错误。

继续之前还要为IndexController添加一个很有用的方法noRouteAction()。一旦请求某个控制器且其不存在时便调用noRouteAction()方法。例如,请求/foo/bar时,如果FooController.php不存在,那么就会执行noRouteAction()。不过,/index/foo的请求还是会产生错误,因为这里foo是一个动作,而非控制器。

在IndexController中添加 noRouteAction() :

清单10

这个例子使用了 $this->_redirect(‘/’) 来描述可以在noRouteAction()中一般可能出现的动作。这可令对不存在的控制器的请求被重定向到根文档(首页)。

现在来创建 FooController.php:

清单11

如果你再请求 /foo/bar,就应该看到执行了barAction(),因为请求的动作是bar。这样不仅可以支持友好的URL,同时也可以用极少的代码就可以很好得进行组织。酷啊!

还可以创建一个__call()方法来处理未定义的动作的请求,如 /foo/baz:

清单12

现在只需几行代码就可以很优雅地处理进入的请求了,让我们继续。

Zend_View

Zend_View是一个可以协助你组织视图逻辑的类。它并不使用特定的模版系统,为了简便起见,在本例中我也不会使用模版系统。然而,你可以随意使用你喜欢的。

记住所有进入的请求都是由前端控制器来处理的。因此,既然应用程序的框架已经这样存在了,那么以后的天价都必须适应它。为了演示Zend_View最基本的用法,我们将IndexController.php中的代码修改成这样:

清单13

在视图目录(这里是views)创建一个叫做example.php的文件:

清单14 –

现在,当请求网站的根的资源时,应该可以看到example.php的内容。虽然现在这还不是很有用,不过记住你的工作目标是按照一个结构化、有组织的方法来开发Web应用。

为了更清楚地利用Zend_View,将模版(example.php)修改一下,包含一些数据:

清单15

添加了两个额外的特性。$this->escape()方法必须用在所有的输出上。即便你要自己创建输出(例如这个例子中的),也要将所有的输出进行转义,这种好习惯可以防止出现跨站脚本(XSS)。

$this->title$this->body特性在这里是用于演示动态数据的。它们应该在控制器中定义,所以让我们修改IndexController.php来给他们赋值:

清单16

现在你再浏览网站,应该看到了模版所使用的这些值。在模版中使用$this的原因是模版是在Zend_View的实例的范围内执行的。

记住example.php仅仅是一个普通的PHP脚本,所以你可以在其中做任意你想做的事情。最好还是尽量遵守规则,仅仅在模版中进行显示数据的工作。控制器(或者是控制器进行分配的模块)则应该承担所有的业务逻辑。

在继续讲之前,我要最后对Zend_View做一个补充。在每个控制器的方法中实例化$view对象会要额外输入很多东西,而我们的主要目标是更简单、更快速地进行开发。而且,如果模版都存放在同一个目录下的话,每次都要调用setScriptPath()也是一件麻烦事。

幸好,Zend类包含了一个注册表,它可以帮助我们消除这种反复的工作。你可以使用register()方法将$view对象存放在注册表中:

清单17

可以使用registry()方法来获取它:

清单18

从今往后,本教程就会使用注册表了。

Zend_InputFilter

The last component this tutorial covers is Zend_InputFilter. This class provides a simple but rigid approach to input filtering. You instantiate it by passing an array of data to be filtered:

清单19

他会把数组($_POST)设置为NULL,这样就不可能再直接进行访问了。Zend_InputFilter提供了一些根据特定条件筛选数据的方法。例如,如果你需要$_POST['name']都是字母,可以使用getAlpha()方法:

清单20

传给每一个筛选方法的参数是对应要进行筛选的数组元素的键。该对象(在这个例子中是$filterPost)是一个包含了有错误的数据的保护笼,这使得对数据的访问更加可控和一致。因此,当要访问输入数据的时候,应该使用Zend_InputFilter

Zend_Filter提供了一些静态的过滤方法,这些方法和Zend_InputFilter的方法遵循同样的规则。

创建一个新闻管理系统

尽管预览版还包含了很多组件(甚至还有更多的正在进行开发),但是只需要使用前面讨论过的组件就可以构建简单的应用了。在构建应用的过程中,你就会对框架的基本结构和设计有一个更加清晰的理解。

每个人开发应用的方式都有所不同,所以Zend Framework尽可能地尝试包容这些差异。同样,本教程是根据我的偏好写的,所以你可以将它们调整为适合自己口味的方式。

当我开始开发某个应用时,我是先从界面开始的。这并不是说我喜欢做表面文章,花大量功夫在样式、图片上,其实我是站在一个用户的角度来透视问题。这样,我将一个应用看作是一系列页面的集合,每个页面对应一个唯一的URL。这个新闻管理系统有以下一些URL组成:

清单21

马上开始根据控制器考虑这些URL。IndexController显示新闻、AddController处理新闻和评论的添加,AdminController处理诸如审批新闻之类的管理工作,以及ViewController用于查看指定的新闻条目和相应的评论。

首先,如果有FooController.php,先将其删除,并修改IndexController.php并添加合适的动作,并加入一些关于业务逻辑的注释放着:

清单22

下面,创建AddController.php:

清单23

注意AddControllerindexAction()不应被调用。只有当请求的路径是/add时才会调用这个方法。因为用户也许会手工输入URL,还是有可能会被调用的,所以这时应该将用户重定向到首页、显示一个错误或者你觉得合适的动作。

下面,创建AdminController.php:

清单24 –

最后,创建ViewController.php:

清单25

AddController中的一样,index()方法应该是不可能会被调用的,所以可以在其中安排任何动作。ViewController和其他的有些不同,因为还不知道什么是有效的动作。为了能支持类似/view/23这样的URL,必须使用__call()来支持动态动作。

与数据库进行交互

因为Zend Framework的数据库组件相对还不太稳定,同时我又希望例子更容易使用,所以我使用了SQLite的类来存储和获取新闻条目以及评论:

清单26

当然,你可以用自己的解决方案来替换这个类。包含它只为了提供一个完整的例子,并不是给出一个推荐的实现。

这个类的构造器需要获得SQLite数据库的完整路径和文件名,数据库必须事先创建好:

清单27

这只需要运行一次,然后就只要将完整的路径和文件名传给Database类就行了:

清单28

整合

为了能将所有的东西放到一起,先在lib目录中创建Database.php,这样loadClass()就能找到它了。而index.php文件现在要实例化$view$db并将它们存储在注册表中。也可以创建一个叫做__autoload()的函数来自动加载所有需要用到的类:

清单29

下面,在视图目录中创建一些简单的模版。index.php文件可以用于显示index视图:

清单30 –

view.php 模版可以用于显示特定的新闻条目:

清单31

最后,admin.php模版可以用于审批新闻条目:

清单32

为了简单起见,就使用一个带密码的表单作为访问控制机制。

放好了这些模版之后,就只要将原来放在控制器中占着位置的注释替换成几行代码。例如,IndexController.php就变成了:

清单33

组织好所有的东西之后,应用的首页的完整的业务逻辑就被减至四行代码。AddController.php还要再处理一下,需要更多的代码:

清单34

因为用户在提交了一个表单之后被重定向了,所以在这个控制器里面不需要视图。

AdminController.php中,要处理两个动作,显示管理界面和审批新闻:

清单35

最后是ViewController.php:

清单36

这段代码提供了一个功能完整——虽然非常简单的——的新闻共享和评论的应用。最好的地方就是借助于框架优雅的设计,添加更多的功能十分简单,同时随着Zend Framework的逐渐程序,各方面都会变得更好。

更多资料

本指南仅仅是讲解了一些皮毛,还有一些其他的资源可以参考。除了官方手册之外,Rob Allen提供了一些他对于Zend Framework的详细感受,Richard Thomas也给出了一些有用的注释。如果你有自己的看法,可以在本页上留下留言说出自己的想法。

结语

不过还是能发现这个预览版有些粗糙,我自己写这个教程的时候,遇到过一些挫折。不过整体上来说,我认为Zend Framework兑现了大部分承诺,同时所有的参数者依然在继续努力改进它。Chris Shiflett 是 Brain Bulb——一个专于PHP开发和安全性的咨询公司—— 的主席,你可以阅读一下Chris的Blog或者访问Brain Bulb的网站

什么是 Cake?

Cake 是一个针对PHP的,使用了诸如ActiveRecord、Association Data Mapping、Front Controller和MVC等知名设计模式的快速开发框架。我们的主要目标是提供一个可以令各种层次的PHP用户快速地开发出健壮的Web应用,而又不失弹性。

为什么使用 Cake?

  1. 灵活的许可证MIT License
  2. 完全自主的知识产权:每一行代码都是由CakePHP开发小组写出来的。
  3. 极其简洁:只要看看名字就知道了……
  4. 快速开发:开发之迅速史无前例。(看看zZine的文章
  5. 最佳实践:Cake很容易理解,而且已经把工业标准设置在了安全性、会话处理和其他的东西中。
  6. 面向对象: 无论你是一个老练的OO程序员还是一个初学者,都可以感到十分轻松。
  7. 无需配置:只要安装好数据库,好戏就开场了。

厌倦了不断重复?总是Ctrl-C然后Ctrl-V代码?想让你的应用更快速地转化成产品?请选择Cake!看看Wiki立刻上手。

关键特性

  • 兼容 PHP4 和 PHP5
  • 提供了集成的数据库 CRUD 和简化了的查询
  • 请求分配器,和美观的、可自定义URL。
  • 快速、灵活的模版机制(使用PHP语法和助手方法)
  • 可以从任何网站的子目录中运行,只需要少量甚至无需改动Apache的配置。

立刻加入

我们一直在寻找人手来帮助我们写指导、进行测试和书写文档。参与的最佳地点就是IRC。我们正在完善一些针对希望对这个项目编写代码的贡献者指导方针。当然,任何人都可以提出您宝贵的意见和建议。
#cakephp at irc.freenode.net ? CakePHP Wiki ? CakePHP Google Group ? CakeTRAC (development site)

指南

Ma client server简明教程

翻译:ShiningRay @ NirvanaStudio
原文地址:http://minnow.cc.gatech.edu/squeak/2978

{译者:Ma client server是针对Smalltalk的一个网络应用框架,由于十分好用,介绍到这里来}

简介

Ma client server 可以帮助你非常方便地书写客户端/服务器端(Client/Server,以下简称C/S)程序。事实上,它容易到了服务器段程序只要用一行代码:

MaServerSocket new listenOn: 12345 answer: [ :requestByteArray | 'Hello world!' asByteArray ]

这个框架实际上是基于一个稳定可靠的、多线程的Socket模型,是由John McIntosh分享给我的。

在C/S模型中,一个客户端向服务器段发送一个请求,然后服务器处理请求并返回一个应答。

这个框架提供了相互配合的两层结构。你选择其中你想使用的一层然后写两个程序。一个客户端程序会给远程服务器发送请求,服务器上则运行着另一个程序处理请求。

如果你选择较低的一层,“套接字层”(Socket Layer),你发送的是ByteArray(字节数组,一个基本类)的请求,接收的是ByteArray的应答。在较高一层,“对象请求层”(Object Rquest Layer),你可以发送任意的请求对象,获取任意的对象作为应答。较高层上使用了“Ma对象序列化”(Ma Object Serialization)框架来将对象转换成ByteArray,然后让较低的一层为你把这个ByteArray发送出去。

使用套接字层

建立服务器

如果你只是要发送和接收ByteArray的数据,你可以随便写你的服务器程序。但记住,不管在哪里,你要接收ByteArray作为输入,你就必须应答一个ByteArray

然后,要启动服务器:

myServerSocket _ MaServerSocket new
listenOn: 12345
answer:
[ :requestByteArray |
... 将 requestByteArray 传给你的服务器端程序 ... ]

MaServerSocket 利用了 SharedQueue和后台进程来确保处理过程不会因在网络上发送和接收ByteArray数据而阻塞,现在发送和接收完全在后台进行。“answer”块一次对一个客户端请求进行执行。

当你完成之后,一定要关闭套接字这样资源才能正确被释放:

myServerSocket shutdown

在客户端获得应答

下面客户端程序建立了一个MaClientSocket对象,要将IP地址作为ByteArray中的数字指明:

mySocket _ MaClientSocket hostAddress: #(192 168 1 1) asByteArray port: 12345.

建立了套接字之后还没有进行任何连接。只有在你发送请求的时候才会发生:

responseByteArray _ mySocket sendData: myRequestByteArray

同时具有一个sendData:startingAt:count:waitForReplyIn:方法可以达到最大的效率。如果你提供作为返回的ByteArray 不够大,你就会得到一个更大的。

可选的套接字事件

MaServerSocket 要用到一个 “server”, 默认是一个MaServer对象不过它什么也不做。但如果你给MaServer派生子类并且重写其中一些方法,这些方法会在如下时候调用套接字加入队列、一个ByteArray请求完全抵达,或者是发送一个响应等等。详细信息见MaServer

使用对象请求层

如果你选择使用对象请求层,你发送“请求”对象并获得某种应答对象。这样你可以专心写客户端和服务器程序,而不用关系如何解析ByteArray了。

建立服务器

这里当你准备开始写你的服务器段程序时,不是建立一个MaServerSocket对象,而是建立一个MaTcpRequestServer对象:

myServer _ MaTcpRequestServer protocol:
{ MyRequestClass1.
MyRequestClass2.
MyResponseClass1.
MyResponseClass2.
OrderedCollection.
Dictionary. "etc." }.

这是什么?是的,你必须告诉她你要发送和接收的所有类,来记录你请求对象的形式。例如,如果你有一个 SubmitArticleRequest类,里面有一个Article对象,你不仅要列出SubmitAritcleRequest类,还要给出Article和所有其他Article引用的类和这些类他们引用的类,如此继续。然而,你不需要给出String, ByteArray, Set, Symbol, SmallInteger, Float, True, False或者UndefinedObject等类。这些类已经自动成为协议的一部分了。

也可以指明一个MaServerConsole来接收事件。派生MaServerConole并改写他的一个通知方法,象下面这样,他就会被自动调用。

myServer _ console: myConsole

当你准备启动服务器时,你要使用 processOn:do:

myServer
processOn: 12345 ;
using:
[ :requestObject |
... 将 requestObject 传递给服务器程序,可以应答响应 ... ]

当完成之后,你需要关闭并释放系统资源:

myServer shutdown

建立客户端

你的客户端程序建立一个 MaTcpRequestServerLink 并指向服务器所监听的地址 hostAddress 和端口 port

myLinkToServer _ MaTcpRequestServerLink hostAddress: #(192 168 1 1) asByteArray port: 12345

在你要做任何事之前,你必须先建立连接。这确保你在客户端的镜像中包含了所有必须的协议 (如果没有就会抛出异常)。

myLinkToServer connect

如果要在网络状况和你的耐性做出平衡,你可能想改写默认的超时期限为30秒:

myLinkToServer timeoutSeconds: 30

在客户端获得应答

现在你已经连上了,你的客户端程序可以如下从服务器端获得应答:

myLinkToServer submit: someRequestObject

记住, someRequestObject 必须是协议的成员之一,同样你从submit:取回的应答对象也必须是协议之一:

好了!当你完成之后,别忘了断开连接这样你可以将网络资源还给系统

myLinkToServer disconnect

有趣的Morphic图形系统

教程: 有趣的Morphic图形系统

作者:John Maloney
翻译: @ NirvanaStudio
原文地址:http://static.squeak.org/tutorials/morphic-tutorial-1.html

这篇教程要用在Morphic工程中。要建立一个Morphic工程,只要在Squeak窗口的背景上点击鼠标,不要再任何其他窗口上,出现了屏幕菜单。选择“open….”并选择“project(mophic)”。一个小的桔色的“Unnamed”Morphic工程窗口就出现了。点击窗口中间可以放大到全屏幕。(如果你不确定你在什么地方,只要探出屏幕菜单——如果标题是“World”,那你已经在Morphic工程中了)

首先我们需要建立一个浏览器“Browser”和一个工作区“Workspace”。先复习一下,在Squeak屏幕的空白处按下鼠标左键。在出现的屏幕菜单上选择 ”open…”。点击“browser”。一个绿色的浏览器就出现了。再次利用这个屏幕菜单,选择 ”open…” ,并选择“workspace”。

如果你是一个新手,刚刚看完前面的教程,你应该已经有一个叫“My Stuff”的分类。把浏览器最左边的列表拉到最底端,应该就放在那里。

如果没有,我们需要新建一个地方来添加你的东西。在浏览器的左上面板中,点击右键呼出菜单[Option-click] (在苹果机上 – 教程以下都将Mac苹果的指令以这种方式显示)选择“add item…”并输入“My Stuff”并按回车。把列表拖到最下面,你会发现它已经被选中了。

我们再次白手起家,建立一个程序。我们先从一个空的类开始,这里我们要让他成为Morph的一个子类。在Morphic对象系统中,Morph是一个通用的图形类。我们现在看一下建立新类的一个模版。修改成下面这样:

Morph subclass: #TestMorph
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'My Stuff'

首先选择“Object”并输入单词“Morph”(M一定要大写)。选择“NameOfClass”并输入“TestMorph”。新建立的类就会成为Morph的一个子类。删除实例变量名和类变量名的文字内容。按Alt+s接受。[Command-s]

现在我们来到工作区并新建一个我们刚刚建立的类的实例。输入:

TestMorph new openInWorld.

选择这行并按下Alt-d [Command-d]或者从右键菜单中选择“do It” [Option-click]

一个新的图形对象——一个蓝色的方块,现在出现在左上角。这样你就搞定了一个图形对象,虽然几乎没写什么代码。你可以拾起这个对象并移动它。现在先用鼠标把它抓起来。注意了,当你拾起这个Morphic对象的时候,他下面投射出了一个阴影。这个可以帮助你确定你已经确切的把他抓起来了,而且在其他任何物体之上。如果有对象覆盖在上面,抓起这个对象会自动地把他拉到最前端,这时投影就会显示它现在在其他任何物体之上了。

你可能注意到奇怪的大写方式,但是在Smalltalk中,一个选择器只能是中间没有任何空格的一个字符串。所以我们约定在每个英文单词的第一个字母大写,然后去掉中间的空格连起来。其他语言也常在单词之间使用下划线或者破折号。

halo labels.gif
现在按住Alt并单击 [Command-click]这个蓝色的东西,这时你会看见一组不同颜色的小圈环绕在周围,我们称之为“光环”。这些光环每一个都是向这个Morph对象发送指令的一种快捷的途径。如果我的鼠标停在任意一个圆点上,一个小小的帮助气球会弹出来告诉我这个圆点能做什么。这个黑色的点上的气球说:“Pick up”。也就是,如果我拖动这个黑色的把手,他可以像我直接拖动这个蓝色方框一样。这样可能看起来是一个多余的功能,但是因为可能有时候Morph对象会有交互的行为,比如按钮,这个把手让你可以直接操作一些直接和鼠标动作相关的对象。

这里一个基本的想法是,大多数系统,如HyperCard,依靠模式来改变对象的大小等等。也就是编辑一个对象针对使用它是分离的。在Mophics系统中,你可以在任何东西上面使用光环不用考虑他是如何活动的。光环是在它运行时的一种安全的处理方法。你不需要中止他的按钮功能或者是其他的东西。如果这个东西是一个按钮,你可以无需激活就可以编辑它,也不需要关闭它。

让我们来看看光环到底能做什么。比如这个绿色的,它会产生一个副本。粉红的光环中的X会将它删除(移动到垃圾桶中)。另一个常用的功能是改变它的尺寸,由这个黄色的实现。现在暂时不要对它做其他事情了,尤其不要使用蓝色的按钮(在对象的左下角)。

现在让我们开始制作我们自己的对象吧。我们先写一些方法来自定义它。

我要做的第一件事情是让我们的对象在你用鼠标点击他的时候做点什么。这里我们要实现两个方法。点击浏览器,选中第三个面板中的 “no message”。把下面的代码粘贴到底部的面板并接受,Alt-s[Command-s]

handlesMouseDown: evt
^ true

如果这是我第一次在这个映像中接受一个方法,我必须先输入初始值,这个值将会跟着我修改方法一直记录。这个方法,handlesMouseDown,告诉Morphic对象有一个对鼠标敏感的东西。

下一个方法我们要添加的是当鼠标按下的时候实际要做的事情。继续,把下面的代码粘贴进去成为另一个方法。

mouseDown: evt
self position: self position + (10 @ 0).

将在你点击它的时候,这个代码会让对象向右边移动10个像素。试着点击这个对象看看会发生什么。

在这时我们已经有了两个方法。一个返回“true”说我们需要响应mouseDown:事件。第二个是对鼠标按下事件做出的响应,移动了对象的位置。

现在我想给这个Morph对象一些行为来重新绘制它自己。把这个方法粘贴到浏览器中并用Alt-s接受 [Command-s].

drawOn: aCanvas
| colors |
colors := Color wheel: 10.
colors withIndexDo: [:c :i |
aCanvas fillOval: (self bounds insetBy: self width // 25 * i + 1)
color: c].

现在,当你点击对象的时候,你会看到对象的完全不同的外观。让我们回头看看这个方法究竟做了什么。

这个方法的第三行(代码的第一行)是给临时变量‘colors’赋值。如果你看到两个竖线和一列变量名,那这些变量就是这个方法的局部变量,通常可以叫做临时变量。在Smalltalk和Squeak中,你可以不用自己声明变量——如果确实有系统会自动询问你。而且我们也没有任何“类型”所以你不用声明任何类型。任何变量都可以存放任何对象。所以我们把表达式(Color wheel: 10)的值赋给‘colors’。要显示这个方法作了什么,选择‘wheel:’并按下Alt-m查看实现器。你会看到有两个实现——选择Color class的那个。

我们在Squeak中经常做的一件事情是在方法之前放上一小段注释。第一行说了‘wheel:’是干什么的。他返回一个thisMany colors的一个集合,thisMany是一个参数。这些颜色会均匀分散在色环上。这是颜色的光谱。

如果很方便可以给出这个方法的一个例子,这也是我们经常做的。这里第二个注释是一个表达式你可以实际运行的。选中引号中的内容并按下Alt-d。在屏幕的最上方出现了一条展开的色环。这时一个在光谱上间隔的一些颜色的集合。(但不是最大饱和也是最大亮度,所以他们不会太刺眼。

在这个世界里面我们可以直接在屏幕上涂鸦,但他之后不会自动清除。所以我使用了屏幕菜单的“restore diplay”菜单项来去掉那些画在屏幕顶部的东西。

了解“wheel:”的含义在这里有点偏离主题了。我们知道现在这是一些颜色的集合。点击标题栏左边的 “X”关闭窗口。

这个方法的下一部分遍历这个颜色集合。

"下面是drawOn方法的一部分:"
colors withIndexDo: [:c :i |
aCanvas fillOval: (selfbounds insetBy: self width // 25 * i + 1)
color: c].

withIndexDo: 消息同时提供了一个颜色元素“c”和一个索引“i”,让我们能跟踪我们在列表中的位置。第一次循环索引会变成1,第二次是2……如此继续,直到10。我们只需要知道我们在列表中的哪个位置并增加缩进,让椭圆每次更小。我们发出消息”fillOval:color:“并在带上加上了括号的参数——一个矩形,比外部的矩形尺寸上缩小了 (((self width)// 25) * i + 1)像素,由(self bounds)返回——第二个参数是一个颜色。作为索引,i增加,缩进也增加,每次返回一个更小的嵌入矩形,每个矩形里面我们都会画一个椭圆并用颜色c填充。

当我们再看这个对象时,我们看见了10条颜色。这个看起来很不错啊,同时由于使用了发送给自身的消息“width”,作为他的一个参数,它就可以知道它实际上有多大。用Alt-点击[Command-click] 呼出光环并拖动黄颜色的点。你就可以改变它的大小了,不管变成什么尺寸,他都会一直重新绘制自身。

我下一个想做的事情是点击他并调用一些动画。既然这样那么第一件要做的事情是建立一系列的点。当我点击这个对象的时候,我希望他会沿着每个点来回移动直到所有的点都走过了。为了这个想法,我需要做些工作

Morph subclass: #TestMorph
instanceVariableNames: 'path'
classVariableNames: ''
poolDictionaries: ''
category: 'My Stuff'

回到浏览器,并点击“instance”按钮。然后会出现TestMorph的类定义。然后点击实例变量名的位置,在单引号中间,并输入“path”。这个会成为一个新的实例变量来保存一个显示我们对象位置的点的列表。现在我要点击名称为 “as yet unclassified”的消息分类。

当我添加了一个实例变量,我要知道它应该初始化为什么内容。当我们给TestMorph定义这个消息:

initialize
super initialize.
path := OrderedCollection new.

这一行代码“super initialize”为什么出现在这里?虽然类TestMorph的定义看起来十分简单,但path并不是他唯一的实例变量。在浏览器的第二个面板中,右键点击出现一个菜单,选择“inst var refs”,你会看见一个列表,里边列出了这个对象从超类继承的其他变量。我这里不想选择其中任何一个。如果我做了,他会把所有用到这个实例变量的方法列出来,不过,你可以看到这里有自类Morph继承的6个实例变量。

“super initialize”给我的超类,Morph类发送了初始化消息。当你给接收器“super”发送消息“initialize”的时候,他其实是发送给“self”,但是要保证是被继承的initialize的版本被调用。

我们的初始化的中心是:“ path := OrderedCollection new”。它将一个空的集合赋值给path。现在当我的TestMorph接收了发送的intialize消息,他首先完成Morph要做的初始化,然后,他再完成它自己的初始化。结果是所有从Morph继承的实例变量包括我新添加的都被初始化了。

我们实际上在这里又有一个约定,一般不会自动给一个新的对象发送“initialize”消息。但是,Morph对象总是给每一个新的Morph实例发送初始化消息。

这个TestMorph对象,现在就在屏幕上,并没有对我们新的代码获得初始化。我们在定义了新的 initialize 之前就创建了他。让我们先把它删除并做一个新的。用Alt-点击 [Command-click]呼出对象的光环。点击里面带个 X 的粉红色圆圈来删除这个对象。他现在被扔进了垃圾筒了。现在我们执行下面的代码来搞一个新的TestMorph(也许这次就可以初始化好了):

TestMorph new openInWorld.

我们现在要当你在我们的对象上点击鼠标的时候,让他做点什么事儿。我们现在已经有了一个“path”集合。把下面的方法复制进去并且接受:

startAnimation
path := OrderedCollection new.
0 to: 9 do: [:i | path add: self position + (0@(10* i))].
path := path, path reversed.
self startStepping.

我们在第一行创建了一个新的 OrderedCollection。在下一行,我们作了10次计算并把表达式的结果加到变量path上。我们保存了相对于目前位置的一些点,”self position”,加上一个我建立的点。建立的点的X坐标是0,“@”(可以建立一个点)后面的,Y左边是i的10倍,“i”是循环的变量,从0到9每次增加1。所以,最终的效果是建立的10个点,Y坐标是从当前坐标加上(0的10倍)到(9的10倍)并把这些新的点添加到path集合中。

接下来一行,我们把path扩展为(path, path reverse)。“reverse”会将任何集合用相反的顺序放置。逗号(“,”)操作符是另一个消息选择器用来连接两个集合。

我们所做的是把一个10个点的列表,从0到90,并且附加上一个列表,从90返回到0。这样我们现在就有20个点,出发并最终回到原来的位置。

该方法的最后一行把我们的Morph对象登记在一个可以持续发送“step”消息的一个引擎中。这是动画引擎的秒针,是动画的心跳。现在我们必须让我们的Morph对象理解step方法:

step
path size > 0 ifTrue: [self position: path removeFirst].

这个方法很容易理解。它说只要在点的列表中还有东西,也就是只要path集合的长度大于零,就移动自己。给自己发送消息“position”,并将从点集合中删除的第一个点作为参数传送进去。他在做每一步的之前检查并确保表中确实有东西可以删除。

从图象上看,它会立刻跳到下一个点。

现在这些东西都已经设置好要准备运行了,但是,他并没有开始动画。好吧,那是因为我们并没有真正通过向他发送开始动画的消息,所以我们才没有把这个球踢出去。我非得要做的一件事就是要试着找出发送消息给这个对象的途径,其实有一个最方便的方法就是让他自己给自己发消息,当鼠标按下的时候。

mouseDown: evt
self startAnimation.

这里有两种途径可以定义这个方法。你可以在任何现有的方法上粘贴(在浏览器下面的面板中),或者你可以点击“mouseDown”在右边的面板中,并修改我们现有的mouseDown。其实当你接受的时候都是一样的。

当你完成了上面的,再去点击你的Morph对象,你应该能看到发生了一些东西,它动了,太好了~,但是,他动得十分十分十分得慢。哎~,我失望了因为我以为Sqeak是很快的。其实呢,是默认仅仅每秒钟才给对象发送一次“step”消息.但是对象可以决定它自己需要多久被通知要执行“step”,我们只要实现一个消息“stepTime”:

stepTime
^ 50

它返回对象要求的 step 消息的时间间隔(以毫秒计)。现在,明显你可以要求两次 step 消息之间是 0 秒,但是你不会成功。这里存在一个基本的判断。

现在如果我们再次点击我们的对象,我们就能看到一个快得多的动画。我现在把它改成 10 毫秒,看看能不能达到每秒 100 帧。让我们看看能不能成功。好的,我不知道我是不是真的达到了 100 帧每秒,不过他看上去确实很快。

你知道,我是给“动画公司”工作的。这个动画起始并立刻停止,同时每个人都知道还有“渐进”和“慢出”来让他看上去更优雅。这里有一个小小的改进,使用了“i”的平方来让动画开始的时候比较慢。

startAnimation
path := OrderedCollection new.
0 to: 29 do: [:i | path add: self position + (0@(isquared / 5.0))].
path := path, path reversed.
self startStepping.

我只更改了这个方法里面的一行。我们现在准备在path中建立30个点,然后附加上反转的,一共60个点,另一个需要更改的是替代10次。最后,表达式将会是“841 / 5”。

现在动画就是开始下落时比较慢并且加速然后在他回来时又慢下来。事实上,他看上去像某种球在弹跳。

现在是一个很好机会让你自己和预先制作的Morphic对象玩玩乐。我们先拿一个装满对象的容器。如果你的系统中启用了标签,点击屏幕底部的 “Supplies”标签。如果底部没有标签页,使用屏幕菜单并选择“authoring tools…”。选择“standard parts bin”。无论什么情况你都能获得一大帮对象你可以拖到屏幕上,在你拖出来一个之后,Alt-点击[Command-click] 呼出光环,并按住红色圆圈呼出对象的内容菜单(contents menu)。这里是一些Morph对象:

  • A RectangleMorph (内容菜单中, 试试 “raised bevel” 和 “insetbevel”)

  • An EllipseMorph

  • A StarMorph

  • A CurveMorph (内容菜单中, 试试 “show handles”)

  • A PolygonMorph (f内容菜单中 , 试试”show handles”)

  • A TextMorph (可以用黄色的把手把文字块加宽)

  • [ignore the gradient filled Sketch Morph for now]

  • [ignore the green PasteUpMorph]

  • 画家的调色板可以在你丢下的位置开始新绘制一幅图。画完后,点击“Keep”按钮把图案变成Morph对象

  • [ignore the StringMorph]

什么是REBOL?

翻译:ShiningRay @ NirvanaStudio

简而言之,REBOL是提供了分布式计算和通信的一种轻量级软件技术。

REBOL技术包含两个部分:

REBOL语言

REBOL语言结合了编程语言和元数据语言(如XML)的概念。

这种结果是产生了一种新的语言,它提供了对现代网络分布应用的更有效解决方案。相比传统的语言,REBOL在更少的代码上提供了更强大的表达能力。REBOL应用程序和解决方案的一般典型的代码大小都在10KB的数量级上,而不是10MB。

REBOL发音为“reb-ol”(类似“rebel with a cause”中的),代表“基于相关表达式的对象语言”(relative expression based object language)。他第一次发布是在1997年到目前为止已经下载超过四百万次。他对客户端和服务器端应用程序都是十分合适的,就像下面所描述的。


你可以在《REBOL到底哪里不同》一文了解更多内容或者想迅速浏览一下REBOL语言的介绍,请看《REBOL 语言简介》。

X-Internet平台

X Internet是指可执行互联网(executable Internet),它是Internet发展的下一个阶段。

X Internet概念是本地计算机(客户端)成为像网络服务器一样强大,这样更多的计算责任可以被转换到客户端完成。这种方式由三个好处:

  1. 他改善了用户体验的质量。
    他让Internet应用程序运行的像本地应用程序一样快。Web设计造成的延迟不复存在。

  2. 他提高了服务器的性能。

    由于客户端作了更多的工作。这就让你在同一台服务器上可以进行的连接次数大大增加。现在典型的是大约10到50倍于原来的连接数量。这就好像以一台的代价可以做10-50台或更多服务器的事。

  3. 他使得网络通讯更加有效。

    应用程序不需要每次连接都传送用户界面信息(如:网页)。取代的是指需要发送用户产生的动作相关的数据和代码。这让X Internet程序仅仅占用目前典型Web应用程序所用带宽的1/10到1/50。

是不是说X Internet反对“瘦客户端”计算模型?当然不是,如果你使用REBOL。因为REBOL的先进的语言设计,X Internet应用程序将和大多数基于web的解决方案比,显得特别得小。这就是我们所谓的轻量级。当应用程序构建得较为完善,他们将花费更少的时间和金钱来进行开发,并且很容易维护和升级。

如果要了解X Internet和REBOL解决方案,请参见我们的IOS概览页面

FIT 简介

Fit: Framework for Integrated Test

优秀的软件需要协作和沟通,在开发过程中,客户如何才能知道他们的程序员如何正确处理了事情呢?而程序员又如何知道客户究竟想的是什么呢?测试人员如何才能知道什么是正确的而什么又是错误的?让这些小组能有效和精确地交流应该是团队创建伟大软件的一个目标。

FIT就是一个用于增强交流和协作的工具。FIT创建了一个在客户和程序员之间的反馈循环。FIT让客户和测试人员可以使用诸如Microsoft Office之类的工具来给出程序应当如何表现的例子——而无需成为直接编码的程序员。FIT自动针对实际的程序检测那些例子,这样就在业务世界和软件工程世界之间建立了一个简单而且有效的桥梁。

有了FIT,客户可以通过将他们的主题相关的专业知识和想象引入实际的工作中,给开发过程直接提供更多的指导。客户所获得的更多关于目前产品开发中正在发生的东西的可见性,能让他们随时控制项目避免偏离目标。

==FIT如何工作==

FIT通过读取由类似MicrosoftWord之类的工具生成的HTML文件中的表格来进行工作。每一个表格通过一个程序员写的“装置”来进行解释。装置将通过运行实际的程序来检测表格中的例子。

在这个例子中,团队要建立一个产品用于计算职工的薪水。团队已经一起创建了一个包含一些如何计算小时薪水例子的FIT文档。

表格包含了例子。第一行告诉了FIT如何读取表格。第二行给出了例子的头,剩下的行给出了例子。例如,在第一个表格中的例子说:“如果某人工作了40个工时同时没有休息时,那么就付给$20每小时的薪水,然后他的总薪水是$800。”

(虽然这个例子只使用了一个简单的表格格式来展示计算的结果,其实还有很多不同的表格格式可以使用。)

FIT自动针对软件检验表格中的例子。在我们这个例子中,对前两个测试案例,软件给出了正确的解,所以FIT把表格单元标示为绿色。在最后一个测试案例中,软件给出了错误的解,所以FIT把这个表格单元标记为红色。这个软件说职员的总薪酬是$1,040,而期望的值是$1,360。


为了能让FIT能使用这个表格工作,团队的程序员创建了一个“装置”来告诉FIT如何和他们的软件交流。情况类似下面:

程序员使用了一个ColumnFixture来将表格中的列映射到装置中的变量和方法上。前三列,提供了信息,对应于装置中的变量。最后一列,包含期望的值,对应于装置中的Pay()方法。要计算答案,程序员使用他们程序中的WeeklyTimesheet类。

==总结==

FIT给予了客户和程序员一个关于软件的精确交流的方法。客户所给的具体的例子让程序员能深刻理解将要构建的产品。程序员的对于装置的工作和软件可以让客户给出不同的例子进行试验来获取对于软件如何真正工作更深入的了解。这样通过一起工作,整个团队可以学会更多关于产品的内容并产生更好的结果。

Io语言

“动态语言”现在是一个很时髦的术语,常用来表示那些编程语言十分地具有弹性而且很合适“敏捷”开发环境。在这种趋势背后有一些很有趣和很强大的语言,Io就是其中一个十分重要的语言。

Io最早发布在2002年,它混合了Lua、Lisp、Smalltalk和其他一些语言的某些方面的一个小语言。而起初的大想法是要把Io作为一个完整的可视化编程语言的基础,就像Self一样。

概览

Io属于“解释型”语言家族(像Perl、Python等等),这种语言的代码并不是通过编译而至直接解释并运行的。和很多“解释型”语言一样,Io也是高度动态的:一个程序可以迅速地生成并解释新的代码。同时,Io通过采用了Lisp的“代码即数据”的模型让这个特性向前迈进了一步,它可以让任何Io程序访问和处理它自身在内存中的对象模型。毫无疑问,这也让Io成为一个自省的语言。

并发编程在很多应用中都是一个新兴的被关注的方面,尤其是大多数用户界面和Web应用。Io从Act1中获得了灵感并使用了“参与者”(Actor)的概念。参与者介于线程和延续之间,它可以让你更容易编写你的并发应用,而原有的基于线程或者是进程编程的负担则不复存在。

简介清晰在Io的语法和他的对象模型中是显而易见的。语法可读性很好,而且看上去很好地结合了Lisp和Smalltalk。Io的对象模型是基于原型的。一个基于原型的对象模型不使用类来表示泛化和特化,取代的是创建特定的对象来用作“模型”或是“原型”并通过他们来创建新的对象。在这种编程范型中,对象是从原型中克隆出来的而不是从一个类实例化得来的。

对象模型是基于消息的,这表示方法调用甚至是变量访问都是通过发送动态的消息来完成的,而不是“硬布线”的(像C++和Java那样)。同时,Io对象响应消息的方式可以在运行时进行改变,这也是一个很典型的“动态”特性。

Io的足迹很小可以很方便地嵌入C或者是C++应用中。这方面它最有趣的特点之一是他的Objective-C的桥接器,这在集成上达到了一个令人惊奇的程度,在Io中使用你的Objective-C对象几乎不要写任何粘合代码。

Io分析

长处

Io的主要的优点来自他简洁的设计:它是一个可以很快学会的语言因为他有一个简单而且一致的语法、语义和API。由于Io的足迹小,所以它十分合适嵌入式编程。Io的另一个长处是它的速度。它能在性能上胜过很多其他解释型语言,这让他成为密集工作的一个理想选择。

Io的另一个长处——从一个嵌入的角度来看是很有意思的——是你可以重新定义几乎任何运行机制。Io语法中的任何东西都已经转化成了消息,而消息是可以在运行时重新定义的。从这方面来看,实际上你就可以改变里面任何东西来满足你的需求。

同时,Io对于并发编程的解决方案对于Web应用和GUI脚本编程也极具吸引力。

弱点

尽管Io有很多有趣和先进的特性,然而它还是十分年轻。到目前为止它还没有什么值得称赞的开发工具诸如文档生成器或者是代码检查器等等,而且在解释其上面仍然有一些问题。尽管如此,随着Io社群的不断壮大,更多的代码被制作共享,这个“青少年问题”会最终消失。

范例程序

参考

从Trails和Firebird开始

作者:Chris
翻译:ShiningRay @ Nirvana Studio

0. 前言

在Trails的首页上有一段Trails的指导视频,它比本文说得更为详细。你可以看看它,另外根据Firebird设置一节中的内容,设置一下和Firebird相关的东西。

1. 什么是Trails?

Trails是一个领域驱动开发框架,它使用了Hibernate、Spring和Tapestry。其中,Hibernate 被用作数据访问层,Tapestry用来给用户显示数据。而Spring 则是把Hibernate和Tapestry连接在一起。

Trails自带了几乎所以必需的jar文件——你只需要安装一下Firebird的数据库驱动,它可以在 http://firebirdsql.sf.net上下载。

1.1 Hibernate

Hibernate是一个O/RM工具。O/RM的意思是:对象关系映射。O/RM可以让你把 java 对象映射到后台数据库中。Hibernate使用了XDoclet来指明映射信息所需的信息,以便在数据库中存储复杂的对象。而XDoclet使用了javadoc注释来告诉Hibernate如何映射对象。例如:

[code lang=”java”]/**
* @hibernate.class table=”PERSON”
*/

public class Person {
}
[/code]

这段代码会告诉Hibernate要将一个指定的对象(在这里是Person)映射到PERSON表。

Hibernate 的主页是:www.hibernate.org.

1.2 Tapestry

Tapestry 是(简而言之)一个Web框架。更确切地说,Taspetry是一个基于组件的Web框架,它将表示和逻辑清晰地分离开来了。

在Tapestry中,一个页面和一个.html文件相关,这个文件负责这个页面的外观,和一个Java类,它负责对.html文件提供数据,还有一个.
page或者是一个.jwc文件(这由你是要作为一个真正的页面还是一个单独的组件),这两个负责把前两个层次连接起来。

组件是通过ognl语言来访问的,形式如:

jwcid 指明了使用的组件——这里是一个PageLink,它是一个HTML表现中的<a></a>标签的一个组件。page属性指明了你要链接的页面的名称。

Tapestry 的主页在jakarta.apache.org/tapestry

2. 安装Trails。

首先从trails.dev.java.net下载Trails.

当前的版本是0.5.1。先把下载的文件解压缩(在https://trails.dev.java.net上有一个很棒的演示,教你如何利用Trails来写应用程序)。

解压缩trails,并进入新建的文件夹。更改build.properties文件以匹配你的tomcat路径,
然后做以下这些事情:

通过运行下面的指令来创建trail.jar(我在我的机器上必须这样做)

3. 写一个新的应用程序

3.1 创建一个新的trail应用:

这是在问你,把工程的根目录放在哪里(在MacOS X上我输入的是/Users/chris/Desktop/projects——Windows用户可能要输入诸如c:\path\to\new\project的路径)

输入工程名称

然后,一个目录包括所有必须的jar文件就被创建好了。

3.2 启动

3.3 创建一个新的 “Java Project”

  • 输入工程名称
  • 选择 “Create project at external location”(在外部位置创建工程) 并指向新创建的文件夹。

  • 点击 “next”
  • 点击 “add folders”
  • 选择 “src”,然后点击OK

  • 点击 “finish”

新创建的工程就会被导入到Eclipse中。

4. 设置

4.1 改变tomcat的主目录

  • 打开Eclipse中的open build.properties 文件并将tomcat.home改称你的tomcat的目录。

4.2 更改数据库驱动:

  • 打开文件 context/WEB-INF/hibernate.properties 并把其中的设置改为::

4.3 在主机上创建一个新数据库(这里是127.0.0.1)

并且在 FIREBIRD_HOME/aliases.conf 中添加一个别名,这样写:

在生产系统中,你还要为以后要连接的用户更改用户名和密码 :-)

4.4 安装Firebird数据库驱动

firebird.sf.net下载Firebird的JCA-JDBC驱动,解压缩并把jar文件安装到CATALINE_HOME/common/lib下(详细内容参见 JayBird FAQ)。

5. 开始编码

5.1 创建一个领域对象(Domain Object)

领域对象可以简单地说成是POJO(Plain Old Java Objects),它是Hibernate用来在数据库中存放数据的。

  • 在Eclipse中选择src文件夹并点击 File -> New -> Class(文件->新建->类)
  • 输入一个包名(de.test.data)
  • 在Name输入框中输入类名:Person
  • 点击 “finish”

成功新建并打开了一个类。

5.2 告诉Hibernate要使用的表格:

把表格名称作为XDoclet的hibernate.classabove标签添加到类的说明中。XDoclet任务以 @ 符号开始,后面跟着一个名空间(在这里是hibernate)和一个动作,指明要做什么(更多信息参见hibernate.sf.net)。

XDoclet标签 @hibernate.class table=”PERSON” 将告诉Hibernate把这个对象中的数据存储在一个叫做PERSON的表中。

表格的名称无需和类名相匹配——你也可以指定一个MY_PERSON作为名称 :-)。

5.3 创建属性:

  • 先输入以下内容:

  • 在“Outline”(大纲)中选择PersonID并右键点击它。
  • 选择Source -> Generate Getters and Setters
  • 两个都选中并点击OK

现在已经有了getter和setter例程,而且已经添加了注释。然后我们添加下面的注释:

这将告诉Hibernate使用表格的PERSON_ID列来存储表格的主键,同时通过使用一个生成器来自动新建这个字段的值。
键将由SQ_PERSON_ID生成器来生成。

在大纲中选择name并且右键点击它(选择 source
-> generate getters and setters,选择Name和SurName然后点OK :-) )

这次,我们不再需要主键——我们仅仅需要一个字段来存放姓名。所以我们继续并添加以下javadoc注释:

[code lang=”java”] /**
* @hibernate.property column=”LAST_NAME” not-null=”true”
*/
public String getName() {
return Name;
}
[/code]

以及surname属性

由名称属性而来的getter上的列是必须出现的,因为我们要覆盖默认的行为。Hibernate会假设一个叫“NAME”的字段——但这在Firebird中是一个关键字,所以我们必须另外选择一个名称。

记住:Hibernate标记必须总是设置在getter上——而不是setter。

如果需要,我们可以通过在Hibernate的XDoclet标记中添加not-null=”true”属性来设置一个null值——默认值为false。

5.4 创建查询表

现在提示有一个错误——是LSalutation。

这时把你的鼠标移到LSaltutation上并且按下Ctrl+1(在Apple Macintosh上你要按Command + 1)。然后会出现以下对话框: 

输入要创建的文件的包名,点击“finish”,然后做以下几步动作:

  • 给他一个ID
  • 个它一个名称
  • 生成getter和setter
  • 并且指明给表格设置的类名,以及ID和属性字段

现在,又是另一个对象可以被Hibernate映射了。对于Hibernate,这已经可以用了,但对于Trails,还少个东西:

  • 一个 equals() 和一个 toString() 方法

toString() 方法是用来在列表视图中能正确显示属性,而equals方法是用来标示对象的。所以只要添加以下代码到LSalutation类中:

返回到Person.java中并且为Saltuation属性创建getter和setter。

由于我们要给salutations使用另一个表中的数据,所以这里我们要用另一个属性。所以这里我们要用一个多对一的关系。也就是,我们要把javadoc注释改成:

现在Hibernate已经了解如何引用salutation类了。

这就是我们要写的全部代码了。 :-)

6. 构建应用程序:

打开build.xml文件,右件点击war目标并选择 ant -> build

这将调用ant来构建.war文件(Trails的指南说,使用deploy目标可以部署程序——这不能在我的机器上运行)。然后我把project.war文件复制到TOMCAT_HOME/webapps中去。

7. 访问应用程序:

打开浏览器并输入127.0.0.1:8080/project_name

现在,享受一下浏览和输入数据的乐趣吧 :-)

无任何担保——Chris