内容


使用 Eclipse 和 JavaFX 开发 Mashup 应用

Comments

开始之前

Web 2.0 的时代已经全面来临,Mashup 的应用越来越多,RIA(Rich Internet Application)应用的呼声也越来越高,很多公司都纷纷推出了自己的 RIA 解决方案,比如 Adobe 公司的 AIR,Microsoft 的 Silverlight 等。而 Java 在互联网应用系统的开发上却受到了前所未有的挑战。在这样的背景下,SUN 公司于今年的 Java ONE 大会上推出了 JavaFX,希望借此以迎接这样的挑战。JavaFX 是一种声明式的静态类型脚本语言,可以让用户非常容易和快速地开发应用程序用户界面,并且能够很好地和互联网上提供的众多 Web 服务结合起来,进行 Mashup 应用的开发。

关于本教程

本教程将采取从简单到复杂,知识点和实际代码相结合的方式。先讲述一些简单的概念和代码,使大家先对 JavaFX 建立起直观的印象,并且能够写出自己的应用程序界面。然后再介绍 JavaFX 的类以及 Mashup 的概念,并且讲述如何使用 Web service,从而在建立好程序界面的基础之上,增加业务逻辑,组建 Mashup 应用。

目标

学完本教程后,您将不仅能够掌握 JavaFX 的基本概念和语法,用 JavaFX 编写比较复杂的 UI 界面,并且能够增加自己的业务逻辑开发满足自己需求的 Mashup 应用。

先决条件

要学习本教程,您需要有一定的编程经验,并了解面向对象的概念。同时您应该熟悉 Eclipse 开发环境,熟悉插件安装过程。

代码示例和安装要求

您需要一些工具才能试用本教程中的代码。所有这些工具都可以免费下载(参见 参考资源):

  • Java SDK 1.5 或更高版本的 JDK;
  • Eclipse Europa 或更高版本;

JavaFX 简介

关于 JavaFX

JavaFX 是一个为了应对快速开发高交互性的跨平台应用的挑战而诞生的解决方案。目前它包括两个部分:JavaFX Script 和 JavaFX Mobile。JavaFX Mobile 主要是为了开发移动终端应用而设计,本文主要讨论 JavaFX Script。以下内容如果不特别指出,JavaFX 均指JavaFX Script。

JavaFX 最大的优点是它强大而简单的 UI 设计能力。使用其简单的脚本声明式语法,利用其基本组件,就能非常容易的设计出非常漂亮,用户感受极佳的应用程序界面。在下面的例子中您将体验到用 JavaFX 设计出来的精彩界面。

简单的语法是 JavaFX 的另外一个优点,它使用脚本声明式的语法。简单的语法却仍然让 JavaFX 具有强大的处理能力。尤其对数组,JavaFX 提供了非常强大的支持,支持类似 XPath一样用点号访问数组中的内容,并且更引入了类似 SQL 语言的数组元素查询功能!除此之外,JavaFX 还支持面向对象的编程思想,支持类,继承等。并且与 Java 的单继承不同,JavaFX 支持多继承。

作为 Java 世界的一个新成员,JavaFX 生来便具有了 Java 的很多优点,比如跨平台,有 JRE 的地方就能运行 JavaFX。并且你能够在 JavaFX 的代码里面引入 Java 的类,有了 Java 的支持,大大的增强了 JavaFX 的竞争力。

体验 JavaFX 界面

为了更快地体验 JavaFX 带来的丰富界面,我们先来快速地浏览几个 JavaFX 官方网站上提供的应用示例。在 Open JavaFX 官方网站 页面上大家可以找到许多 JavaFX 的应用示例。我们可以随便挑选一个!

  • 点击:JavaFX Script Studiomoto Demo,选择“下载 JNLP 文件到本地”。
  • 用 Java Web Start 打开下载到本地的 studiomoto.jnlp 文件。

