文/陳剛 from www.chengang.com.cn
最近由于工作關系,老大囑咐我看一下Java Web Start。以前安裝JDK時,會在“開始”菜單加一個快捷菜單“Java Web Start”,也不知是做什么用的,我一般都是刪除。今天從網上查了一下資料,不看不知道,一看嚇一跳,覺得這JWS(Java Web Start簡稱)很象傳說中的“服務器端小程序下載運行”。而且JWS很早就有了,我看有些文章資料已經是2002年發(fā)的,自己竟然全然不知它的存在,實在是愚昧呀。
1. JWS有什么用
B/S風行的一個很大原因就是它有部署方便的優(yōu)勢,這是C/S的Application所無法比擬的。現(xiàn)在,JWS讓用戶可以下載服務器端的Java Application到本機運行,并且沒有安裝、配置等繁瑣的操作。SUN網站上有Demo,大家可以體驗一下效果:http://java.sun.com/products/javawebstart/demos.html 。
2. JWS的運行原理
瀏覽器的運行Java Applica ton的鏈接指向的不是程序本身,而是一個*.jnlp文件,這個文件包含了Java Application的一些配置信息。然后JWS解讀這個文件的信息,將服務器端的Java Application下載到本機上,并運行。
當然第一次運行程序時,由于要下載所以速度會稍微慢一些,不過第二次運行時,JWS會自動去服務器上檢查是否有新的程序版本發(fā)布,如果沒有就會直接運行本機已經下載的程序,這就和運行本機Java Application沒什么區(qū)別了。運行程序之初,JWS還會提示你是否創(chuàng)建一個相應的快捷菜單。
程序下載到本機的默認位置是:“C:\Documents and Settings\admin\Application Data\Sun\Java\Deployment\javaws\cache\indirect\indirect12423.ind”,你可以在本機的“JWS應用程序管理器”的里重新設置此存放目錄。

JWS無疑要比Applet的應用范圍更廣(據說還得過**的最佳創(chuàng)意獎),它對于布署一些小型的程序應用是非常方便的,但我以為現(xiàn)在還主要適用于局域網。因為一個程序一般約有幾十M,如果是Internet用戶第一次的下載速度會很慢。
3. 安全性問題
但和Applet一樣,JWS也面臨安全性問題,默認情況下JWS對本機磁盤和本地網絡的訪問是有限制的。如果該程序要越權訪問,這時會彈出一個警告框(類似于ActivX的數(shù)字簽名),用戶可以自已決定是否信任該軟件,而對其放開限制。
4. JWS的優(yōu)缺點
JWS的優(yōu)點就是讓程序的布署更簡單,而且用戶端的應用可以時刻保持和服務器端的最新版本同步,這為升級版本提供了很大的方便。缺點也是明顯的,由于要運行應用必須一次下載所有的程序文件(JWS的jnlp配置文件有個lazy選項,但作用不明顯),所以第一次下載速度很慢,不適用于互聯(lián)網。從這一點來看B/S形式的應用還是有優(yōu)勢的。
5. 參考資料
http://www.chinaitlab.com/www/news/article_show.asp?id=25239
http://blog.csdn.net/emag_java/archive/2005/01/13/252047.aspx
Java Web Start實例
1、示例說明
由于本BLOG現(xiàn)主要以Eclipse和SWT為內容,所以Java Web Start(簡稱JWS)也以一個SWT應用程序來做為示例。本文用<Eclipse從入門到精通>書中打包一章的打包結果為示例,該示例為一個SWT/JFace程序,其打包后的文件結構如下:

