简介
Project Phobos 是一个脚本友好的轻量级 Web 应用程序环境,它运行在 JavaTM 平台中。借助 Phobos,开发人员可以使用多种脚本语言编写 Web 应用程序。在编写应用程序的过程中,他们可以利用开发环境提供的良好交互性,该环境省去了明确的编译和部署步骤,只保留了 Java 平台的功能。
本文档介绍应用程序开发人员非常感兴趣的 Phobos 架构的一些基本功能。作为补充资料,这篇入门 教程 介绍了如何在一个简单的应用程序中结合所有这些元素。您会发现,在阅读本文时参阅该教程会非常有用。我们计划在以后的几周中发布其他一些文档,这些文档侧重于介绍更高级的主题。
由于我们当前将 JavaScript 作为 Phobos 中的主要脚本语言,本文档假设您具有 JavaScript 语言的基本知识。
目录
架构概述
平台和环境
资源和目录布局
脚本
JavaScript 引擎
嵌入的 JavaScript 引擎
视图
路径
控制器
预定义的全局变量
生命周期事件
会话
库
架构概述
下表显示了 Phobos 的高级组件。

图 1:Phobos 架构图表
蓝色/绿色的部分代表顶部正常运行 Phobos 的基础结构。正如 下一部分 所解释,可以将 Phobos 应用程序部署在不同的运行时环境上。通常,在任何兼容的 servlet 容器中将 Phobos 应用程序部署为常规的 Web 应用程序。
红色的部分是 Phobos 自身的主要组件。它们包括以下内容:
- 成为运行时环境和 Phobos 之间界面的适配器代码
- 一组与 JSR-223 兼容的脚本引擎
- 一些脚本 库,这些库是与可用脚本引擎捆绑在一起或专门为 Phobos 编写的
- 一些预先打包的 AJAX 库,如 jMaki 和 Dojo Toolkit,专门在浏览器客户端内使用
- 一些预先打包的 Java 库,如 JDOM 和 Rome(有关详细信息,请参阅库部分)
最后,红色的部分代表应用程序的元素。这些元素包括:
- 可以直接服务于 HTTP 请求的 脚本
- 根据模型-视图-控制器 (MVC) 模式共同工作以服务于传入请求的 控制器和视图
- 其他与应用程序相关的内容,例如包括:静态的 HTML 页面、 CSS 文件、模板
以下部分详细介绍图表中出现的每个概念,以及一张图片中无法包含但对于 Phobos 开发人员来说很重要的其他元素。
Phobos 可以运行在不同的平台上。目前,我们支持其中两个平台:
- 在常规 Web 应用程序中
- 在独立模式(用于 IDE 集成和单元测试)中
下一部分详细介绍运行 Phobos 的平台如何影响应用程序的物理布局。例如,某些外部资源(如数据库)只有当 Phobos 在特定平台上运行时才可用。运行在应用程序服务器上的应用程序(如 GlassFish)应该使用作为服务器自身的一部分发送的网络数据库,而不使用嵌入的数据库实例。
依赖于特定平台的代码可以使用 globals.platform 变量来发现所使用的平台。 与这三个平台相对应的值如下所示:
- "webapp":在 Web 应用程序中
- "standalone":在独立模式中
除了平台之外,Phobos 还定义了环境的概念。环境就是应用程序的逻辑配置。例如,逻辑配置可以是开发、测试和生产。在其寿命内,应用程序部署在不同的环境中,尤其当应用程序从开发阶段发展到生产阶段时。环境通过捕获特定于每个阶段的所有信息来帮助轻松进行这些过渡。例如,开发人员可能希望避免在开发时启用特定的性能优化(可能因为它们会对开发周期产生负面影响)而是仅在系统测试和生产期间启用它们。
Phobos 希望开发人员用记忆中的一种或多种环境编写应用程序。然后负责部署应用程序的人可以通过使用特定于平台的方式(如使用系统属性)选择要使用的环境。正在运行的应用程序可以通过检查 globals.environment 变量确定其运行的环境。默认的环境为“开发”。
资源和目录布局
在 Phobos 上下文中,资源就是应用程序可以访问的任何文件。这包括属于应用程序的所有脚本和静态内容(如 HTML 页面)。还包括组成 Phobos 框架的所有脚本。
Phobos 应用程序的资源是根据特定的目录布局进行组织的。Phobos 区分虚拟目录布局和物理目录布局。虚拟目录布局跨所有平台都相同,而物理目录布局却因平台而异。
在虚拟布局中,应用程序有四个处于顶部级别的目录:
- application,它包含所有非内容应用程序文件,但不包含配置信息。例如,此目录中的文件包括脚本、模板和视图
- environment,它包含 运行应用程序的环境的配置信息
- framework,它包含所有特定于框架的文件
- static,它包含应用程序所使用的所有静态内容,包括任何预先包装的客户端库,如 Dojo Toolkit 或 jMaki widgets。
单独保留静态内容的原因是它通常可能使用特定于平台的机制服务比任何动态(例如,生成的脚本)内容具有更高性能的静态内容。将静态内容隔离在其自己的目录中可以简化此任务。环境信息独立于应用程序信息使得在多个应用程序之间共享文件更容易。
在应用程序代码中,您总是使用虚拟名称引用文件。因此,无论使用的平台如何,您都可以通过使用名称 /static/index.html 来引用名为 index.html 的静态文件。还要注意,虚拟名称始终是绝对的,这意味着它们以 / 字符开头。将来,Phobos 可能允许 URI 架构出现在虚拟名称的前面,从而允许引用远程资源。例如,存储在数据库中或由某些外部应用程序动态生成的脚本、模板或文档。
根据所使用的平台,应用程序的物理布局可能有所不同。以下部分介绍在 平台和环境 部分中引用的每个平台的物理布局。
在 Web 应用程序中运行的应用程序的物理布局
当作为标准的 Web 应用程序运行时,application、 environment 和 framework 虚拟目录都映射到 WEB-INF 目录下相同名称的目录。位于 static 虚拟目录中的所有静态内容都映射到 Web 应用程序的顶级目录。代码示例 2 显示了在 Web 应用程序中运行的应用程序的物理布局。
myApplication/ ...static files... WEB-INF/ application environment framework
代码示例 2:在 Web 应用程序中运行的应用程序的物理布局
在独立平台中运行的应用程序的物理布局
在调试应用程序时由 IDE 使用的此平台中,只有一个应用程序可以在给定的时间运行,因此物理布局与虚拟布局相同,这意味着不会发生共享或重新映射。只有一种例外情况,那就是 framework 目录通常来自共享的 Phobos 安装而不是应用程序的一部分。
application environment framework (* may not be present) static
代码示例 4:在独立平台中运行的应用程序的物理布局
脚本
编写应用程序代码的最简单方法是在 Phobos 中服务一个 HTTP 请求以将其放置在脚本中。
采用 JavaScript 编写的“hello, world”脚本类似以下内容:
response.setStatus(200); response.setContentType("text/html"); writer = response.getWriter(); writer.println("Hello from Javascript!"); writer.flush();
代码示例 5:打印来自 JavaScript 的 Hello 的 JavaScript 代码
如果您将该文件另存为 application/script/hello.js,则将在客户端每次尝试访问 URL /hello.js 时调用该文件。在内部,只要脚本引擎支持编译 Phobos 就会先动态编译脚本,然后才运行这些脚本。只要检测到对以前运行的脚本的更改,Phobos 就会丢弃过时、已编译的代码并且再次重新编译该脚本,而无需重新部署应用程序。这样使用 Phobos 进行开发就会具有非常高的交互性。
application/script 目录是预先配置的,用于包含脚本,但您可以通过操纵路径 覆盖此设置,如 路径 中所述。顺便说一句,特殊的 URL / 映射到名为 index.js 的脚本。
request 和 response 全局变量都分别绑定到请求和响应对象。尽管对象的实际类取决于所使用的平台,但多数情况下,这些对象将符合 javax.servlet.http.HttpServletRequest 和 javax.servlet.http.HttpServletResponse 类的约定。但任何特定于 servlet 容器的方法除外。请注意,在 Phobos 中处理会话的方式与在常规 servlet 容器中处理会话的方式不同。有关详细信息,请参阅 会话 部分。
Phobos 使用 JSR-223 调用任何脚本。因此,可以采用任何语言编写脚本,只要该脚本的类路径中具有与 JSR-223 兼容的脚本引擎即可。Phobos 附带两个内置脚本引擎:
您可以从 java.net 的 脚本 项目站点上下载更多引擎。
在此阶段,对于大多数应用程序代码来说,建议使用的语言是 JavaScript。Phobos 本身几乎就是采用 JavaScript 编写的,并且该框架假设您所使用的语言能够调用 JavaScript。此时,从另一种脚本语言调用 JavaScript 的任务比较复杂,需要了解 Mozilla Rhino 脚本引擎的内部。当然,也可以在另一种脚本语言中定义与 JavaScript 的一流接口(更像它们已经提供的 Java 接口)以便可以轻松访问 Phobos 库作为该接口的副产品。
JavaScript 引擎
Phobos 中的 JavaScript 引擎基于 Java Platform Standard Edition 6 (Java SE 6) 中代码名称为 Mustang 的引擎,它使用 Mozilla Rhino 来进行操作。与 Mustang 中的 JavaScript 引擎相比,Phobos 中的引擎具有以下附加功能:
- 支持 XML (E4X) 的 JavaScript 语言扩展名
- 编译为字节码
- 能够对 Java 类进行子类化(受特定于平台的任何安全限制的限制)
- 可扩展的顶级功能
E4X 允许在 JavaScript 代码内使用 XML 文字和类似于 XPath 的表达式。例如,可以按照如下步骤重新编写代码示例 5 中的“hello, world”。请注意,在代码的第一行中 HTML 文本的周围缺少双引号。
var text = <html><head><title>Hello</title></head><body>Hello from Javascript!</body></html>; response.setStatus(200); response.setContentType("text/html"); writer = response.getWriter(); writer.println(text); writer.flush();
代码示例 6:使用 XML 文字的 Hello JavaScript 示例
嵌入的 JavaScript 引擎
嵌入的 JavaScript 引擎允许您将 JavaScript 语句和表达式嵌入到 HTML 文件、 XML 文件或文本文件中,非常类似于 PHP 所执行的操作。
标识嵌入的 JavaScript 文件的扩展名为 .ejs。.ejs 文件的正文将逐字复制到标准复写器。在大多数脚本语言中,您可以通过对 context.writer 求值来获得该复写器(由 JSR-223 定义)。
另一方面,在运行时对周围有特殊标记的语句和表达式求值。该工具类似于 JSP 中的 scriplet。代码示例 7 显示了表达式的语法。代码示例 9 显示了语句的语法。
<%= ... a JavaScript expression ... %>
代码示例 7:表达式语法
当遇到前述的代码时,嵌入的 JavaScript 引擎对表达式求值并将其结果作为字符串打印给复写器。例如,以下脚本将字符串 "Two and two is 4.0" 打印给复写器。
Two and two is <%= 2 + 2 %>
代码示例 8:表达式示例
以下代码显示了 .ejs 页面中语句的语法。
<% ... JavaScript statements ... %>
代码示例 9:语句语法
当遇到前述代码时,嵌入的 JavaScript 引擎执行带引号的语句,而不向复写器发送任何内容。例如,以下代码向复写器打印字符串 "Two and two is 4.0" 并且它以静默方式将该字符串 "silent assignment" 指定给本地变量 a。
Two and two <% var a = "silent assignment" %> is <% context.getWriter().print(2 + 2) %>
代码示例 10:语句示例
尽管 .ejs 文件本身就是脚本,但它们非常适合于定义应用程序的视图。以下部分介绍 Phobos 定义的视图
视图
将处理请求的代码与呈现要发送回浏览器的页面的代码分离比较好。脚本和 控制器 的作业就是处理请求;呈现页面是视图的领域。
以下脚本简单地演示了为了呈现该页面而将页面请求分离。该页面的路径为 /application/view/status.ejs。脚本自身可能位于 /application/static/status.js 中。
model = { message: "everything is fine" }; library.view.render("/application/view/status.ejs");
代码示例 11:呈现页面的脚本
前述脚本使用 library.view.render 函数呈现视图。参数是视图资源的名称,在本例中为嵌入的 JavaScript 文件,如代码示例 12 所示。
<html> <head> <title>Status</title> </head> <body> <%= model.message %> </body> </html>
代码示例 12:嵌入的 JavaScript 视图示例
按照惯例,脚本和视图使用名为 model 的全局变量通信,但您可以使用其他任何机制。
如果您将此脚本和视图与 脚本 部分中的简洁脚本相比较,您将看到设置响应的状态代码和内容类型的代码已经消失了。通过 library.view.render 函数来自动执行该任何。
路径
每次您想引用给定的视图时编写较长的字符串(如 "/application/view/status.ejs")是非常单调乏味的。作为一种速记方法,Phobos 定义了常用资源的几个路径。将资源名称作为参数接受的库函数将使用适合于您尝试解析的资源的路径解析任何相对名称(不是以 / 字符开头的名称)。
例如,library.view.render 函数将视图资源的名称视为参数。因此,可以重新编写代码示例 11 如下所示:
model = { message: "everything is fine" }; library.view.render("status.ejs")
代码示例 13:无需完整路径即可呈现视图的脚本
render 函数将尝试在视图资源的路径上查找名为 status.ejs 的资源,该资源包括 /application/view。因此,render 函数 解析 为 /application/view/status.ejs。
所有预定义的路径都位于 application.path 对象中。包括控制器、库、模块、脚本和视图的路径。相应的变量如下:
application.path.controller application.path.library application.path.module application.path.script application.path.view
代码示例 14:Phobos 库用来解析资源的路径
路径只是字符串的列表。可以使用普通的数组函数更改应用程序代码或者扩展预定义的路径。因为这会更改应用程序的配置,因此通常它是在启动时执行。例如,若要将 application/myscripts 虚拟目录添加到脚本路径中,您可以编写:
application.path.script.push("/application/myscripts");
代码示例 15:向资源组中添加路径的代码
控制器
由于 脚本 映射为包含脚本名称的 URL,因此脚本自身不能像对象一样封装。 而且,创建很多不同脚本以处理多个相关操作的任务就像在表单上显示和更新数据一样变得很单调。由于这个原因,Phobos 定义了控制器。
控制器就是位于 控制器名称空间的子名称空间中的控制器类的一个实例。按照惯例在请求 URL 和控制器之间进行链接,但是开发人员可以对此进行自定义。例如,如果 Phobos 框架收到一个以下 URL /form/update 的请求,查找它会在 controller 层次结构的 form 名称空间中查找一个名为 Form 的控制器类。
/form/update
代码示例 16:控制器类上函数的 URL
查找该类时,框架将其实例化并查找一个更新方法。如果找到,则调用该方法。
JavaScript 支持基于原型的对象系统,但没有内在的封装名称空间的概念。为了确保控制器机制与 JavaScript 正常工作,Phobos 框架引入了一些特殊的命名惯例和库函数。为了进行演示,让我们详细地查看一下 Phobos 如何调用表单控制器的 update 方法
- 控制器是控制器名称空间的一部分。该名称空间由控制器路径中的文件表示,默认情况下该路径为 /application/controller。因此,当查找 表单名称空间时,Phobos 尝试加载一个名为 /application/controller/form.js 的脚本。
- Phobos 框架加载该脚本之后,名称空间作为名称 controller.form 下的一个对象可以访问,其中 controller 是表示控制器层次结构根目录的全局变量。
- 为了实例化控制器层次结构的form 名称空间中的 Form 类,Phobos 尝试解析表达式 controller.form.Form。若要标识为一个类,控制器类必须为 function 类型。该函数是构造函数,并且新创建的对象为此调用的控制器实例。
- 若要在控制器实例上调用 update 方法,Phobos 在该对象上查找名为 update 的函数值属性。如果找到,便用绑定到 this 变量的控制器实例调用它。
以下代码显示了 form.js 文件的一部分,该部分显示了如何为名为 form. 的控制器定义构造函数
library.common.define(controller, "form", function() { this.Form = function() { this.update = function() { // ... code to update the form goes here ... } } });
代码示例 17:定义名为 form 的控制器的代码
使用 library.common.define 库函数将名称空间定义为另一个空间的子空间。在本例中,将 form 定义为 controller 的子名称空间。在 library.common.define 正文中指定给 this 对象的属性为外部可见的名称空间的成员。在 define 调用中显示为第三个元素的匿名函数对于延迟到以后对其正文求值是必不可少的,因为这样 define 可以避免多次无用地重新定义名称空间。
值得指出的是,this 每次绑定到不同的对象:
- 在 this.Form 中,this 绑定到代表正在定义的名称空间的对象。
- 在 this.update 中,this 绑定到正在构建的对象,该对象为控制器实例。
- 在函数的正文如 this.update 中,this 绑定到全部构建好的控制器实例。
Phobos 强制一个约定,即类名称为大写。从技术上说,类名称实际上是用作构造函数的函数的名称。这就是为什么代码示例 17 中的第二行代码必须采用这种方法编写的原因。
由于 JavaScript 对象模型具有极高的可扩展性,因此也可以采用其他方法获得同样的结果。代码示例 18 和 19 就是与代码示例 17 执行相同功能的其他两种方法。
library.common.define(controller, "form", function() { this.Form = function() {}; this.Form.prototype.update = function() { // ... code to update the form goes here .... } } });
代码示例 18:定义控制器的另一种方法
library.common.define(controller, "form", function() { this.Form = function() {};
with(this.Form) { prototype.update = function() { // ... code to update the form goes here ... } } });
代码示例 19:定义控制器的第三种方法
这三种方法之间的差别主要是样式和便利性。
将来版本的 Phobos 可能会引入一些语法甜头 (syntactic sugar) 以使名称空间和类定义更加简单。在本例中,我们将为使用关键字如 package 和 class 扩展的 JavaScript 方言新建一个脚本语言。
如果客户端尝试访问 URL(如没有操作方法的 /form/foo),则给定的 form 控制器会怎样呢?在本例中,框架随后将查找一个名为 onRequest 的方法,该方法充当该控制器类的 catch-all 操作。如果该方法不存在,则框架向客户端返回一个 404 NOT FOUND 错误。
预定义的全局变量
到目前为止,我们还没有解释表达式(如 library.view.render)的工作方式。Phobos 定义了很多全局变量,这些变量都是显式名称空间的根。除 library 和 controller 之外,还有一个 module 全局变量。每个名称空间都有一个相对应的路径,如路径中所述。
模块类似于库,但它们专门用于应用程序。作为一项指导原则,只有计划在某些点上向 framework 虚拟目录添加该代码时才应该定义自己的库(如 application/library/mylibrary.js)。
将库移动到框架是非常透明的,因为库的默认路径包括 /framework/library 和 /application/library 目录。因此,可以在它们之间自由移动文件。
应该在模块中定义不想成为框架的一部分的代码。例如,您可能希望拥有一个“helpers”模块,该模块包含您计划从应用程序的多个控制器中调用的非常有用函数。可以通过定义此表单的名为 application/module/helpers.js 的文件类完成此操作:
library.common.define(module, "helpers", function() { this.myUsefulFunction = function() { // ... useful code goes here ... } });
代码示例 20:定义模块
可以使用以下表达式从应用程序中的任何位置调用该函数:
module.helpers.myUsefulFunction( ... )
代码示例 21:调用用户定义的模块函数的表达式
正如 控制器 一样,可以进行很多同样类型的模块定义,如以下代码所示。
library.common.define(module, "helpers", function() { function myUsefulFunction() { // ... useful code goes here ... }
// export the function this.myUsefulFunction = myUsefulFunction; });
代码示例 22:定义模块的另一种方法
除了与名称空间关联的变量以及在前面在 脚本 部分所述 request 和 response 变量之外,Phobos 还定义了其他一些全局变量,如下所示:
- application 包含很多描述应用程序本身的属性,包括配置信息,如路径或不同的名称空间
- invocation 是某个映射对象的 JavaScript 代理,该对象包含一个请求-响应生命周期的数据。 一旦处理完 HTTP 请求之后,该映射便被破坏
- globals 是某个映射对象的 JavaScript 代理,该对象包含等于应用程序自身生命周期的数据。
对于开发人员来说,所有这些对象,包括那些是代理的那些对象都显示为具有可读和可写(但当前不能枚举)的属性的常规 JavaScript 对象。因此,当定义一个新的请求范围的变量 myDatum 值为 5 时,应该读取以下表达式。
invocation.myDatum = 5;
代码示例 23:定义新的请求范围的变量的表达式
用于配置应用程序的选项,如 路径,都位于 application.options 下。另一个经常使用的选项为 application.options.datasource,该选项表示默认情况下数据库访问库所使用的数据源 。
生命周期事件
Phobos 应用程序具有一个简单的生命周期。两个最重要的事件为启动和关闭。除了后台任务(将在随后的文档中进行介绍)之外,位于启动和关闭之间的所有 Phobos 应用程序都要服务于传入的请求。
您可以让应用程序代码在发生启动或关闭时执行。在启动时,Phobos 尝试按固定的顺序运行很多脚本和函数。让我们假设运行 Phobos 的平台由字符串 "PLATFORM" 标识环境由字符串 "ENVIRONMENT" 标识。则在启动时执行的脚本和函数如下所示:
- /environment/ENVIRONMENT.js 脚本
- /environment/startup-PLATFORM.js 脚本
- /application/startup.js 脚本
- application 模块的 onStartup 函数,此时使用当前的模块路径解析
根据以下列表中所述的每个脚本或函数的 期望行为建立顺序。
- 特定于环境的脚本应该只设置一些应用程序选项
- 特定于平台的脚本应该基于所使用的平台获得或定义资源
- startup.js 脚本和 onStartup 函数应该对应用程序执行任何实际的启动工作,如连接数据库和检查某些表是否存在
startup.js 脚本和 onStartup 函数之间几乎没有什么差别。建议使用 onStartup 函数,但如果需要更改模块路径,则有必要使用 startup.js 脚本。
关闭时,执行以下步骤:
- 此时使用当前的模块路径执行和解析 application 模块的 onShutdown 函数
- 执行 /application/shutdown.js 脚本
此时,我们还不需要标识特定于环境或特定于平台的关闭脚本。
会话和“flash”
Phobos 使用 Cookie 管理会话。
会话由包含某些名称/值属性的对象表示。您可以使用 invocation.session 来访问该对象。不要被它位于 invocation 下的事实所误导:尽管在每次调用时都会重新创建对象本身,但它的内容将永久存在。(奇怪的是,会话数据当前存储在 application.sessionStore 下。将来有可能发生更改,当我们添加文件或数据库会话永久性时可能发生更改。)
您可以使用普通的 JavaScript 语法写入、读取和删除会话范围的属性,如以下代码所示:
invocation.session.userName = "Fred"; // ... some code here .... model = { name: invocation.session.userName }; // ... more code here ... delete invocation.session.userName;
代码示例 24:写入、读取和删除会话范围的属性
往返于字符串的所有转换都是自动进行。如果是对象,则默认的转换不太有用。例如,对象 {a:1, b:2} 将被序列化为 [Object object],从而使其丢失了所有状态。如果您决定使用复杂的 JavaScript 对象作为值,则您可能希望首先使用 library.json.serialize 和 library.json.deserialize 函数将其转换往返 JSON 表示方法。
预定义的属性 invocation.session.id 返回一个字符串,该字符串唯一标识会话。该字符串的一个用处是作为数据库密钥。名称以 __ (双下划线)开头的属性留作框架使用。
应用程序可以禁用会话管理以避免当通过在启动脚本中设置以下属性时的性能开销。
application.options.session.enabled = false;
代码示例 25:禁用会话管理
Ruby on Rails 首先引入了 flash,它是一个特定于范围的属性包。它的生命周期恰好两个请求-响应周期:在处理一个请求的过程中在 flash 中插入的数据将在处理下一个请求的过程中可见,并且随后进行自动收集。当您希望将信息从一个操作传递到下一个操作(如重定向)时,flash 非常有用。
在 Phobos 中,您可以使用 invocation.flash 访问 flash。实际上,flash 属于会话状态的一部分。因此,您需要非常仔细地执行操作,避免对会话属性和 flash 属性使用相同的属性名称。
invocation.flash.message = "Login failed"; library.httpserver.sendFound("... redisplay the login page ....");
// then in the action we redirected to: model = { message: invocation.flash.message }; library.view.render("... some view ...");
代码示例 26:从 Flash 写入和读取
库
Phobos 附带很多 JavaScript 库,这些库位于 library 名称空间下。最常用的库如下所示:
- httpserver 包含有助于使用 HTTP 级别功能的函数,如重定向和错误;
- json 包含 JSON 序列化/取消序列化函数;
- lang 包含与语言有关的函数,例如,若要测试对象的类型,请使用另一个对象的属性扩展对象或创建一个类似于扩展多个基类的对象的类;
- log 包含向日志中写入信息、警告和错误消息的函数;
- template 包含使用 JavaScript 中的 FreeMarker 模板引擎的函数;
- view 包含通常由视图调用以呈现自身各个部分的函数,可以通过包含其他资源,也可以通过编程创建新的标记;
此时,没有与 JavaScript 等价的 JavadocTM 工具,但是我们希望不久之后获得一个这样的工具。直到目前为止,查看在特定库中定义的函数的唯一方法就是浏览位于 framework/library/LIBRARYNAME.js 下的它的源代码。
目前,Phobos 没有向任何预定义的 JavaScript 对象添加任何属性。尽管有一个添加这些扩展的非常明确的位置。根据最初的用户反馈,我们计划添加更多便利的函数,就像 Prototype JavaScript 库一样。
最后,由于 JavaScript 以及在 Java 平台上运行的大多数其他脚本语言都具有与 Java API 的出色接口,因此脚本可以轻松调用任何 Java 库。Phobos 的标准分发包括 JDOM 和 ROME 实用程序库:
此外,您还可以直接访问属于 Java 平台一部分的任何类。
当使用来自 JavaScript 的 Java 类库时,您可以只使用 Packages 全局变量引用合格的类名称。例如,您可以使用以下代码创建 JDOM SAXBuilder 对象。
var builder = new Packages.org.jdom.input.SAXBuilder();
代码示例 26:创建 JDOM SAXBuilder 对象
结束语
我们希望本文档帮助您掌握了 Phobos 中最重要的概念。如果您还没有掌握,可以通过 教程 来工作并尝试使用 Phobos 编写一些简单的 Web 应用程序。
后续文档将详细介绍更高级的功能,如 AJAX(使用类似于 jMaki 的技术)、永久性、RSS/Atom、自定义应用程序使用的 URL 等等。由于 Phobos 的工作尚在进行之中,因此我们要求您加入 Phobos project on java.net 上的邮件列表,为它的开发贡献自己的力量。
|