程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 通過CD-ROM分發Java Web Start應用程序

通過CD-ROM分發Java Web Start應用程序

編輯:關於JAVA

眾所周知,Java Web Start (JWS) 支持以基於 Web 的方式來分發應用程序。 既然如此,為何還要通過 CD-ROM 來分發 Java Web Start (JWS) 應用程序呢? 這有許多原因。對於較大的應用程序,完整安裝可能會是一項寵大的下載任務, 即便使用高速帶寬也無濟於事。其次,並非所有的桌面系統都是在線的,並且不 一定都能訪問互聯網(例如,考慮到公司的安全性)。最後,部分人僅僅是喜歡 使用 CD。

一家客戶公司曾要求將它們的應用程序分發到世界的任何范圍,包括寬帶覆蓋 不到的地方。該應用程序包含大量產品的相關信息,包括詳細的圖表。所有這些 信息構成了應用程序的主要部分,並且包括 JVM 在內的完整安裝將超過 40 MB。 除此之外,公司還希望能夠在商品交易會通過 CD 分發應用程序,並附贈宣傳材 料;因此,基於 CD 的分發是非常有必要的。通常,CD 安裝可以采用商業或開源 的安裝程序,而這些安裝程序比比皆是。但是,使用 Java Web Start 運行應用 程序時,需要將應用程序安裝在特定的位置,而不受用戶的意願控制,這是安裝 程序的規定。

本文介紹如何通過 CD 或互聯網安裝應用程序。安裝流程具有如下要求:

已安裝的應用程序檢查更新並與 JWS 緩存集成。

安裝應在未安裝 Java 的機器上完成。

已安裝的應用程序應不要求互聯網連接。

安裝必須易於使用,並且必須提供一個簡單的用戶界面。

應用程序安裝通常由通用的安裝程序執行,但傳統的安裝流程會有效地創建一 個單獨的、對 JWS 一無所知的應用程序。每次發布更新時,用戶都需要下載並安 裝新版本,而 JWS 應用程序只需要下載經過更新的組件,這種流程更加有效和可 靠。因此,本文還將介紹 JWS 應用程序的安裝程序。

JWS Primer

Java Web Start 允許通過到 JNLP 文件的鏈接來啟動 Java 應用程序。JNLP 文件描述主方法或應用程序的入口點,並引用應用程序所使用的資源。

當 JWS 應用程序啟動時,JVM 將嘗試訪問所需的資源,並根據需要更新它們 ,然後將文件復制到緩存中。隨後嘗試啟動應用程序時,JWS 可以檢查該緩存並 跳過資源下載步驟。如果客戶機器為離線狀態,或者如果無法連接服務器,則 JWS 可以在離線模式中運行應用程序。

如果 JWS 啟動文件(JNLP)保存在 CD 中,則 JWS 將聯系服務器並下載任何 新文件。顯然,如果客戶機器在線,這將破壞通過 CD 分發文件的計劃。相反, 我們需要采用一些方法來更新 JWS 緩存,就像應用程序已由 JWS 預先載入一樣 。

更新 JWS 緩存

Java 5 版本的 JWS 包含一個 -import 選項,它的作用是將特定位置下的 JWS 應用程序導入到緩存中。

此位置上的 CD 映像只是 Web 服務器上的一個副本:JNLP 文件、.jar 文件 和該 JNLP 文件引用的資源。如果使用 servlet 服務於此 JNLP,則 CD 映像將 需要生成的 JNLP 文件的一個功能完備的快照。

因此,可以通過調用以下命令將 CD 映像安裝到 JWS 緩存中:

<JAVA_HOME>/jre/bin/javaws -codebase <CACHE_IMAGE> - import <CACHE_IMAGE>/<XXXX>.jnlp

其中,<JAVA_HOME> 是 JVM 的根目錄,<CACHE_IMAGE> 是 JWS 應用程序在 CD 上的位置,而 <XXXX> 是應用程序 JNLP 文件的名稱。稍 後,我們將介紹如何自動化此命令並將它包裝在一個簡單的 GUI 中。

在安裝緩存中的應用程序時,JWS 會提示用戶安裝啟動應用程序的桌面和菜單 快捷方式。完成 JWS 安裝後,我們可以再次調用 JWS 啟動最新安裝的應用程序 。

<JAVA_HOME>/jre/bin/javaws -import <CACHE_IMAGE>/<XXXX>.jnlp

這將再次使用 CD,但 JWS 這次將使用 JNLP 文件引用的安裝。如果機器已與 互聯網連接,它將采用通常方式檢查更新,然後啟動應用程序。如果沒有網絡連 接,則應用程序以 CD 交付的標准啟動。

當用戶下次啟動應用程序時,他們可以使用菜單或桌面快捷方式,而不再需要 CD。或者,用戶可以通過頁面上指向相同 URL/JNLP 文件組合的鏈接來啟動應用 程序;也就是站點上的原始版本。