說明:
- myswt是主包,里面含有自己寫的程序代碼
- swt-win32-3063.dll是本地化文件
- lib子目錄下還有三個jar文件:jface.jar、runtime.jar、swt.jar,這三個文件是SWT程序的支持庫
如果是在本地運行此程序,雙擊myswt.jar即可(要求Windows中jar格式的文件默認用javaw.exe打開,如下圖所示:
現(xiàn)在我們要將這個程序用JWS部署到服務器端,然后編寫一個網頁,讓用戶單擊網頁上的鏈接就可以下載該SWT程序并運行。
2、準備工作
本人的開發(fā)環(huán)境為:WinodwsXP SP2 + JDK1.4.2 + Tomcat 5.0.28
(1)首先得先安裝Tomcat,這一步的操作方法本文省略
(2)在Tomcat的webapps\ROOT路徑下創(chuàng)建一個“myswt”目錄。在我的電腦上,其絕對路徑如下:E:\Program Files\Apache Software Foundation\Tomcat 5.0\webapps\ROOT\myswt。
(3)將前面所述的SWT程序的文件復制到webapps\ROOT\myswt目錄中。
3、生成證書
創(chuàng)建一個批處理文件:key.bat
c:\jdk\bin\keytool -genkey -keystore myKeystore -alias myself
c:\jdk\bin\keytool -list -keystore myKeystore
pause
說明:
- keytool是JDK自帶的一個工具,用于數(shù)字簽名。在我的電腦,它是位于c:\jdk\bin\路徑下,由于我沒有設置環(huán)境變量path,所以在批處理文件中硬性指定keytool的路徑。如果是自己用或者公司內部用,象本文這樣用keytool生成一個自簽名的證書也就可以了。但如果你想讓簽名更正式一些,以獲得其他用戶的信任,最好去認證中心(如 Thawte 或 VeriSign)獲取一個證書。
- 第一句將生成一個證書,文件名:myKeystore
- 第二句是列出密鑰證書中的所有入口。(這一句是可選的,只是為了顯示出來看一下,不要也行)
- 最后一句是暫停pause,以便批處理完成后,我們可以回顧一下全過程。
運行批處理key.bat后的全部輸入過程如下圖所示:

4、用證用為應用程序簽名
(1)因為簽名只認jar包,所以先將swt-win32-3063.dll文件用WinRAR或c:\jdk\bin\jar打一個jar包(swt-win32-3063.jar)。客戶端下載后,會自動解開此包,將swt-win32-3063.dll還原到客戶端。
注意:如果你用WinRAR打包,在壓縮時必須選ZIP格式,不能選RAR格式。
(2)創(chuàng)建一個用于簽名的批處理文件:jarsigner.bat,其內容如下:
c:\jdk\bin\jarsigner -keystore myKeystore myswt.jar myself
c:\jdk\bin\jarsigner -keystore myKeystore lib\jface.jar myself
c:\jdk\bin\jarsigner -keystore myKeystore lib\runtime.jar myself
c:\jdk\bin\jarsigner -keystore myKeystore lib\swt.jar myself
c:\jdk\bin\jarsigner -keystore myKeystore swt-win32-3063.jar myself
pause
這里每一條命令都要求你輸入密碼,它就是在創(chuàng)建證書myKeystore時設置的那個密碼。至此,簽名證書部份完成了,下一步是創(chuàng)建jnlp文件。
5、創(chuàng)建jnlp文件
(1)創(chuàng)建一個名為myswt.jnlp的jnlp文件,這個文件是Java Web Start的核心配置文件,其內容如下:
<?xml version="1.0" encoding="GBK"?>
<jnlp codebase="http://localhost:8080/myswt">
<information>
<title>子在川曰(http://blog.csdn.net/glchengang)</title>
<vendor>陳剛</vendor>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="1.4+"/>
<jar href="myswt.jar"/>
<jar href="lib/jface.jar"/>
<jar href="lib/runtime.jar"/>
<jar href="lib/swt.jar"/>
<nativelib href="swt-win32-3063.jar"/>
</resources>
<application-desc main-class="jface.dialog.wizard.WizardDialog1"/>
</jnlp>
說明:
- encoding="GBK" 本文選擇了GBK,一般來說應該用UTF-8。我在這里之所以選擇GBK字符集,主要是為了演示示例方便,如果是正式應用,還是應該改為UTF-8。如果用UTF-8,則該文件的中文要轉換成UNICODE碼,否則實際運行時將顯示亂碼,你可以用c:\jdk\bin\native2ascii.exe來進行“漢字->UNICODE”的轉換。
- codebase="http://localhost:8080/myswt" 本應用程序的URL
- <information>項,是一些顯示信息,<title>、<vendor>都是必選的。<offline-allowed/>是可選的,它表示允許應用程序脫機運行(不和服務器聯(lián)網)。
- <security>項是指開放用戶本機的所有權限給應用程序,這一項會導致彈出一個數(shù)字簽名對話框。
- <resources>列出了用戶需要下載的資源。<j2se version="1.4+"/>是指,要求用戶本機安裝Java1.4以上版本。<nativelib>是指此包含有本地文件,這時JWS下載后會將此包解開。
- <application-desc>指定了程序的入口類,你也可以指定其他的入口類,它不受限制。jface.dialog.wizard.WizardDialog1是myswt.jar包中的一個向導式對話框,這是我自己編寫的一個SWT程序。
(2)創(chuàng)建一個HTML網頁,網頁指向jnlp文件。我們給此HTML網頁取名:test.html,其內容如下:
<A HREF="myswt.jnlp">啟動</A>
6、最后效果
(1)最后的服務器的目錄結構如下圖所示:

(2)用瀏覽器瀏覽:http://localhost:8080/myswt/test.html

單擊“啟動”后出現(xiàn)下圖,開始從服務器上下載SWT應用程序:

下載完成后,出現(xiàn)如下圖,提示用戶是否向應用程序開放本機所有權限(彈出這個對話框是由jnlp文件中的<security>項設置決定的)。
單擊“啟動”按鈕,將運行程序,出現(xiàn)下圖。(附注:這里沒有彈出提示你添加快捷菜單的對話框)

7、其他注意事項
(1)如果單擊網頁的“啟動”鏈接時,顯示的是jnlp文件的內容,還非下載服務器的應用程序。這時你需要做如下檢查:
-
在Windows中,jnlp格式的文件應該默認用javaw打開。如果你把它改變成了用記事本或其他程序打開,就也會出錯。
-
WEB服務器是否能否辨識jnlp、jar、class文件的格式。如果你是用Tomcat,可以打開conf目錄的WEB.XML文件檢查一下。一般來說,較新的WEB服務器都支持jnlp,如果Tomcat、WebLogic等(微軟的IIS不支持Java,當然也不可能支持jnlp,我是這么想的沒去測試過)。如果不支持,就在WEB服務器的配置文件里加上下面的內容。
<mime-mapping>
<extension>class</extension>
<mime-type>application/java</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jar</extension>
<mime-type>application/java-archive</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jnlp</extension>
<mime-type>application/x-java-jnlp-file</mime-type>
</mime-mapping>
(2)在使用Java Web Start的時候可能會出現(xiàn)"下載資源錯誤",大致的出錯信息如下:
JNLPException[category: Download Error : Exception:
java.io.IOException:
rename failed in cache : LaunchDesc: null ] at.....
這個錯誤的原因是因為每次調用Java Web Start都會到server上查找程序是否更新,然后將程序下載到本地的java web start目錄下的cache目錄中,如果cache中已經有同名文件,而且該文件正在被使用,那么新下載的文件就會出現(xiàn) rename failed錯誤,而且手工去刪除本地的文件還會報錯:文件正被使用!
這里涉及到Java Web Start中的sign機制,可能對每個jar文件都需要標記,有的時候會在任務管理器中看到javaw.exe在運行,將該程序終止后就可以將本地的jar文件刪除掉,說明這些本地文件可能還保留著文件鎖定吧!有時即使將Task Manager中將所有的java程序都kill掉還是會出錯,必須要注銷windows才可以,不知道是不是Java Web Start
(3)如果需要給*.jar文件傳遞參數(shù),可以用如下代碼:
<application-desc main-class="XBFrame"/>
<argument>-port</argument>
<argument>1008</argument> "注意-port和1008是兩個參數(shù),要分開寫
</application-desc>
(4)有的時候還需要看到*.jar中System.out.print語句輸出的信息,就要打開jws的console,可以在jws manager 中的首選項中設置(附注:(2)、(3)、(4)照抄<<java web start實現(xiàn)關鍵問題(二)>>一文)
(5)如果出現(xiàn)失敗,最基本的查錯手段就是看看出錯的“詳細信息”,如下圖所示。
單擊“詳細信息”按鈕,出現(xiàn)下圖
參考資料
作者簡介