如果您的 JDK 是通过向导安装的,则默认情况下系统会自动使用 Java Web Start 打开 JNLP 文件。否则,您可以点击右键,选择“打开”,在选择打开程序时指向您机器 JRE_HOME/bin 目录里面的 JavaWS.exe 这个程序。然后经过一段时间的下载,就会看到如下 图 1 程序运行界面了。其他例子的运行过程和本例基本相同。关于 JNLP 文件的介绍和本例 JNLP 文件内容的剖析,参见本教程 部署 JavaFX 小节。

图 1. JavaFX 程序运行界面
图 1. JavaFX 程序运行界面
图 1. JavaFX 程序运行界面

Hello World!第一个 JavaFX 应用

下面就将开始我们的 JavaFX 开发之旅!首先,我们将配置一个基于 Eclipse 的 JavaFX 开发环境;然后,我们将利用这个开发环境开发一个简单的 Hello World 应用,同时我们将解释一些 JavaFX 脚本编程的基本概念。

搭建 Eclipse 开发环境

在开发之前我们通常需要做些准备工作,比如搭建好开发环境。在本教程中,我们将在 Eclipse Europa(Eclipse V3.3)环境中开发 JavaFX,我们假设您已经下载并且在计算机中安装好了 Eclipse Europa 开发环境(关于如何下载和安装 Eclipse Europa,请参见 参考资源)。为了使 Eclipse 支持 JavaFX 应用的开发,我们需要在 Eclipse 环境中安装 JavaFX 开发插件,它给我们提供了一个 JavaFX 的编译环境和开发的 IDE,能够提供语法高亮和错误提示等基本功能,但是现在的版本功能还比较简单。希望以后的版本能够有大幅度的改进,毕竟好的开发环境可以促进语言的普及。

插件的安装过程比较简单,其步骤如下:

  1. 运行 Eclipse, 选择菜单 help -> software updates -> find and install,如下图所示:

    图 2. 为 Eclipse 安装 JavaFX 插件
    图 2. 为 Eclipse 安装 JavaFX 插件
    图 2. 为 Eclipse 安装 JavaFX 插件
  2. 然后选择“search for new features to install”

    图 3. 为 Eclipse 新建插件站点
    图 3. 为 Eclipse 新建插件站点
    图 3. 为 Eclipse 新建插件站点
  3. 点击“New Remote Site”按钮,新建一个远程站点,可以任意输入一个名字,例如本例中我们输入“JavaFX”,然后输入插件的安装 URL:

    http://download.java.net/general/openjfx/plugins/eclipse/site.xml

  4. 点击“完成”按钮,将进行一系列的安装过程,在 Eclipse 重启之后,插件就已经安装完毕了。

创建 JavaFX 项目

安装好 JavaFX 开发插件之后,我们可以在 Eclipse 中创建 JavaFX 项目,您可以按照下面的步骤创建:

  1. 从 Eclipse 的主菜单选择 New --> Project,在选择工程向导窗口中选择 Java Project

    图 4. 建立第一个 JavaFX 项目
    图 4. 建立第一个 JavaFX 项目
    图 4. 建立第一个 JavaFX 项目
  2. 给这个工程输入个名字,本例名字为 JavaFXHello,其它区域默认值即可。

    图 5. 为第一个 JavaFX 项目取个名字
    图 5. 为第一个 JavaFX 项目取个名字
    图 5. 为第一个 JavaFX 项目取个名字
  3. 点击 next

    图 6. 其他部分默认即可
    图 6. 其他部分默认即可
    图 6. 其他部分默认即可
  4. 默认设置即可,点击 Finish

第一个 JavaFX 项目就已经建立起来了,您可以在 package explorer 视图中看到项目的目录结构,如下图所示:

图 7. 已经建立了第一个 JavaFX 项目
图 7. 已经建立了第一个 JavaFX 项目
图 7. 已经建立了第一个 JavaFX 项目

创建 JavaFX 文件