JVM 因素

整個過程中的一個問題是,上述命令需要 JVM 的支持,而在少數一些情況下 ,系統中默認可能沒有安裝 JVM 或者 JVM 在系統路徑中不可用;因此,需要采 取一些額外措施來定位可用的 JVM。此外,當用戶插入 CD 時,安裝程序應該能 啟動並檢查 JVM 是否已存在。檢查 JVM 的流程如下所示:

檢查 JVM(針對安裝程序)。

如果未檢測到 JVM,則安裝它。

啟動安裝程序,顯示通常的許可信息。

安裝目標 JVM(如果應用程序需要)。

導入 JWS 緩存。

啟動 JWS 應用程序。

JWS -import 選項要求最低的 JWS 版本為 Java 5,因此,即便應用程序有可 用的 JVM,但此 import 選項仍然需要一個較新版本的 JVM 支持。其次,import 進程需要花費一些時間,並且必須在應用程序啟動之前完成,而許多普通安裝程 序都難以實現這種延時的執行。

考慮到這些因素,構建一個自定義啟動應用程序來執行這些步驟是有必要的。

運行安裝

由於 JWS -import 命令將完成安裝流程中涉及的大部分實際工作,因此啟動 應用程序的主要任務就是使用合適的命令找到並啟動 JVM,然後通過 GUI 讓用戶 了解安裝狀態。

查找 JVM

在 Windows 中,可以在系統注冊表的 HKEY_LOCAL_MACHINESOFTWAREJavaSoftJava Runtime Environment 鍵下面查找 JVM。該鍵可能包含多個值,因此應用程序將迭代這些條目並嘗試查找最新版本且 可用的 JVM。

以下方法接受最小和最大版本號作為參數,並嘗試查找 JVM 的路徑:

