互动出版网 专业图书网上第一专营店 独家提供样章 第5章 共享知识:DWk,基于 DWR的Wki 我 还记得之前看过的《呆伯特( Dilbert)》连环漫画,这里我先给你讲述一下。由于完 全是根据记忆,因此可能不一定准确,不过希望不会影响我的讲述 它讲的是一名咨询师正在试图向一位秃头老板推销一些在线协作工具。此刻,这个老板很有 洞察力地对咨询师说,“这些工具不会仅仅帮助那些无知的员工更加有效地共享他们的愚昧吧?” 就在这个时候,咨询师疯狂地鼓吹老板去签约! 你会问重点是什么?难道说《呆伯特》不像一本连环漫画,更像美国公司IT部门的纪实?不, 这是因为在本章我们将构建一个在线协作工具!现在,无论使用它共享无知还是有用的知识,我 们可以简洁地说这不是本书的范畴。 在本章中,将构建一个Wiki,这是在整个Web20运动中比较有用的产品之一。我们当然会 使用DWR为它增加Aax特性(这也正是Wik急需的),从而也为我们提供一个便利的小应用程序, 用于共享知识(或者无知,这取决于秃头老板决策的正确与否)。不再拖延了,让我们开始吧。 (不过,如果你想花几分钟浏览一下呆伯特的漫画,我并不介意。) 51应用程序的需求和目标 那么,确切地说,wiki到底是什么呢?简言之,它是一个Web应用程序,可供用户相互合作 创建一个Web站点。换言之,用户可以创建多个页面(这个页面通常被称作文章),然后将它们 链接在一起。这个链接的过程通常是自动完成的,无须实际编写HIML代码:通常在Wiki上工作 都不会要求使用HTML。在大多数情况下,仅有已注册的用户方可修改和创建文章,因为这里需 要用户承担一定的责任。这个Wiki程序必须处理两个用户同时编辑同一篇文章时可能出现的并发 问题(一般可以通过一个用户在编辑的时候“锁定”文章来解决这个问题)。 当然,Wk通常还有许多其他的特性,这里我们将完成其中的一些特性。我们继续讨论,下 ①如果不熟悉《呆伯特》,强烈建议你放下手中的工作,浏览www.dilbert.com网站。《呆伯特》是美国的一部连环漫画, 里面有许多极搞笑的角色,这些角色来自一家公司的∏部门(是的,好像是I部门,不过我并不能确认里面是否以 某种方式提过 怎样,如果你本身在IT部门工作,而且又在阅读本书,猜想你将会从作者 Scott Adam的漫画创 作中感受到更多的乐趣
共享知识:DWiki,基于 DWR的Wiki 还记得之前看过的《呆伯特①(Dilbert)》连环漫画,这里我先给你讲述一下。由于完 我 全是根据记忆,因此可能不一定准确,不过希望不会影响我的讲述。 它讲的是一名咨询师正在试图向一位秃头老板推销一些在线协作工具。此刻,这个老板很有 洞察力地对咨询师说,“这些工具不会仅仅帮助那些无知的员工更加有效地共享他们的愚昧吧?” 就在这个时候,咨询师疯狂地鼓吹老板去签约! 你会问重点是什么?难道说《呆伯特》不像一本连环漫画,更像美国公司IT部门的纪实?不, 这是因为在本章我们将构建一个在线协作工具!现在,无论使用它共享无知还是有用的知识,我 们可以简洁地说这不是本书的范畴。 在本章中,将构建一个Wiki,这是在整个Web 2.0运动中比较有用的产品之一。我们当然会 使用DWR为它增加Ajax特性(这也正是Wiki急需的),从而也为我们提供一个便利的小应用程序, 用于共享知识(或者无知,这取决于秃头老板决策的正确与否)。不再拖延了,让我们开始吧。 (不过,如果你想花几分钟浏览一下呆伯特的漫画,我并不介意。) 5.1 应用程序的需求和目标 那么,确切地说,Wiki到底是什么呢?简言之,它是一个Web应用程序,可供用户相互合作 创建一个Web站点。换言之,用户可以创建多个页面(这个页面通常被称作文章),然后将它们 链接在一起。这个链接的过程通常是自动完成的,无须实际编写HTML代码;通常在Wiki上工作 都不会要求使用HTML。在大多数情况下,仅有已注册的用户方可修改和创建文章,因为这里需 要用户承担一定的责任。这个Wiki程序必须处理两个用户同时编辑同一篇文章时可能出现的并发 问题(一般可以通过一个用户在编辑的时候“锁定”文章来解决这个问题)。 当然,Wiki通常还有许多其他的特性,这里我们将完成其中的一些特性。我们继续讨论,下 ① 如果不熟悉《呆伯特》,强烈建议你放下手中的工作,浏览www.dilbert.com网站。《呆伯特》是美国的一部连环漫画, 里面有许多极搞笑的角色,这些角色来自一家公司的IT部门(是的,好像是IT部门,不过我并不能确认里面是否以 某种方式提过)。不论怎样,如果你本身在IT部门工作,而且又在阅读本书,猜想你将会从作者Scott Adam的漫画创 作中感受到更多的乐趣。 第5章
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 5.1应用程序的需求和目标80 面列出 WIki将要提供的特性和功能。 口前面提到过,仅有已注册用户能够添加或删除文章(或者给文章加评论)。 口给文章加评论是允许用户讨论某个文章,而无须实际地编辑该文章。所有的用户都能够 阅读这个评论,但只有已注册用户可以加评论。 口实施容器管理的安全,通过DWR与EE安全的集成,封闭适当的远程方法。 口当对文章进行编辑时,需要保持相关历史信息,以便人们能够看到是谁做了什么样的改 动。为简单起见,只记录编辑前后文章的文本(并不是太复杂,比较容易实现)。 提供一个帮助页面,辅助用户理解如何使用 WIki。 口虽然写文章时不要求使用HTML,但使用它可以在文章中包含丰富的内容,而不必创建自 己的完整Wiki语言。 口希望 WIki尽可能得灵活,这样用户就可以尽可能多地编辑可见界面。把尽可能多的界面 当做文章,和其他的一样。其中会存在一些例外情况,为了解决这些例外,将使用一个 名为 FreeMarker的比较灵活的模板系统,并创建一个通用的DWR扩展来使用它,这个扩 展以后也可重用。 口任何以大写字母开头的单词将会被解释成到文章的一个链接。单击这个单词,将会跳到 对应的文章或者占位符,如果文章不存在,用户可以在此创建文章。很显然,并不是所 有以大写字母开头的单词都应该是文章的链接,因此还需要采用某种方法来覆盖这个链 接(这并不需要什么非常复杂的算法,但是必须是有效的)。 口使用数据库来存储Wiki的内容,具体而言就是 Apache Derby。另外,可以采用 Spring库的 JDBC支持来尽量避免自己编写较低层的JDBC代码 口DWik将支持“锁定”文章以便编辑,这个锁持续的时间由配置决定, 般情况下,使用DWR把用户界面连到后台,并且你会发现这样必须撰写的代码量远小于 其他方式。 在真正开始剖析该应用程序的代码之前,先讨论即将使用的几个关键技术,包括 FreeMarke 模板库、 Apache Derby数据库以及 Spring库的JDBC支持 5.1.1 FreeMarker 正是由于我喜欢不时来点新意,因此先讨论 Free Marker。另外,只要可能,我总是会选择偷 懒(我当然崇拜霍默·辛普森的人生原则),因此想借用 FreeMarker主页内容简单讲解 FreeMarker 是什么(如果理解成直接引用,也可以) FreeMarker是一个“模板引擎”,这个通用工具可根据模板生成文本输出(从HML到自动生成 的源码等)。这是一个Java包,为Java开发人员提供了一个类库。这个应用程序本身并不服务终 端用户,不过编程人员可能会将它嵌入到自己的产品中, FreeMarker的设计目的是生成 HTML Web页面,特别是用于基于 servlet的应用程序中,而这些应
5.1 应用程序的需求和目标 80 面列出DWiki将要提供的特性和功能。 前面提到过,仅有已注册用户能够添加或删除文章(或者给文章加评论)。 给文章加评论是允许用户讨论某个文章,而无须实际地编辑该文章。所有的用户都能够 阅读这个评论,但只有已注册用户可以加评论。 实施容器管理的安全,通过DWR与J2EE安全的集成,封闭适当的远程方法。 当对文章进行编辑时,需要保持相关历史信息,以便人们能够看到是谁做了什么样的改 动。为简单起见,只记录编辑前后文章的文本(并不是太复杂,比较容易实现)。 提供一个帮助页面,辅助用户理解如何使用DWiki。 虽然写文章时不要求使用HTML,但使用它可以在文章中包含丰富的内容,而不必创建自 己的完整Wiki语言。 希望DWiki尽可能得灵活,这样用户就可以尽可能多地编辑可见界面。把尽可能多的界面 当做文章,和其他的一样。其中会存在一些例外情况,为了解决这些例外,将使用一个 名为FreeMarker的比较灵活的模板系统,并创建一个通用的DWR扩展来使用它,这个扩 展以后也可重用。 任何以大写字母开头的单词将会被解释成到文章的一个链接。单击这个单词,将会跳到 对应的文章或者占位符,如果文章不存在,用户可以在此创建文章。很显然,并不是所 有以大写字母开头的单词都应该是文章的链接,因此还需要采用某种方法来覆盖这个链 接(这并不需要什么非常复杂的算法,但是必须是有效的)。 使用数据库来存储Wiki的内容,具体而言就是Apache Derby。另外,可以采用Spring库的 JDBC支持来尽量避免自己编写较低层的JDBC代码。 DWiki将支持“锁定”文章以便编辑,这个锁持续的时间由配置决定。 一般情况下,使用DWR把用户界面连到后台,并且你会发现这样必须撰写的代码量远小于 其他方式。 在真正开始剖析该应用程序的代码之前,先讨论即将使用的几个关键技术,包括FreeMarker 模板库、Apache Derby数据库以及Spring库的JDBC支持。 5.1.1 FreeMarker 正是由于我喜欢不时来点新意,因此先讨论FreeMarker。另外,只要可能,我总是会选择偷 懒(我当然崇拜霍默·辛普森的人生原则),因此想借用FreeMarker主页内容简单讲解FreeMarker 是什么(如果理解成直接引用,也可以)。 FreeMarker是一个“模板引擎”,这个通用工具可根据模板生成文本输出(从HTML到自动生成 的源码等)。这是一个Java包,为Java开发人员提供了一个类库。这个应用程序本身并不服务终 端用户,不过编程人员可能会将它嵌入到自己的产品中。 FreeMarker的设计目的是生成HTML Web页面,特别是用于基于servlet的应用程序中,而这些应
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 5.1应用程序的需求和目标81 用程序往往会遵循MvC( Model view Controller,模型-视图-控制器)模式。在MVC模式中使用 动态Web页面就是为了将设计人员(HIML创作者)与编程人员分开。每人都做自己擅长的事情。 计人员可以修改页面的外观,而不必要求编程人员修改或者重新编译代码,因为应用程序逻辑 (Java程序)与页面设计( Free Marker模板)是分离的。模板不会受到复杂的程序片段的千扰。即 便在项目中,编程人员和HIML页面创作者是同一个人,这种分离也是非常有用的,因为这样做 可以保持应用程序逻辑清晰,并且便于维护 虽然 Free Marker具有某些编程功能,但是,它并不像PHP那样成熟。准确地说,Java程序负责准 备需要显示的数据(比如发起SQL查询),而 FreeMarker仅负责使用模板生成文本页面,显示这 些数据。 到底什么是模板引擎 简而言之,模板引擎有时候又被称作模板处理程序,它是一套软件或者用于构建软件的组 件,它以模板作为输入。模板类似于一张套用信函,有很多空白嚅要填写。模板引擎负责将模 板与数据模型(即组织成具有一定格式的数据集合)结合起来,从而生成某种类型的文档输出 如果是普通文本,则可能生成PDF、Excl电子表或者你希望的某种格式。 FreeMarker当然就是 这样一种模板,相信你还熟悉另外一种模板JSP!虽然有些人并没有认识到JSP是一种模板技术 但实际上它确实是。 上面的内容对 FreeMarker做了全面的解释!是的,很全面。我想现在你一定很想看一下 FreeMarker实际上是什么样,对吧?下面的命令将满足你的愿望,代码清单5-1列出一个非常简单 FreeMarker模板。 代码清单5-1 Free Marker模板的 Hello World小例子 Hello, $name), from a Freemarker template These are a few of my favorite things t favoriteThings as thing siting, name) 现在,你可能已经注意到上面引用的 remArker描述中的最后一段,“……Java程序负责准备需要 显示的数据…”这实际上意味着你需要构建一个Map,并填充数据。Map中的数据用于替换模板中的 记号,例如s{name}。在代码清单5-2中,可以看到一个为代码清单5-中的模板创建数据Map的简单例 代码清单5-2使用 FreeMarker的非常简单的例子
5.1 应用程序的需求和目标 81 用程序往往会遵循MVC(Model View Controller,模型-视图-控制器)模式。在MVC模式中使用 动态Web页面就是为了将设计人员(HTML创作者)与编程人员分开。每人都做自己擅长的事情。 设计人员可以修改页面的外观,而不必要求编程人员修改或者重新编译代码,因为应用程序逻辑 (Java程序)与页面设计(FreeMarker模板)是分离的。模板不会受到复杂的程序片段的干扰。即 便在项目中,编程人员和HTML页面创作者是同一个人,这种分离也是非常有用的,因为这样做 可以保持应用程序逻辑清晰,并且便于维护。 虽然FreeMarker具有某些编程功能,但是,它并不像PHP那样成熟。准确地说,Java程序负责准 备需要显示的数据(比如发起SQL查询),而FreeMarker仅负责使用模板生成文本页面,显示这 些数据。 到底什么是模板引擎 简而言之,模板引擎有时候又被称作模板处理程序,它是一套软件或者用于构建软件的组 件,它以模板作为输入。模板类似于一张套用信函,有很多空白需要填写。模板引擎负责将模 板与数据模型(即组织成具有一定格式的数据集合)结合起来,从而生成某种类型的文档输出, 如果是普通文本,则可能生成PDF、Excel电子表或者你希望的某种格式。FreeMarker当然就是 这样一种模板,相信你还熟悉另外一种模板JSP!虽然有些人并没有认识到JSP是一种模板技术, 但实际上它确实是。 上面的内容对FreeMarker做了全面的解释!是的,很全面。我想现在你一定很想看一下 FreeMarker实际上是什么样,对吧?下面的命令将满足你的愿望,代码清单5-1列出一个非常简单 的FreeMarker模板。 代码清单5-1 FreeMarker模板的Hello World小例子 现在,你可能已经注意到上面引用的FreeMarker描述中的最后一段,“……Java程序负责准备需要 显示的数据……”这实际上意味着你需要构建一个Map,并填充数据。Map中的数据用于替换模板中的 记号,例如${name}。在代码清单5-2中,可以看到一个为代码清单5-1中的模板创建数据Map的简单例 子。 代码清单5-2 使用FreeMarker的非常简单的例子
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 5.1应用程序的需求和目标8 import freemarker cache. ClassTemplateLoader import freemarker template Configuration import freemarker template. Defaultobjectwrapper import freemarker template Template import java. io Stringwriter; ort java.io.writer import java. util. Array import java. util. HashMa public class Freemarker Test t public static void main(String[] args)i try i Cuntiguralion tConfig new Configuration); fmConfig. setobjectwrapper(new Defaultobjectwrappero)) onfig. setTemplateLoader (new ClassTemplateLoader( new Freemarker(.getClassO,"/")); HashMap data new HashMap ( data put("name","MY HAVURIIE READER ); ArrayList favoriteThings- new ArrayList; Hash Map tll new HasMMapo ft1 put ("na favoriteThings. add( ft1) HashMap +t2=new HashMap (; favoriteThings. add(ft?) HashMap [- new HashMap() ft3.put ("name","Jericho"); data put(" favoriteThings", favoriteThings) template= fmConfig getTemplate("hello. ft1"); Writer out= new Stringwriter( template process(data, out System. out. println(out toString()) 3 catch(Exception e)i e printStackTrace() 这是一个百分之百可以正常工作的例子,可以在本书的源代码下载包中找到它。经过编译和 行之后,可以看到输出结果如图5-1所示(还可以在命令行中看到编译和执行的过程)
5.1 应用程序的需求和目标 82 这是一个百分之百可以正常工作的例子,可以在本书的源代码下载包中找到它。经过编译和 运行之后,可以看到输出结果如图5-1所示(还可以在命令行中看到编译和执行的过程)
互动出版网 China-Pub. com 专业图书网上第一专营店 独家提供样章 51应用程序的需求和目标83 arker. jar FreemarkerTest Java 图5-1 FreeMarker运行结果 我觉得,这段代码具有一定的自我解释特性。 Free Marker的初始创建阶段,主要创建 Configuration对象并告诉它如何查看数据模型(它是一个对象包装器,不过这是一个更高级 的主题,暂时先跳过),以及告诉 Free Marker如何查找模板(在这个例子中,它是一个相对于使 用 FreeMarker的类的相对路径,因此这个模板必须位于伴随该类的默认包中)。一旦这个阶段完 成,则开始使用典型的方式填充Map,最后实例化这个模板(更特殊的情况是,告诉 Configuration对象你需要的模板,并由该对象来实例化模板),并借助数据Map来处理模板 输出到控制台,就是这样。非常简单! Free Marker提供一个很好的类似编程语言的选择结构,可以使用它们来组成循环、构建分支, 以及定义变量。不过, FreeMarker自己的描述中也讲到,它还不足以构成一个完整的编程语言。 请尽量保持模板简单而又普通,这样才是明智的。 WIki应用程序中的模板不会比这第一个例子 复杂,因此我们不会深入讨论 Free Marker的使用细节。不过,我想你会认同我的观点, FreeMarker 是一个方便使用的小工具,留在身边不会有错! 在这本书中,我们并没有太深入地讨论 Free Marker,不过它的功能远不止这里所介绍的 FreeMarker被应用到许多知名的应用程序和框架中, Struts2就是一个突出的例子,因而它的起 源非常好。我建议你花一些时间浏览 Free Marker网站htp!/ /freemarker sourceforge. net, FreeMarker 的好处之一是,它的文档非常棒,而且 FreeMarker团队会花时间讲解一些很好的例子。我相信它 会增长你的见识。就个人经验而言,我仅在几个月前才看到有 FreeMarke这个项目,但是从那以 后,我发现我会经常使用它,且很容易就可以把它加到我正在编码的环境中。它是我最近几年 来遇到的最有用的库之一,因此花些时间研究一下,我想你会和我一样发现它很有用 5.1.2 Apache Derby 接下来的难题是如何以及在哪里存储用户在DWk中创建的内容。当然,我们有多种选择。 可以将内容存储在文件系统中,实际上我最初也是这样计划的。不过这个方案有不少的问题,最 重要的是在一些环境中并不能在Web应用程序中操作文件系统。我希望DWik至少对读者有用 因此不能假设你必须在不允许写入文件系统的环境中运行DWki 另一个方案是数据库,这是我最后确定的方案,也是引入 Derby的原因 Derby最初是 Cloudscape公司的一个名为JBMS的产品。首次发布时间是1997年。没过多久,准
5.1 应用程序的需求和目标 83 图5-1 FreeMarker运行结果 我觉得,这段代码具有一定的自我解释特性。FreeMarker的初始创建阶段,主要创建 Configuration对象并告诉它如何查看数据模型(它是一个对象包装器,不过这是一个更高级 的主题,暂时先跳过),以及告诉FreeMarker如何查找模板(在这个例子中,它是一个相对于使 用FreeMarker的类的相对路径,因此这个模板必须位于伴随该类的默认包中)。一旦这个阶段完 成,则开始使用典型的方式填充Map,最后实例化这个模板(更特殊的情况是,告诉 Configuration对象你需要的模板,并由该对象来实例化模板),并借助数据Map来处理模板。 输出到控制台,就是这样。非常简单! FreeMarker提供一个很好的类似编程语言的选择结构,可以使用它们来组成循环、构建分支, 以及定义变量。不过,FreeMarker自己的描述中也讲到,它还不足以构成一个完整的编程语言。 请尽量保持模板简单而又普通,这样才是明智的。DWiki应用程序中的模板不会比这第一个例子 复杂,因此我们不会深入讨论FreeMarker的使用细节。不过,我想你会认同我的观点,FreeMarker 是一个方便使用的小工具,留在身边不会有错! 在这本书中,我们并没有太深入地讨论FreeMarker,不过它的功能远不止这里所介绍的。 FreeMarker被应用到许多知名的应用程序和框架中,Struts 2就是一个突出的例子,因而它的起 源非常好。我建议你花一些时间浏览FreeMarker网站http://freemarker.sourceforge.net。FreeMarker 的好处之一是,它的文档非常棒,而且FreeMarker团队会花时间讲解一些很好的例子。我相信它 会增长你的见识。就个人经验而言,我仅在几个月前才看到有FreeMarker这个项目,但是从那以 后,我发现我会经常使用它,且很容易就可以把它加到我正在编码的环境中。它是我最近几年 来遇到的最有用的库之一,因此花些时间研究一下,我想你会和我一样发现它很有用。 5.1.2 Apache Derby 接下来的难题是如何以及在哪里存储用户在DWiki中创建的内容。当然,我们有多种选择。 可以将内容存储在文件系统中,实际上我最初也是这样计划的。不过这个方案有不少的问题,最 重要的是在一些环境中并不能在Web应用程序中操作文件系统。我希望DWiki至少对读者有用, 因此不能假设你必须在不允许写入文件系统的环境中运行DWiki。 另一个方案是数据库,这是我最后确定的方案,也是引入Derby的原因。 Derby最初是Cloudscape公司的一个名为JBMS的产品。首次发布时间是1997年。没过多久,准