在java開發的早期,重點被放在了用戶端開發。語言中對於applet和安全下載的支援
對於全球資訊網(WWW)的發布看上去是個不錯的主意。但是現實是java最大的成功在於伺服器端,java的強大功能和適應性贏得了伺服器端開發人員的心。同時,用戶端的開發落後了。棘手的開發問題限制了applet的效用,開發人員被迫轉向基於瀏覽器的瘦用戶端。
Java Network Launching Protocol (JNLP,java網路載入協議) 承諾改變這個現狀。通過JCP(Java Community Process)的JSR-56的開發,
JNLP解決了很多先前用java開發針對用戶端的功能的問題。一個JNLP用戶端是一個應用程式或者說服務,它可以從宿主於網路的資源中載入應用程式。如果你使用JNLP打包一個應用程式,那麼一個JNLP用戶端能夠:
o 為該應用探測,安裝並且使用正確版本的JRE(java運行時環境)
o 從瀏覽器或者案頭載入應用程式
o 當新版本的應用出現時自動下載最新的版本。
o 為了加速啟動速度在本機緩衝應用程式需要的類
o 可以作為applet或者應用程式運行
o 在必要的情況下下載原始的庫
o 以安全的方式使用諸如檔案系統這樣的本機資源
o 自動定位和載入外部依賴資源
Sun 提供了一個實現JNLP的稱為Java Web Start(JWS)的參考實現。讓我們使用它開發一個使用JFC Swing的簡單應用。為了做這個,你需要從http://java.sun.com/products/javawebstart下載JWS。(譯者註:JDK的新版本JDK1.4已經內建JWS,無須另外下載。)
下面是應用程式的代碼:
//File HelloJNLP.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class HelloJNLP extends JFrame {
public HelloJNLP() {
super("Hello JNLP");
String loadedFrom = this.getClass().getClassLoader().toString();
JLabel jl = new JLabel("loaded by " + loadedFrom);
JEditorPane jtp = new JEditorPane("text/plain",
"Edit this text");
getContentPane().add(jl, BorderLayout.NORTH);
getContentPane().add(jtp, BorderLayout.CENTER);
}
public static void main(String [] args) {
JFrame f = new HelloJNLP();
f.setBounds(100,100,325,250);
f.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.out.println("Shutting down...");
System.exit(0);
}
});
}
}
JNLP的核心是一個發布清單(deployment manifest)。它是一個使用.jnlp做
副檔名的XML檔案(JNLP規範簡單的稱之為"JNLP 檔案")。要發布HelloJNLP,你需要在JNLP檔案中描述它,就像下面這樣:
<?xml version="1.0" encoding="UTF-8"?>
<!-- file Hello.jnlp -->
<jnlp codebase="http://staff.develop.com/halloway/TechTips/May2001"
href="http://staff.develop.com/halloway/TechTips/May2001/Hello.jnlp">
<information>
<title>Hello</title>
<vendor>Tech Tips Sample May 2001</vendor>
<icon href="http://www.supcode.com/Article/html/4/43/2005/03/05/HelloJNLP.jpg"/>
</information>
<resources>
<j2se version="1.2+"/>
<jar href="HelloJNLP.jar"/>
</resources>
<application-desc main-class="HelloJNLP"/>
</jnlp>
這個清單包含用戶端需要下載和使用HelloJNLP的所有資訊:
o jnlp元素的codebase屬性指出搜尋應用程式資源的頂級URL。
o information元素指出一個JNLP使用者介面可以顯示給用戶端的資訊。
o j2se元素指出用戶端必須有1.2版本或者更新的J2SE(tm)。(這是對於applet開發的一個大的提高,因為它常常受限於瀏覽器提供的VM(虛擬機器))
o jar元素指出程式的JAR檔案的相對於jnlp codebase位置。
o application-desc元素指出要啟動並執行類。你可以添加子項目用以指定命令列參數或者系統屬性。
要將這個應用程式發布給一個web伺服器,你需要執行以下的步驟:
1. 修改jnlp的codebase和hrefURL為你自己的web伺服器的合適的URL。
2. 將JNLP檔案發布到web伺服器。
3. 編譯並打包HelloJNLP.java並發布到web伺服器。例如:
jar cvf HelloJNLP.jar HelloJNLP.class HelloJNLP$1.class
4. 建立一個表徵圖http://www.supcode.com/Article/html/4/43/2005/03/05/HelloJNLP.jpg並將之安裝在web伺服器上。你可以使用
http://staff.develop.com/halloway/TechTips/May2001/http://www.supcode.com/Article/html/4/43/2005/03/05/HelloJNLP.jpg
5. 設定你的web伺服器的mime-type關聯:.jnlp映射到mime-type application/x-java-jnlp-file。例如,對於Apache,添加如下一行到mime.types:
application/x-java-jnlp-file jnlp
重新啟動web伺服器。
從用戶端執行那個應用程式,首先確認你已經安裝了JWS。然後簡單的在瀏覽器中指向該jnlp檔案。JWS用戶端將下載該jnlp檔案,下載必要的資源,載入應用程式。你所看到的將是在一個編輯區中顯示的文本"Edit this text" 。如果你在配置web伺服器上有問題或者不能使用web伺服器,你可以從
http://staff.develop.com/halloway/TechTips/May2001/Hello.jnlp
載入這個程式。
注意HelloJNLP不是作為一個applet運行在瀏覽器中,而是作為一個獨立的應用程式。
當你關閉程式時,HelloJNLP使用System.out列印訊息"Shutting down...",然而沒有控制台可見。控制台是JWS的諸多設定中預設設定為"off"的其中一個。這是你可以修改的一對設定中的一個值,就像下面這樣:
1. 編輯JWS安裝目錄中的javaws.cfg檔案。添加一行"javaws.cfg.forceUpdate=true"。
這會導致JWS在啟動應用程式前自動檢查更新的版本。
2. 運行JWS。使用菜單File->Preferences,進入Advanced標籤並且選擇"Show Java Console"。(由於JDK1.4中的本機化,JWS將顯示中文的介面,所以此處的因為被自動顯示為對應的中文)同意,選擇"Log Output"將日誌輸出到你選擇的檔案。當你在調試時並且需要捕獲System.out和System.err時是非常有用的。
HelloJNLP顯示一個編輯器,但是編輯器的內容在你關閉程式後將丟失。將下面的代碼添加到HelloJNLP.java會自動的將編輯器的狀態儲存到用戶端的硬碟上:
//changes to HelloJNLP.java
import java.io.*;
import java.net.*;
import javax.jnlp.*;
//replace the constructor with this new version:
JEditorPane jtp;
public HelloJNLP() {
super("Hello JNLP, Second Version");
String loadedFrom = this.getClass().getClassLoader().toString();
JLabel jl = new JLabel("loaded by " + loadedFrom);
jtp = new JEditorPane("text/plain", "Edit this text");
readEditorContents();
getContentPane().add(jl, BorderLayout.NORTH);
getContentPane().add(jtp, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.out.println("Shutting down...");
try {
writeEditorContents();
}
catch (Exception ex) {
System.out.println("Yoinks!");
ex.printStackTrace();
}
System.exit(0);
}
});
}
//add these helper methods
private void writeEditorContents() throws
UnavailableServiceException, IOException {
System.out.println("writeEditorContents");
PersistenceService ps = (PersistenceService)
ServiceManager.lookup("javax.jnlp.PersistenceService");
BasicService bs = (BasicService)
ServiceManager.lookup("javax.jnlp.BasicService");
URL baseURL = bs.getCodeBase();
System.out.println("CodeBase was " + baseURL);
URL editorURL = new URL(baseURL, "Editor");
try {
ps.create(editorURL, 1024);
}
catch (Exception e) {
e.printStackTrace();
}
FileContents fc = ps.get(editorURL);
DataOutputStream os = new DataOutputStream(
fc.getOutputStream(false));
String s = jtp.getText();
os.writeUTF(s);
os.flush();
os.close();
}
private void readEditorContents() {
try {
PersistenceService ps = (PersistenceService)
ServiceManager.lookup("javax.jnlp.PersistenceService");
BasicService bs = (BasicService)
ServiceManager.lookup("javax.jnlp.BasicService");
URL baseURL = bs.getCodeBase();
URL editorURL = new URL(baseURL, "Editor");
FileContents fc = ps.get(editorURL);
DataInputStream is = new DataInputStream(fc.getInputStream());
jtp.setText(is.readUTF());
is.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
(譯者註:正常編譯需要在CLASSPATH中添加javaws.jar的路徑,在windows下為C:/Program Files/Java Web Start目錄下)
JNLP API定義了一套的服務用以繞過安全沙箱使得一些通常的用戶端操作可以使用。
在writeEditorContents方法中,BasicService尋找應用程式的代碼目錄,然後
PersistenceService將編輯區的內容緩衝在本機硬碟上,這些內容被鍵入到一個和應用程式目錄相對的URL下。PersistenceService提供的名字/值對資料和瀏覽器的cookies很相似。JWS通過一對被稱為"muffins"的東西實現了這個,muffins不時候用來儲存大資料,他們應該用於在用戶端緩衝小的標識符。然後這些標識符能被用於在伺服器上定位大的資訊。
在web伺服器上重新發布修改過的應用程式,然後試著從用戶端運行它--依然通過URL。如果你沒有web伺服器,你可以從
http://staff.develop.com/halloway/TechTips/May2001/Hello2.jnlp 運行這個新版本
轉自:http://hi.baidu.com/ilotus_y/blog/item/09161fec7b24162263d09f63.html