接下来,我们开始创建第一个 JavaFX 文件。

  1. 在 src 目录上 右键 --> New --> Other,在弹出窗口中选择 JavaFX --> JavaFX File

    图 8. 新建一个 JavaFX 文件
    图 8. 新建一个 JavaFX 文件
    图 8. 新建一个 JavaFX 文件
  2. 点击 next

    图 9. 为 JavaFX 文件设定一个名字
    图 9. 为 JavaFX 文件设定一个名字
    图 9. 为 JavaFX 文件设定一个名字
  3. 在文件名处输入我们的第一个文件名:Mashup.fx,最后点击 Finish。此时的视图变成:

    图 10. 建立了第一个 JavaFX 文件
    图 10. 建立了第一个 JavaFX 文件
    图 10. 建立了第一个 JavaFX 文件

开发 Hello World 应用

到目前为止,我们已经建立了一个 JavaFX 项目,并且建立了第一个 JavaFX 文件。那么接下来我们将开始开发一个简单的 JavaFX 应用程序:Hello World!

正如在 JavaFX 简介 中所介绍,JavaFX 提供了非常简单的脚本式语言可以让用户快速的开发 UI 界面。因此,我们先来做一个最简单的 Hello World 的 UI 界面。

  1. 双击 Mashup.fx,进入代码编辑器,将下面的代码复制进去。

    清单 1. JavaFX 的 Hello World 程序
    import javafx.ui.*; 
    Frame {
    	title: "Hello World JavaFX" 
    	width: 200 
    	height: 200
    			
    	content: Label {
    		text: 'Hello World!'
    	}
    	visible: true
    };

    从代码中可以看出,JavaFX 的程序非常简单易懂:整个界面我们用一个 Frame 来表示,title/width/height 三个属性分别用来设置 Frame 的标题、宽、高等信息。Visible 属性为 true,表示可见。Content 属性表示这个 Frame 的 content 是一个 Label,而 text 又是为这个 Label 设置显示的文本属性。JavaFX 的字符串可以放在一对双引号 "" 或者一对单引号 '' 中,但是有点细微的区别,放在单引号中的所有字符都当作普通字符处理,但是如果放在一对 "" 双引号里面,则可以将变量用一对大括号 {} 括起来放到双引号内,从而可以实现将变量和普通字符组合起来形成一个完整字符串的作用。

    例如下例:

    清单 2. JavaFX 的字符串处理
    import java.lang.System;
    var var1 = 'IBM';
    System.out.println("Company: {var1} "); //输出为 Company: IBM

    OK!第一个程序已经完成,下面我们来看看如何在 Eclipse 中运行:

  2. 运行。在 Mushup.fx 文件上 右键点击 --> Run As -- > Open Run Dialog

    图 11. 运行第一个 JavaFX 文件
    图 11. 运行第一个 JavaFX 文件
    图 11. 运行第一个 JavaFX 文件
  3. 在运行窗口中,选中 JavaFX Application 类型,然后点最左上角的“新建”,这个时候会生成一个名字叫做 New_configuration 的运行配置文件,在 Name 输入框内将配置文件名字改为我们的 JavaFX 文件名“Mashup”,并且点 Arguments 标签,在 Program arguments 里面输入“Mashup”,最后点击最下面“Run”按钮运行程序。

    图 12. 进行必要的设置才能正确运行
    图 12. 进行必要的设置才能正确运行
    图 12. 进行必要的设置才能正确运行
  4. 程序运行界面如下:

    图 13. Hello World 程序界面
    图 13. Hello World 程序界面

恭喜!我们的第一个 JavaFX 应用程序已经成功运行了!让我们先喝杯咖啡,稍事放松,接下来我们将会用 JavaFX 开发一个更加复杂的应用界面,为我们的 Mashup 应用做个铺垫。

为 Mashup 应用创建 UI

Mashup 这个词语最近成了互联网世界的一个热门词汇,各技术论坛都纷纷出现了它的身影。那么什么是 Mashup 呢?在开始我们的 Mashup 应用开发之前,我们来谈谈 Mashup 应用的特点。

什么是 Mashup?

在最初的时候,Mashup 应用的含义只局限于在一个页面上集成了几个网站的内容。比如,您可以在同一个页面里面显示新浪的新闻、CSDN 的技术文章、淘宝网上正在拍卖的热门款式相机等。这种简单的内容集合就构成了最初的 Mashup 应用。

但是后来,Mashup 的应用得到了进一步的扩展,人们不仅单纯的在一个页面内显示来自不同网站的信息,而且还对来自不同网站的信息进行处理,增加自己的业务逻辑,比如筛选过滤等等。为了帮助人们快速的完成这种业务处理功能,各 IT 巨头都提供了一些 Mashup 开发工具,比如 IBM 的 QEDWiki、微软的 Popfly、雅虎的 Pipes 等。Mashup 在业界的受重视程度,可见一斑。

更多关于 Mashup 的资源,请参见 参考资源 中的相关文档。

JavaFX 与 JavaScript

因为所有的浏览器都实现了同源策略,即 JavaScript 脚本只与源于该脚本所属页面所在的同一服务器的元素进行交互。所以浏览器在跨域访问数据的时候会存在安全性问题而受到一些限制。而 Mashup 应用在一个页面内要与多个不同网站的数据进行动态交互,所以现在的 Mashup 应用有时候不得不将一些数据处理功能放到服务器端完成。即在服务器端与不同的网站数据进行交互处理,将最终的处理结果再传回客户端。而 JavaFX 作为全新的 RIA 解决方案,可以脱离浏览器单独运行,所以也就没有了这样的限制,从而在根本上使 Mashup 应用能够摆脱浏览器安全性限制问题,更方便的创建 Mashup 应用。

关于 Mashup 应用示例

在本教程的后面,我们将构建两个示例应用,用来演示如何利用 JavaFX 和 REST 风格的 Web service 来创建简单的 Mashup 应用。我们首先利用 JavaFX 构建应用程序的 UI 界面,然后在此基础上添加业务逻辑代码来分别构建两个不同的 Mashup 示例应用。在第一个示例应用中,我们将通过调用一个单一的 REST Web 服务 API 来实现股票查询的功能。在后面的一个示例中,我们将从多个服务源中检索数据,实现天气预报和城市信息查询的功能。

通过示例应用,我们将展示如何利用 JavaFX 调用 REST API 以获得来自于互联网的数据检索服务,以及如何将返回结果与 JavaFX 界面组件之间进行绑定,从而实现查询结果的显示。

接下来,我们将首先利用 JavaFX 来构建 Mashup 示例应用程序的 UI 界面。

创建 Mashup 应用的 UI

清单 3 是创建 Mashup 示例应用 UI 界面的 JavaFX 脚本代码。关于创建用户 UI 界面的知识点在前面的章节中基本已经讲过,只不过本示例更为复杂,多用了一些 UI 组件,比如 SplitPane、SplitView、TextField 等。根据前面介绍的基础知识您应该很容易看懂这部分代码,它们只不过是给这些组件多设置了一些属性而已,在此,将不作过多阐述。关于 JavaFX 的 UI 设计的更为详细的技术文档和教程,可以参考本教程的 参考资料

清单 3. 建立 Mashup 应用的 UI 界面
import javafx.ui.*; 

var stockSymbol = TextField { };
var zipCodeField = TextField { };