private String getInstalledPath(
int majorMin, int minorMin, int revMin,
int majorMax, int minorMax, int revMax )
{
String installedPath = null;
int latestVersion = 0;
String keyRoot =
"HKEY_LOCAL_MACHINESOFTWAREJavaSoft" +
"Java Runtime Environment";
Vector results = getRegEntries( """ + keyRoot + "" /s" );
int numEntries = results.size();
for ( int i = 0; i < numEntries; i++ ) {
String key = results.get( i++ ).toString();
int pos = key.indexOf( "Java Runtime Environment" );
if ( pos > 0 ) {
pos += "Java Runtime Environment".length() + 1;
String version = key.substring( pos );
String parts[] = version.split( "[._]" );
int majorVersion, minorVersion, revision;
majorVersion = Integer.parseInt( parts[ 1 ] );
if ( parts.length > 3 )
minorVersion = Integer.parseInt( parts[ 2 ] );
else
minorVersion = 0;
if ( parts.length > 4 )
revision = Integer.parseInt( parts[ 3 ] );
else
revision = 0;
if ((( majorVersion == -1 ) ||
( majorVersion >= majorMin )) &&
(( majorVersion == -1 ) ||
( majorVersion <= majorMax ))) {
if ((( minorMin == -1 ) ||
( minorVersion >= minorMin )) &&
(( minorMax == -1 ) ||
( minorVersion <= minorMax ))) {
if ((( revMin == -1 ) ||
( revision >= revMin )) &&
(( revMax == -1 ) ||
( revision <= revMax ))) {
// Prefer the neweset acceptable version
int thisVersion = majorVersion * 10000 +
minorVersion * 100 + revision;
if ( thisVersion > latestVersion ) {
String value = null;
while ( i < numEntries ) {
value = results.get( i++ ).toString().trim();
if ( value.startsWith( "JavaHome" ))
break;
}
installedPath = value.substring(
value.indexOf( "REG_SZ" ) + 6 ).trim();
latestVersion = thisVersion;
}
}
}
}
}
}
return installedPath;
}

上述方法的作用是查找注冊表條目。可以通過一些 API 來獲 取注冊表的值,但是對於這種情況,最實際的方法是使用簡單的命令行 REG QUERY <key>,其中,<key> 是查詢的注冊表路徑。下面這個方法將 運行該命令並從輸出流中讀取條目,然後將它作為 Vector 返回:

private Vector getRegEntries( String key )
{
Vector results = new Vector();
try {
Process proc = Runtime.getRuntime().exec( "REG QUERY " +
key );
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String result = "";
String line;
while (( line = br.readLine()) != null ) {
line = line.trim();
results.add( line );
}
return results;
}
catch ( Exception ex ) {
message( language.getString("6") + ex.getMessage() );
ex.printStackTrace();
}
return null;
}

安裝 JVM

如果無法找到合適的 JVM,那麼可以通過 CD 安裝它,只要知道它的位置就行 。啟動程序使用一個資源文件定位所需的各種資源,並通過此機制定向到 JVM 安 裝包。啟動 JVM 安裝的方法仍然是使用正確的命令,但這次,由於進程運行的時 間相對較長,因此需要等待它運行完成。execed 進程的 waitFor 方法將使線程 等待,但是為了避免阻塞 UI 線程,需要將它嵌入在一個 SwingWorker 中:

private void installJre()
{
try {
final String javaInstall = (String)props.get(
"jre_installer" );
status.setText( language.getString("3") );
SwingWorker worker = new SwingWorker()
{
public Object construct()
{
try {
Process process = Runtime.getRuntime().exec(
workingDir + File.separatorChar +
javaInstall );
process.waitFor();
exitValue = new Integer( process.exitValue());
}
catch ( Exception ex ) {
exitValue = new Integer( -1 );
ex.printStackTrace();
}
return exitValue;
}
public void finished()
{
int ev = exitValue.intValue();
if ( exitValue != 0 ) {
status.setText( language.getString("Error:_") +
exitValue );
message( language.getString("4") );
}
else {
installedJrePath = getInstalledPath( 5, -1, -1,
5, -1, -1 );
doInstall( installedJrePath );
}
status.setText( "" );
}
};
worker.start();
}
catch ( Exception ex ) {
status.setText( language.getString( "5" ));
ex.printStackTrace();
}
}

啟動 JWS 和 Wait

定位到 JVM 之後,可以使用適當的命令行來啟動它。在調用 JWS 時,初次調 用 import 可能需要花費一些時間,因此需要再次使用 waitFor 方法,而第二次 調用只需要啟動應用程序即可(並讓它執行自己的任務)。當應用程序啟動之後 ,可以退出啟動應用程序,它的任務已經完成:

private void launchWebStart( String javaWSPath,
String jnlpPath,
String userDir )
{
try {
String webStartCommand = """ + javaWSPath + """ + " -wait
-codebase file:///" + userDir + ""+ appDirectory +
" -import " + jnlpPath;
Process process = Runtime.getRuntime().exec(
webStartCommand );
process.waitFor();
int exitValue = process.exitValue();
if ( exitValue != 0 )
status.setText( language.getString("7") );
else
status.setText( language.getString("8") );
int rc = JOptionPane.showConfirmDialog( null,
language.getString("9"),
language.getString("10"),
JOptionPane.YES_NO_OPTION );
if ( rc == JOptionPane.YES_OPTION )
Runtime.getRuntime().exec( javaWSPath + " -offline " +
jnlpPath );
status.setText( language.getString("11") );
SwingWorker worker = new SwingWorker()
{
public Object construct()
{
try {
Thread.currentThread().sleep( 3000L );
}
catch ( Exception ex ) {
}
return null;
}
public void finished()
{
System.exit( 0 );
}
};
worker.start();
}
catch ( Exception ex ) {
status.setText( language.getString("12") );
ex.printStackTrace();
}
}

包裝

解決安裝的內在機制之後,啟動程序還需要一個簡單的用戶界面(如圖 1 所 示),讓用戶了解當前的進展情況:

圖 1. 安裝程序歡迎頁面(單擊圖片查看大圖)

用戶界面已通過 config.properties 文件進行了定位和配置,包括徵標、應 用程序位置和 JVM 版本。 Aria 項目 已根據開源許可提供了完整的應用程序和 源代碼。

完成啟動應用程序的創建和測試之後,最後一步需要創建一個完整的 CD 安裝 ,即插入 CD 時啟動安裝的 autorun 特性。有關在 Windows 中創建 autorun.inf 文件的詳細信息,請參閱 Autorun的 Wikipedia 條目,但該特性需 要一個本機可執行的文件。可以通過 Launch4J 包裝器來創建這種可執行文件。 下載的源文件中包含一個簡單的 Launch4J 配置文件。運行後,Launch4J 將為應 用程序創建一個 .exe 文件。再次,需要在包裝器中綁定一個 JVM,因為此處的 啟動應用程序是一個 java 應用程序,並且最終用戶的系統可能沒有安裝 JVM。

創建 .exe 之後,可以創建 autorun.inf 文件並將它添加到 CD 映像中。

[autorun]
open=XXXX.exe
icon=xxxx.ico
action=Open XXXX
label=My Application

跨平台問題

應用程序啟動程序依賴一些特定於 Windows 的特性,因此只能在 Windows 中 運行。但是,本文所介紹的技術是可以跨平台的,因此檢查您是否使用其他平台 的原因是考慮到 本機啟動程序 的可用性。舉例來說,IzPack 提供了適用於多個 平台的啟動程序。此外,如果您知道所使用的平台包括 JVM(比如說 Mac OS X) ,則本機啟動程序可能是冗余的,因此可以直接運行應用程序。

結束語

通過結合 Java Web Start 與 Launch4J,我們可以將創建的應用程序分發給 交易會來訪者,使他們能夠方便並快速的安裝應用程序。Java Web Start 的完整 更新功能對於用戶仍然可用,因此他們可以方便地獲取更新,並能在沒有互聯網 連接的地方使用應用程序。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved