posts - 14,  comments - 37,  trackbacks - 0
          在java開發(fā)的早期,重點(diǎn)被放在了客戶端開發(fā)。語言中對(duì)于applet和安全下載的支持
          對(duì)于萬維網(wǎng)(WWW)的發(fā)布看上去是個(gè)不錯(cuò)的主意。但是現(xiàn)實(shí)是java最大的成功在于服務(wù)器端,java的強(qiáng)大功能和適應(yīng)性贏得了服務(wù)器端開發(fā)者的心。同時(shí),客戶端的開發(fā)落后了。棘手的開發(fā)問題限制了applet的效用,開發(fā)者被迫轉(zhuǎn)向基于瀏覽器的瘦客戶端。

          Java Network Launching Protocol (JNLP,java網(wǎng)絡(luò)加載協(xié)議) 承諾改變這個(gè)現(xiàn)狀。通過JCP(Java Community Process)的JSR-56的開發(fā),
          JNLP解決了很多先前用java開發(fā)針對(duì)客戶端的功能的問題。一個(gè)JNLP客戶端是一個(gè)應(yīng)用程序或者說服務(wù),它可以從宿主于網(wǎng)絡(luò)的資源中加載應(yīng)用程序。如果你使用JNLP打包一個(gè)應(yīng)用程序,那么一個(gè)JNLP客戶端能夠:

          o 為該應(yīng)用探測(cè),安裝并且使用正確版本的JRE(java運(yùn)行時(shí)環(huán)境)
          o 從瀏覽器或者桌面加載應(yīng)用程序
          o 當(dāng)新版本的應(yīng)用出現(xiàn)時(shí)自動(dòng)下載最新的版本。
          o 為了加速啟動(dòng)速度在本機(jī)緩存應(yīng)用程序需要的類
          o 可以作為applet或者應(yīng)用程序運(yùn)行
          o 在必要的情況下下載原始的庫(kù)
          o 以安全的方式使用諸如文件系統(tǒng)這樣的本機(jī)資源
          o 自動(dòng)定位和加載外部依賴資源

          Sun 提供了一個(gè)實(shí)現(xiàn)JNLP的稱為Java Web Start(JWS)的參考實(shí)現(xiàn)。讓我們使用它開發(fā)一個(gè)使用JFC Swing的簡(jiǎn)單應(yīng)用。為了做這個(gè),你需要從http://java.sun.com/products/javawebstart下載JWS。(譯者注:JDK的新版本JDK1.4已經(jīng)內(nèi)置JWS,無須另外下載。)

          下面是應(yīng)用程序的代碼:

          //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的核心是一個(gè)發(fā)布清單(deployment manifest)。它是一個(gè)使用.jnlp做
          擴(kuò)展名的XML文件(JNLP規(guī)范簡(jiǎn)單的稱之為"JNLP 文件")。要發(fā)布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="HelloJNLP.jpg"/>
            </information>
            <resources>
              <j2se version="1.2+"/>
              <jar href="HelloJNLP.jar"/>
            </resources>
            <application-desc main-class="HelloJNLP"/>
          </jnlp>

          這個(gè)清單包含客戶端需要下載和使用HelloJNLP的所有信息:

          o jnlp元素的codebase屬性指出搜索應(yīng)用程序資源的頂級(jí)URL。
          o information元素指出一個(gè)JNLP用戶接口可以顯示給客戶端的信息。
          o j2se元素指出客戶端必須有1.2版本或者更新的J2SE(tm)。(這是對(duì)于applet開發(fā)的一個(gè)大的提高,因?yàn)樗3J芟抻跒g覽器提供的VM(虛擬機(jī)))
          o jar元素指出程序的JAR文件的相對(duì)于jnlp codebase位置。
          o application-desc元素指出要運(yùn)行的類。你可以添加子元素用以指定命令行參數(shù)或者系統(tǒng)屬性。

          要將這個(gè)應(yīng)用程序發(fā)布給一個(gè)web服務(wù)器,你需要執(zhí)行以下的步驟:

          1. 修改jnlp的codebase和hrefURL為你自己的web服務(wù)器的合適的URL。
             
          2. 將JNLP文件發(fā)布到web服務(wù)器。

          3. 編譯并打包HelloJNLP.java并發(fā)布到web服務(wù)器。例如:
            
             jar cvf HelloJNLP.jar HelloJNLP.class HelloJNLP$1.class
            
          4. 創(chuàng)建一個(gè)圖標(biāo)HelloJNLP.jpg并將之安裝在web服務(wù)器上。你可以使用
             http://staff.develop.com/halloway/TechTips/May2001/HelloJNLP.jpg
            
          5. 設(shè)置你的web服務(wù)器的mime-type關(guān)聯(lián):.jnlp映射到mime-type application/x-java-jnlp-file。例如,對(duì)于Apache,添加如下一行到mime.types:
            
             application/x-java-jnlp-file jnlp
            
             重新啟動(dòng)web服務(wù)器。

          從客戶端執(zhí)行那個(gè)應(yīng)用程序,首先確認(rèn)你已經(jīng)安裝了JWS。然后簡(jiǎn)單的在瀏覽器中指向該jnlp文件。JWS客戶端將下載該jnlp文件,下載必要的資源,加載應(yīng)用程序。你所看到的將是在一個(gè)編輯區(qū)中顯示的文本"Edit this text" 。如果你在配置web服務(wù)器上有問題或者不能使用web服務(wù)器,你可以從
          http://staff.develop.com/halloway/TechTips/May2001/Hello.jnlp
          加載這個(gè)程序。

          注意HelloJNLP不是作為一個(gè)applet運(yùn)行在瀏覽器中,而是作為一個(gè)獨(dú)立的應(yīng)用程序。

          當(dāng)你關(guān)閉程序時(shí),HelloJNLP使用System.out打印消息"Shutting down...",然而沒有控制臺(tái)可見??刂婆_(tái)是JWS的諸多設(shè)置中缺省設(shè)置為"off"的其中一個(gè)。這是你可以修改的一對(duì)設(shè)置中的一個(gè)值,就像下面這樣:

          1. 編輯JWS安裝目錄中的javaws.cfg文件。添加一行"javaws.cfg.forceUpdate=true"。
          這會(huì)導(dǎo)致JWS在啟動(dòng)應(yīng)用程序前自動(dòng)檢查更新的版本。
            
          2. 運(yùn)行JWS。使用菜單File->Preferences,進(jìn)入Advanced標(biāo)簽并且選擇"Show Java Console"。(由于JDK1.4中的本機(jī)化,JWS將顯示中文的界面,所以此處的因?yàn)楸蛔詣?dòng)顯示為對(duì)應(yīng)的中文)同意,選擇"Log Output"將日志輸出到你選擇的文件。當(dāng)你在調(diào)試時(shí)并且需要捕獲System.out和System.err時(shí)是非常有用的。

          HelloJNLP顯示一個(gè)編輯器,但是編輯器的內(nèi)容在你關(guān)閉程序后將丟失。將下面的代碼添加到HelloJNLP.java會(huì)自動(dòng)的將編輯器的狀態(tài)存儲(chǔ)到客戶端的硬盤上:

          //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 FilesJava Web Start目錄下)
          JNLP API定義了一套的服務(wù)用以繞過安全沙盒使得一些通常的客戶端操作可以使用。
          在writeEditorContents方法中,BasicService查找應(yīng)用程序的代碼目錄,然后
          PersistenceService將編輯區(qū)的內(nèi)容緩存在本機(jī)硬盤上,這些內(nèi)容被鍵入到一個(gè)和應(yīng)用程序目錄相對(duì)的URL下。 PersistenceService提供的名字/值對(duì)數(shù)據(jù)和瀏覽器的cookies很相似。JWS通過一對(duì)被稱為"muffins"的東西實(shí)現(xiàn)了這個(gè), muffins不時(shí)候用來存儲(chǔ)大數(shù)據(jù),他們應(yīng)該用于在客戶端緩存小的標(biāo)識(shí)符。然后這些標(biāo)識(shí)符能被用于在服務(wù)器上定位大的信息。

          在web服務(wù)器上重新發(fā)布修改過的應(yīng)用程序,然后試著從客戶端運(yùn)行它--依然通過URL。如果你沒有web服務(wù)器,你可以從
          http://staff.develop.com/halloway/TechTips/May2001/Hello2.jnlp 運(yùn)行這個(gè)新版本。JWS自動(dòng)探測(cè)程序被改變并運(yùn)行新的版本。你可以通過檢查標(biāo)題條的字符串來證實(shí)這點(diǎn),它現(xiàn)在將顯示"Hello JNLP,Second Version." 修改編輯區(qū)的內(nèi)容,然后關(guān)閉它。當(dāng)你再次加載該程序時(shí),你的改變會(huì)出現(xiàn)。(當(dāng)你第一次運(yùn)行新版的程序時(shí)你會(huì)在控制臺(tái)看到一個(gè)異常,這是因?yàn)閞eadEditorContents 第一次不能找到muffin。)
          (譯者注:實(shí)際上第一次運(yùn)行時(shí)出現(xiàn)的異常導(dǎo)致程序無法正常結(jié)束,從而使得編輯區(qū)的內(nèi)容無法寫入客戶端,下次運(yùn)行時(shí)也相當(dāng)于第一次運(yùn)行。即此程序無法展示文章的特性,可能是于筆者的JWS的版本有關(guān),筆者使用的是最新的1.0.1_02(build b03))
          JNLP提供了比這里演示的更多的服務(wù)。例如,你可以:

          o 很好的控制程序如何被下載
          o 描述各個(gè)JAR之間的依賴關(guān)系
          o 下載并運(yùn)行本機(jī)代碼安裝程序
          o 對(duì)簽名的代碼授予附件的權(quán)限
          o 請(qǐng)求指定版本的程序或者applet

          要了解更多有關(guān)JNLP的情況,請(qǐng)到
          http://java.sun.com/products/javawebstart/download-spec.html
          下載JNLP規(guī)范。

          要了解更多JWS的情況,請(qǐng)參考http://java.sun.com/products/javawebstart/
          posted on 2007-07-10 10:32 冰封的愛 閱讀(303) 評(píng)論(0)  編輯  收藏 所屬分類: J2EE
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(3)

          隨筆檔案

          文章分類

          文章檔案

          相冊(cè)

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 两当县| 博客| 镶黄旗| 许昌市| 理塘县| 隆昌县| 松阳县| 梁平县| 九龙城区| 珲春市| 门源| 全椒县| 青州市| 青神县| 永仁县| 马尔康县| 札达县| 玉屏| 通渭县| 波密县| 遂宁市| 黄冈市| 黑山县| 保亭| 达州市| 舒城县| 靖州| 德保县| 四子王旗| 拜泉县| 类乌齐县| 永康市| 沙雅县| 古丈县| 临城县| 微山县| 贵州省| 丹凤县| 平乡县| 汾西县| 石台县|