Frame {
    title: 'Mashup Application'
    visible: true

    content: SplitPane {
        orientation: HORIZONTAL
        content:
            [
            SplitView {
                weight: 0.5
                content:
                BorderPanel {
                    top: GridBagPanel {
                        border: CompoundBorder {
                            borders:
                                [
                                TitledBorder {
                                    title: 'Input Areas'
                                },
                                EmptyBorder {
                                    top: 5
                                    left: 5
                                    bottom: 5
                                    right: 5
                                }
                                ]
                            }
                        cells:
                            [
                            GridCell {
                                anchor: EAST
                                gridx: 0
                                gridy: 0
                                content: SimpleLabel {
                                    text: 'Stock: '
                                }
                            },
                            GridCell {
                                anchor: WEST
                                fill: HORIZONTAL
                                weightx: 1
                                gridx: 1
                                gridy: 0
                                content: stockSymbol
                            },
                            GridCell {
                                anchor: EAST
                                gridx: 0
                                gridy: 1
                                insets: {top: 2}
                                content: SimpleLabel {
                                    text: 'Zipcode: '
                                }
                            },
                            GridCell {
                                gridx: 1
                                gridy: 1
                                fill: HORIZONTAL
                                weightx: 1
                                insets: {top: 2}
                                content: zipCodeField
                            },
                            GridCell {
                                anchor: WEST
                                weightx: 1.0
                                gridx: 0
                                gridy: 2
                                gridwidth: 2
                                fill: HORIZONTAL
                                content: SimpleLabel {
                                    border: EmptyBorder {
                                        top: 10
                                    }
                                    text: "Input Some characters,Press Enter"
                                }
                            }
                        ]//end cells
                    }//end BorderPanel

                    center: BorderPanel {
                        border: CompoundBorder {
                            borders:
                                [
                                    TitledBorder {
                                        title: "Display Stock Price:"
                                    },
                                    EmptyBorder {
                                        top: 5
                                        left: 5
                                        bottom: 5
                                        right: 5
                                    }
                                ]
                            }
                            center: TextArea {
                                font: Font { face: SERIF style: ITALIC size: 16 }
                                lineWrap: true
                                wrapStyleWord: true
                                editable: false
                                text: ''
                            }
                        }                         
                    }
                },//SplitView
                SplitView {
                    weight: 0.5
                    content: SplitPane {
                    border: CompoundBorder {
                        borders:
                            [TitledBorder {
                                title: "Display Mashup Results:"
                            },
                            EmptyBorder {
                                top: 5
                                left: 5
                                bottom: 5
                                right: 5
                            }]
                        }
                        orientation: VERTICAL
                        content:
                        [SplitView {
                            weight: 0.5
                            content:EditorPane {
                                opaque: true
                                preferredSize: {height: 250 width: 250}
                                contentType: HTML
                                editable: false
                                text: ''
                            }
                        },
                        SplitView {
                            weight: 0.5
                            content: EditorPane {
                                preferredSize: {height: 250 width: 250}
                                editable: true
                                text: ''
                        }
                    }]
                }
            }
        ]
    }//end SplitPane
}// end frame

将清单 3 中的代码复制到前面章节中建立的 Mashup.fx 文件中,然后和 Hello World 程序 的步骤一样:保存和运行。我们可以看到如下所示的运行界面:

图 14. Mashup 应用程序的界面
图 14. Mashup 应用程序的界面
图 14. Mashup 应用程序的界面

现在,我们已经为 Mashup 应用做好了铺垫,我们利用 JavaFX 脚本轻松地描述并创建好了一个可执行的 UI 界面。

调用 REST API 实现 Mashup

在本节中,我们将给示例应用的 UI 界面添加一些业务逻辑代码,通过调用互联网网站提供的 REST 风格 Web 服务来检索需要的数据,并将返回的结果与 UI 组件进行绑定,用于显示结果数据,从而完成这个 Mashup 示例应用程序的开发。

Mashup 单一数据源

我们首先来做一个比较简单的 Mashp 应用,只从单一网站获取数据。我们希望在刚才创建的 UI 界面的 Stock 输入框中输入股票代码,比如 IBM,回车后程序会在“Display Stock Price”下面的文本框内显示股票价格。

为了达到上述目的,首先需要建立一个 JavaFX 类 RestService。这个类有两个 String 类型的属性(attribute),一个是 source 属性,用来存放 Web 服务的 URL;另一个是 result 属性,用来存放从 Web 服务中返回的数据。同时还定义了一个操作(operation):update(),用来更新 result 中的内容。

代码的位置加在刚才的 Mashup.fx 文件的顶部,如下:

清单 4. 建立一个 JavaFX 类
import javafx.ui.*; 
import java.net.URL; 
import java.lang.StringBuffer ; 
import java.io.InputStreamReader; 
import java.io.BufferedReader; 

class RestService { 
    attribute source: String ;//hold the url of web service
    attribute result: String ; //hold the data received from  web service
    operation update(); // update the result attribute when get data from a new source
}

operation RestService.update(){
// it means that this update() operation belongs to class RestService 
    var content = new StringBuffer(""); 
    var url = new URL( source ); 
    var is = url.openStream(); 
    var reader = new BufferedReader(new InputStreamReader(is)); 
    var line; 
    while (true) { 
        line = reader.readLine(); 
        if (line == null) { 
            break; 
        } 
    content.append(line); 
    content.append("\n"); 
    } // end while 
    is.close(); 
    result = content.toString(); 
}

JavaFX 中用关键字 class 来建立类,类可以有属性(attribute),操作(operation)和函数(function),我们只用到了前两者。语句:

attribute source: String ; //hold the url of web service

为类 RestService 定义了一个属性 source,其数据类型是 String 类型。JavaFX 语言提供四种基本类型:String(字符串)、Boolean(布尔)、Number(数值)和 Integer(整数)。JavaFX 的操作有点像 Java 中的方法(Method), 但是操作的定义都在类定义之外,用点号(.)来表示操作和类之间的从属关系。

下面的代码,我们建立了一个 RestService 类的实例:

清单 5. 建立类的实例
var restStockService = RestService { 
    result: "Stock price area initialized" 
    source: "http://quote.yahoo.com/download/javasoft.beans?SYMBOLS=IBM&format=p" 
};

和前面创建 UI 界面时的语法很类似,我们给 RestService 类的两个属性赋予了两个初始值。

那么如何能让 Stock 输入框中输入股票代码,回车后“Display Stock Price”下面的框内自动显示股票价格呢?为了达到这个目的,我们要建立一种关联。首先需要给输入框 stockSymbol 指定回车后的动作:

清单 6. 给输入框 stockSymbol 指定动作
var stockSymbol = TextField { };
stockSymbol.action = operation() {
    restStockService.source=
    "http://quote.yahoo.com/download/javasoft.beans?SYMBOLS={stockSymbol.value}&format=p";
    restStockService.update();
};

从代码中可以看出,指定动作是通过设定 action 来实现的。在触发该输入框回车事件后,先让 RestService 类的实例 stockSymbolsource 属性赋值为指向 REST API 的 URL,然后再调用类实例的 update() 方法去更新类实例的 result 属性。

其次,我们需要完成关键的一步,即属性的绑定。我们将“Display Stock Price”下面的显示框,也就是那个 TextArea 组件的 text 属性通过 bind 关键字绑定到 restStockService 对象的 result 属性上去。从而,当 restStockServiceresult 属性值发生变化的时候,TextArea 的 text 属性,也就是它的显示内容也会动态发生变化,从而实现结果的显示。看起来十分地简单!

清单 7. 将 UI 组件 TextArea 的 text 属性绑定到 restStockService.result
center: TextArea {
    font: Font { face: SERIF style: ITALIC size: 16 }
    lineWrap: true
    wrapStyleWord: true
    editable: false
    text: bind restStockService.result
}

保存代码,运行。在 Stock 输入框中输入 IBM,我们将会看到下面的结果:

图 15. 用 Web service 来获得 IBM 股票价格
图 15. 用 Web service 来获得 IBM 股票价格
图 15. 用 Web service 来获得 IBM 股票价格

Mashup 多个数据源

前面我们已经通过调用一个 API 来实现了股票查询功能,接下来我们再稍微增加一点复杂性,将从多个数据源中获取数据。我们将用到两个 Web 服务:一个是 Yahoo! 的天气搜索的 API,比如我们需要搜索 ZipCode 是 94089 的城市的天气情况,那么可以调用它的服务 API :

http://weather.yahooapis.com/forecastrss?p=94089

另一个是 sunlightlabs 提供的 API,可以获得某个城市的信息。比如您给定一个 ZipCode,如 94105,您可以通过以下的 API 来获得信息:

http://api.sunlightlabs.com/places.getCityStateFromZip.php?zip=94105&apikey=23kj234kjb3kjbcl87ds

其中 apikey 是网站提供的一个认证密钥,您使用本例中给出的这个就可以。通过这个 API 将返回一个 JSON 格式的结果数据:

{ "zip" : "94105", "city" : "San Francisco", "state" : "CA" }

可以看出,它表示这个城市的 ZipCode 是 94015,城市名称是 "San Francisco",州的缩写是“CA”。

为了消费这两个服务,我们需要再建立两个 RestService 的实例,代码如下:

清单 8. 再建立两个 RestService 类的实例
var weatherService = RestService { 
    result: "" 
    source: "http://weather.yahooapis.com/forecastrss?p=94105" 
}; 
var locationInfoService = RestService { 
    result: "" 
    source: "http://api.sunlightlabs.com/places.getCityStateFromZip.php?zip=
        94105&apikey=23kj234kjb3kjbcl87ds" 
};

上面的例子一样,给 ZipCode 输入框设定动作,但这次同时更新两个 RestService 类的实例的 result 属性:

清单 9. 给 ZipCode 输入框设定动作
var zipCodeField = TextField { };
zipCodeField.action = operation() {
    weatherService.source=
    "http://weather.yahooapis.com/forecastrss?p={zipCodeField.value}";
    weatherService.update();
    locationInfoService.source=
        "http://api.sunlightlabs.com/places.getCityStateFromZip.php?zip=
        {zipCodeField.value}&apikey=23kj234kjb3kjbcl87ds";
    locationInfoService.update(); 
};

最后需要给界面中右侧的两个结果显示窗口分别绑定 text 属性到新建的 RestService 类的两个实例的 result 属性上去,用于显示结果。

保存,运行!在界面里面输入一个 5 位的数字将会看到下面的界面。

图 16. 最终的程序界面
图 16. 最终的程序界面
图 16. 最终的程序界面

到此为止,我们的 Mashup 应用已经基本建立起来了。但是大家可以看到,从 http://api.sunlightlabs.com 返回的数据只是原始的 JSON 格式数据,限于篇幅,本教程没有对数据进行进一步的解析处理。读者在学完这个教程之后,可以自己动手去尝试对返回的 JSON 数据进行进一步的处理。甚至可以将进一步处理的结果作为参数去调用第三个网站的 API,从而构建更复杂的 Mashup 应用。

本示例的源代码可以在本教程的源代码 下载 中得到。

部署 JavaFX

我们的 Mashup 例子刚才只是在 Eclipse 的 IDE 中运行。但是正如我们在 体验 JavaFX 界面 一节中看到的那样,Openjfx 项目的官方网站的 JavaFX 例子都是将 JavaFX 应用部署在网络上的。客户通过加载 JNLP 文件就可以用 JWS(Java Web Start)来运行。

为了将我们的应用也部署到服务器上,我们就首先要了解一下 JNLP 文件。

JNLP(Java Network Launching Protocol,Java 网络加载协议)。一个 JNLP 客户端就是一个应用程序或者说服务,它可以从宿主于网络的资源中加载应用程序。如果您使用 JNLP 打包一个应用程序,那么一个 JNLP 客户端能够:

  • 为该应用探测,安装并且使用正确版本的 JRE(Java 运行时环境)
  • 从浏览器或者桌面加载应用程序
  • 当新版本的应用出现时自动下载最新的版本
  • 为了加速启动速度在本机缓存应用程序需要的类
  • 可以作为 applet 或者 JavaFX 应用程序运行
  • 在必要的情况下下载原始的库
  • 以安全的方式使用诸如文件系统这样的本机资源
  • 自动定位和加载外部依赖资源

Sun 公司提供了一个 JNLP 的参考实现,即 Java Web Start(JWS)。

下面我们来探索一下 JNLP 文件的内容,用文本编辑器打开前面下载的 studiomoto.jnlp 文件,其内容如下:

<?xml version="1.0" encoding="utf-8"?>
<!--codebase 属性指出搜索应用程序资源的顶级 URL,
下面的 jar 元素的 href 都是相对这个 URL 的相对路径--> 
<jnlp 
    spec="1.5+" 
    codebase="http://download.java.net/general/openjfx/demos"
    href="studiomoto.jnlp">
    <information>
        <!--title :应用程序标题 vendor:供应商-->
        <title>JavaFX Demos:Motorola Music</title>
        <vendor>Sun Microsystems</vendor>
        <!-- 允许离线启动,可以使用javaws -offline命令-->
        <offline-allowed />
    </information>
    <security> 
        <all-permissions/>   
    </security> 
    <resources>
    <!-- 指定客户端需要安装的 JDK 版本和运行时参数,下面指定为1.5+,
    如果客户端现在版本是 1.4,在链接此 JNLP 文件时会提示更新 JDK 版本-->
        <j2se version="1.5+" href="http://java.sun.com/products/autodl/j2se"
        java-vm-args="-Xss1M -Xmx256M"></j2se>
        <!-- 指定要下载到本地的jar文件 -->
        <jar href="JavaFXrt.jar" main="true"/>
        <jar href="Filters.jar"/>
        <jar href="swing-layout.jar"/>
        <jar href="studiomoto.jar"/>
    </resources>
    <!--application-desc 指定 webstart 启动时执行 jar 文件中的哪个类-->
    <application-desc main-class="net.java.JavaFX.FXShell">
        <argument>studiomoto.StudioMoto</argument>
    </application-desc>
</jnlp>

配置文件的含义我已经在里面加以注释,由此我们可以看出程序主要是运行 studiomoto.jar 里面的代码。

根据以上对 JNLP 相关知识的介绍,我们可以看到,为了部署我们的应用:

  1. 首先要将我们的 JavaFX 的代码和引用的其他类库代码打包成相应的 Jar 文件部署到服务器上。关于 Jar 文件打包,解包使用签名等问题可以参见 参考资源
  2. 然后按照上面的 JNLP 文件的格式编写自己的 JNLP 文件,并且将 JNLP 文件也部署到服务器上,注意 JNLP 文件和 Jar 文件的路径问题,确保 Jar 文件能够正确的被加载到客户端。

限于篇幅,本文就不提供 JNLP 文件内容了,您可以在阅读完上述 JNLP 文件介绍后,自己动手将我们的 Mashup.fx 文件打包成一个 Jar 文件,并且编写相应的 JNLP 文件完成应用的部署工作。

通常来说,模仿是快速提高知识的一个有效途径。为了加深我们对 JavaFX 的理解,我们可以将例子的源码下载到本地加以研究。根据上述 Demo 的 JNLP 文件 codebase 和文件名的组合得到 studiomoto.jar 文件的地址:http://download.java.net/general/openjfx/demos/studiomoto.jar。 将该 Jar 文件下载到本地,由于 JavaFX 是脚本语言,我们还可以看到它的代码。

图 17. JavaFX 官网例子的代码结构
图 17. JavaFX 官网例子的代码结构

研究这些源码可以很好的提高您的 JavaFX 编程能力。

结束语

本文教程中,我们尽量结合例子,将 JavaFX 的产生背景、基本语法、UI设计、类的概念穿插进来。最后我们完成了一个界面比较复杂,并且使用 REST Style 的 Web 服务构建的 Mashup 应用。在各种 RIA 解决方案共存的情况下,JavaFX 的出现凭借它简单的语法,天生的跨平台,Java 类库强大的支持肯定会在 RIA 的领域占有一席之地。但作为新鲜面孔,要成为一枝独秀,我想 JavaFX 恐怕还要有一段比较长的路要走,让我们拭目以待吧!

致谢

十分感谢我在 IBM 的同事和 Mentor 陈威,以及我们 DB2 z/OS 开发团队的同事们对我的帮助!


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, Web development, Open source
ArticleID=254886
ArticleTitle=使用 Eclipse 和 JavaFX 开发 Mashup 应用
publish-date=09212007