文章詳情頁(yè)
從Firefox訪(fǎng)問(wèn)Java Plug-in
瀏覽:23日期:2024-06-16 15:32:59
內(nèi)容: 摘要這篇文章與Jeff Friesen前一篇關(guān)于Java Plug-in的文章'Plug into Java with Java Plug-in' (JavaWorld, 6月 1999)是一個(gè)系列的。它專(zhuān)注于Firefox Web瀏覽器的最近的Java Plug-in其中之一。在篇文章中,你能學(xué)會(huì)從Firefox怎樣訪(fǎng)問(wèn)Java Plug-in。你也能學(xué)到一些關(guān)于Java Plug-in文件對(duì)象模塊(DOM),applet狀態(tài)持久化,和cookie。除此以外,你還可以學(xué)習(xí)applet,它在Firefox中的運(yùn)行,這將加強(qiáng)你對(duì)這些內(nèi)容的理解。但那僅僅是開(kāi)始。難道你曾經(jīng)不想去探求Firefox是怎樣與Java Plug-in(在后臺(tái))交互的嗎?繼續(xù)讀下去你就會(huì)找到答案的。版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必保留以下作者信息和鏈接作者:Jeff Friesen;leo173(作者的blog:http://blog.matrix.org.cn/page/leo173)原文:http://www.javaworld.com/javaworld/jw-06-2005/jw-0627-plugin.html譯文:http://www.matrix.org.cn/resource/article/44/44251_Firefox+Java+Plug-in.html關(guān)鍵字:Firefox;Java;Plug-in 從我在JavaWorld 上寫(xiě)'Plug into Java with Java Plug-in' 開(kāi)始,9年已經(jīng)過(guò)去了。我的前一篇文章給Java Plug-in下了定義,講到了怎樣在Netscape Communicator 4.5 和 Internet Explorer 3.02 上怎樣安裝版本1.2,描述了與Java Plug-in相關(guān)的Windows注冊(cè)表設(shè)置,了解了Java Plug-in的控制面版,考查了兩個(gè)java主控臺(tái),討論了HTML 的 和 標(biāo)簽,還發(fā)布了一個(gè)基于Swing的用于Demo的applet。自從我寫(xiě)了那篇文章后,java和Java Plug-in已經(jīng)相繼發(fā)布了許多個(gè)版本??磥?lái)那篇文章已顯老態(tài),所以我已經(jīng)寫(xiě)好它的系列篇,它專(zhuān)注于針對(duì)Firefox Web瀏覽器的最近的Java Plug-in其中之一。這篇文章首先為你講解從Firefox怎樣訪(fǎng)問(wèn)Java Plug-in。然后討論Java Plug-in文件對(duì)象模塊(DOM), applet狀態(tài)持久化 和cookie。比如在Firefox上運(yùn)行的各種applet,當(dāng)你在學(xué)習(xí)這些內(nèi)容時(shí),將會(huì)強(qiáng)化你已經(jīng)掌握的知識(shí)。這篇文章通過(guò)探尋Firefox 和Java Plug-in之間的聯(lián)系,再做歸納。因?yàn)閷?duì)于Java Plug-in而言,在其他地方會(huì)比我在這里所講的要詳細(xì)得多,所以我建議可以學(xué)習(xí)Sun的Java Plug-in文檔,你將會(huì)學(xué)到更多的技術(shù)。這篇文章的實(shí)驗(yàn)環(huán)境是Mozilla Firefox 1.0, J2SE 5.0, 和Windows 98 SE。即使你沒(méi)有這些軟件,我仍然建議你讀完這篇文章。真誠(chéng)地希望你能發(fā)現(xiàn)一些對(duì)你來(lái)說(shuō)還是未知的有興趣的東西。Java Plug-in 和FirefoxJava Plug-in象橋一樣服務(wù)于瀏覽器和一個(gè)外部的 java運(yùn)行環(huán)境(JRE)之間。Java Plug-in對(duì)于在Firefox 中運(yùn)行的applet而言是相當(dāng)重要的,因?yàn)闉g覽器不能自身為其提供一個(gè)JRE——其中包括一個(gè)JVM。因?yàn)檫@篇文章描述的applet會(huì)涉及到不同多個(gè)不同的Java Plug-in內(nèi)容,還有就是這些applet都是在Firefox的環(huán)境中運(yùn)行的,所以我們首先應(yīng)該看一下如何從Firefox中訪(fǎng)問(wèn)Java Plug-in。對(duì)于初學(xué)者來(lái)說(shuō),你必須確認(rèn)在你的平臺(tái)上已經(jīng)安裝了J2SE 5.0 和 JRE。在我的windows平臺(tái)上,我用jdk-1_5_0-windows-i586.exe安裝文件把J2SE 和 JRE都安裝好了。確定你已經(jīng)安裝了JRE,因?yàn)镴RE包含了Java Plug-in。在安裝好J2SE 5.0后,連接Firefox 到 Java Plug-in;首先從Firefox的工具菜單中選擇Options,然后選擇Web Features,最后點(diǎn)擊Enable Java checkbox。一般情況下,標(biāo)簽 和 應(yīng)該指向在Java Plug-in下運(yùn)行的applet。這對(duì)Java Plug-in 5.0來(lái)說(shuō)不是必要的,它能運(yùn)行由簡(jiǎn)單的標(biāo)簽指定的applet。在安裝時(shí),你有機(jī)會(huì)屏蔽Internet Explorer 和 Mozilla (Firefox)/Netscape Web瀏覽器對(duì)applet的執(zhí)行,如果它們遇到了標(biāo)簽,而轉(zhuǎn)交給Java Plug-in處理。如果你放棄這個(gè)選項(xiàng),遲些時(shí)候你可以通過(guò)Java Plug-in的控制面版來(lái)完成這個(gè)變化。比如,打開(kāi)控制面版,選擇標(biāo)簽Advanced。然后點(diǎn)擊 Tag Support左邊的“+,再選擇Mozilla and Netscape選項(xiàng)。關(guān)閉這個(gè)面版后,當(dāng)Firefox遇到標(biāo)簽時(shí),它就會(huì)交給Java Plug-in執(zhí)行。圖1給出了這些必要的改變。 選擇Mozilla and Netscape,所以當(dāng)Firefox遇到標(biāo)簽時(shí),它就會(huì)交給Java Plug-in執(zhí)行提示 我發(fā)現(xiàn)在我的平臺(tái)上選擇Mozilla and Netscape不是必須的。我的Firefox Web瀏覽器不會(huì)去管那個(gè)復(fù)選框的設(shè)置,當(dāng)遇見(jiàn)時(shí),它就會(huì)讓Java Plug-in來(lái)執(zhí)行。Java Plug-in 5.0的文檔談到這是個(gè)奇怪的行為:“如果Mozilla 和 Netscape 7都被安裝好了,負(fù)責(zé)管理對(duì)標(biāo)簽是否支持的Mozilla and Netscape選項(xiàng)沒(méi)有被選中的情況下,標(biāo)簽中的內(nèi)容照樣可以在Sun VM上運(yùn)行。這是與Netscape 7的自動(dòng)掃描功能相關(guān)的一個(gè)bug。因?yàn)槲乙呀?jīng)安裝過(guò)Netscape 6.2.3,所以我認(rèn)為我找到了這個(gè)bug。如果在你的平臺(tái)上遇到了這個(gè)問(wèn)題,記住這點(diǎn)就行了。平臺(tái)上能駐留多個(gè)JRE,當(dāng)Firefox遇到標(biāo)簽時(shí),到底哪一個(gè)JRE來(lái)實(shí)現(xiàn)Java Plug-in?可以從Java Plug-in控制面版上的Java標(biāo)簽上找到答案。在二選一的情況下,我用來(lái)進(jìn)行版本測(cè)試的applet給出了答案,同時(shí)也證明了Firefox是連接了 Java Plug-in的。圖2顯示我當(dāng)前使用的JRE版本是1.5.0。(版本1.5.0是J2SE 5.0的內(nèi)部版本號(hào))圖2. 我已經(jīng)配置好使用JRE 1.5.0的Java Plug-inListing 1給出了該applet的VersionDemo.java文件的源代碼。這些代碼在系統(tǒng)屬性java.version 中設(shè)置了JRE 的版本。Listing 1. VersionDetect.java // VersionDetect.javaimport java.awt.*;public class VersionDetect extends java.applet.Applet{ public void paint (Graphics g) { int width = getSize ().width; int height = getSize ().height; g.setColor (Color.orange); g.fillRect (0, 0, width, height); String version = 'JRE ' + System.getProperty ('java.version'); FontMetrics fm = g.getFontMetrics (); g.setColor (Color.black); g.drawString (version, (width-fm.stringWidth (version))/2, height/2); }} 為了簡(jiǎn)潔,在這篇文章中我將不會(huì)給出運(yùn)行這個(gè)或者其他applet的HTML。參見(jiàn)這篇文章中的source code 。提示 Firefox只支持Java Plug-in 1.3.0_01和更高版本。調(diào)用DOM根據(jù)WWW 聯(lián)合會(huì) (W3C)所說(shuō),文件對(duì)象模塊(DOM)是一個(gè)API,它針對(duì)“有效的HTML和合式的XML文檔。它定義了文檔的邏輯結(jié)構(gòu),訪(fǎng)問(wèn)和操作文檔的方法。 Java Plug-in提供了兩種方法來(lái)調(diào)用DOM:類(lèi)netscape.javascript.JSObject和Common DOM API。JSObject為Java applet 和Web 瀏覽器的JavaScript實(shí)現(xiàn)之間提供了接口,包含使用了DOM 的JavaScript 對(duì)象。這些對(duì)象的例子:Document, Link, 和 Window。我將不會(huì)深入JSObject,因?yàn)樵谖以缙诘奈恼?Talk with Me Java'中,我已經(jīng)討論了這個(gè)類(lèi)。因此我專(zhuān)注于在一個(gè)applet中,通過(guò)Common DOM API來(lái)遍歷DOM 。在J2SE 版本1.4中已經(jīng)介紹過(guò)Common DOM API,它是一個(gè)類(lèi)和接口的集合,通過(guò)這些接口可以讓applet遍歷DOM實(shí)例。因?yàn)橐粋€(gè)瀏覽器通過(guò)幀和窗口能夠顯示多個(gè)文檔,所以會(huì)有許多DOM實(shí)例以備遍歷。一般一個(gè)applet就遍歷它自己的DOM實(shí)例—這個(gè)與文檔相聯(lián)系的DOM實(shí)例指定了這個(gè)applet。訪(fǎng)問(wèn)DOM實(shí)例的起點(diǎn)就是靜態(tài)方法getService(Object obj),該方法位于類(lèi)com.sun.java.browser.dom.DOMService中。一般情況下,一個(gè)被喚醒a(bǔ)pplet的this指針會(huì)被作為一個(gè)參數(shù)傳遞給getService()。這個(gè)方法要么返回一個(gè) DOMService對(duì)象(為這個(gè)applet和它的DOM實(shí)例之間提供接口),要么拋一個(gè)異常:com.sun.java.browser.dom.DOMUnsupportedException (the DOM service is not available to the object) 或者 com.sun.java.browser.dom.DOMAccessException (a security violation has resulted)。例子:DOMService service = DOMService.getService (this);。因?yàn)閣eb瀏覽器提供了不同的DOM實(shí)現(xiàn),所以訪(fǎng)問(wèn)一個(gè)DOM實(shí)例不是線(xiàn)程安全的,除非那個(gè)訪(fǎng)問(wèn)是發(fā)生在DOM access dispatch線(xiàn)程。為了確保線(xiàn)程安全性,DOMService提供了兩個(gè)方法來(lái)保證訪(fǎng)問(wèn)只是發(fā)生在DOM access dispatch線(xiàn)程—invokeLater() 和 invokeAndWait()。兩種方法都用實(shí)現(xiàn)了接口com.sun.java.browser.dom.DOMAction的對(duì)象作為參數(shù),來(lái)提供方法run()。invokeLater()在DOM dispatch線(xiàn)程中異步執(zhí)行run(),invokeAndWait()在DOM dispatch線(xiàn)程中同步執(zhí)行run()。方法run()用實(shí)現(xiàn)了接口com.sun.java.browser.dom.DOMAccessor的對(duì)象作為其唯一參數(shù),然后返回一個(gè)基本的Object引用。方法run()經(jīng)常喚醒DOMAccessor的getDocument()方法,傳遞一個(gè)applet的指針做getDocument()的Object參數(shù)。作為回應(yīng),getDocument()會(huì)返回一個(gè)實(shí)現(xiàn)org.w3c.dom.Document接口的對(duì)象。那個(gè)對(duì)象中就包含了這個(gè)文檔的信息。對(duì)于HTML文檔而言,它會(huì)把Document向下轉(zhuǎn)型為HTMLDocument(位于org.w3c.dom.html中),然后調(diào)用HTMLDocument的方法去獲取這個(gè)文檔的標(biāo)題,域,applet集,和一些其他的。在調(diào)用屬性方法后,run()返回一個(gè)包含文檔信息(比如HTMLDocument的標(biāo)題)的Object對(duì)象。那個(gè)Object隨后又從invokeAndWait()和invokeLater()方法中返回。為了梳理上面討論的內(nèi)容,我寫(xiě)了一個(gè)從一個(gè)HTML文檔中提取標(biāo)題的applet,然后把標(biāo)題顯示給用戶(hù)。下面就是它的代碼。Listing 2. TitleExtract.java // TitleExtract.javaimport com.sun.java.browser.dom.*;import java.applet.Applet;import java.awt.*;import org.w3c.dom.html.*;public class TitleExtract extends Applet{ private String title = 'unknown'; public void init () { try { DOMService service = DOMService.getService (this); title = (String) service.invokeAndWait (new DOMAction () {public Object run (DOMAccessor accessor){ HTMLDocument doc = (HTMLDocument) accessor.getDocument (TitleExtract.this); return doc.getTitle ();} }); } catch (DOMUnsupportedException e) { System.out.println ('DOM not supported'); } catch (DOMAccessException e) { System.out.println ('DOM cannot be accessed'); } } public void paint (Graphics g) { int width = getSize ().width; int height = getSize ().height; g.setColor (Color.cyan); g.fillRect (0, 0, width, height); FontMetrics fm = g.getFontMetrics (); g.setColor (Color.black); g.drawString (title, (width-fm.stringWidth (title))/2, height/2); }} DOMAction的run()方法調(diào)用了HTMLDocument的getTitle()方法去獲取HTML文檔的標(biāo)題。隨后顯示該標(biāo)題。例如,當(dāng)在TitleExtract.html(參見(jiàn)本文的source code)中遇到元素時(shí),getTitle()返回“Extract the title。圖3中顯示了Firefox中的結(jié)果。圖3。 顯示一個(gè)文檔的標(biāo)題注意 當(dāng)從標(biāo)簽 中調(diào)用TitleExtract時(shí),F(xiàn)irefox要求mayscript屬性需要被給出。否則,由于Firefox的DOM實(shí)現(xiàn)依賴(lài)于JSObject,Java Plug-in會(huì)拋出各種異常。Applet在Firefox session中的持久狀態(tài)Java Plug-in 5.0的文檔提到許多有趣的課題。其中之一就是applet的持久性API,它可以讓一個(gè)applet保存其狀態(tài)以備在后來(lái)的相同的web瀏覽器session中使用。State被保存在由Java Plug-in控制的一個(gè)內(nèi)部持久性存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)中;一個(gè)session是指某個(gè)web瀏覽器被打開(kāi)運(yùn)行開(kāi)始到這個(gè)瀏覽器被關(guān)閉結(jié)束。在J2SE 1.4中介紹的applet持久性API ,由聲明在接口java.applet.AppletContext中的三個(gè)方法構(gòu)成:· void setStream(String key, InputStream stream) throws IOException 需要當(dāng)前applet上下文的一個(gè)具體key和具體的stream作為參數(shù)。如果一個(gè)新的stream對(duì)應(yīng)了當(dāng)前的key,這個(gè)新stream將會(huì)取代那個(gè)舊的stream。如果新stream的size超出了內(nèi)部size的限制,將會(huì)拋出一個(gè)異常IOException。· InputStream getStream(String key)返回與當(dāng)前applet key相聯(lián)系的InputStream。如果沒(méi)有指向該key的stream就返回null。· Iterator getStreamKeys()返回一個(gè)迭代器,它包括了指向當(dāng)前applet中stream的所有key。通過(guò)調(diào)用setStream()來(lái)保存狀態(tài)。這個(gè)方法把一個(gè)key(它可以方便地標(biāo)識(shí)一個(gè)輸入流)和一個(gè)InputStream的引用存儲(chǔ)到一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)中去,比如一個(gè)HashMap。取出某狀態(tài)可以通過(guò)相應(yīng)的標(biāo)識(shí)key調(diào)用getStream()。它會(huì)返回一個(gè)InputStream(如果這個(gè)key存在)以恢復(fù)到這個(gè)狀態(tài)。因?yàn)镴ava Plug-in5.0文檔沒(méi)有提供例子來(lái)指出怎樣使用applet持久性API,所以我準(zhǔn)備了一個(gè)例子。它給出了一個(gè)消息傳送applet的兩個(gè)實(shí)例,其中的一個(gè)使用applet持久性API發(fā)送消息給另一個(gè)。圖4中,用戶(hù)在左邊實(shí)例的 Message To Send文本框中輸入一個(gè)消息,然后點(diǎn)擊該實(shí)例的Send按扭。然后用戶(hù)點(diǎn)擊右邊實(shí)例的Receive按扭,這個(gè)消息就會(huì)在該實(shí)例的Message Received文本框中顯示。圖4 .applet的持久性API使applet之間相互發(fā)送消息給對(duì)方。點(diǎn)擊“最大化消息發(fā)送發(fā)生在下面代碼的action listener中。Listing 3. MessageTransfer.java // MessageTransfer.javaimport java.applet.*;import java.awt.*;import java.awt.event.*;import java.io.*;import javax.swing.*;public class MessageTransfer extends JApplet implements ActionListener{ private TextField txtRecvMsg, txtSendMsg; public void init () { // Build the applet's GUI. setLayout (new GridLayout (3, 1)); JPanel pnl = new JPanel (); pnl.setLayout (new FlowLayout (FlowLayout.LEFT)); pnl.add (new JLabel ('Message to send:')); txtSendMsg = new TextField (20); pnl.add (txtSendMsg); getContentPane ().add (pnl); pnl = new JPanel (); pnl.setLayout (new FlowLayout (FlowLayout.LEFT)); pnl.add (new JLabel ('Message received:')); txtRecvMsg = new TextField (20); pnl.add (txtRecvMsg); getContentPane ().add (pnl); pnl = new JPanel (); pnl.setLayout (new FlowLayout (FlowLayout.LEFT)); JButton btnSend = new JButton ('Send'); btnSend.addActionListener (this); pnl.add (btnSend); JButton btnReceive = new JButton ('Receive'); btnReceive.addActionListener (this); pnl.add (btnReceive); getContentPane ().add (pnl); } public void actionPerformed (ActionEvent e) { JButton btn = (JButton) e.getSource (); if (btn.getText ().equals ('Send')) { String text = txtSendMsg.getText (); try { // Output the String object to a byte array output stream. ByteArrayOutputStream baos = new ByteArrayOutputStream (); ObjectOutputStream oos = new ObjectOutputStream (baos); oos.writeObject (text); oos.close (); // Extract the String object from the byte array output stream // as an array of bytes. byte [] data = baos.toByteArray (); // Convert the array of bytes to a byte array input stream. When // the setStream() method is invoked, it caches the input stream // reference and key in the applet persistent store. InputStream is = new ByteArrayInputStream (data); getAppletContext ().setStream ('text', is); } catch (Exception e2) { System.out.println (e2.toString ()); } } else { InputStream is = getAppletContext ().getStream ('text'); if (is != null) try { // Input the cached String object. ObjectInputStream ois = new ObjectInputStream (is); String text = (String) ois.readObject (); txtRecvMsg.setText (text); } catch (Exception e2) { System.out.println (e2.toString ()); } } }} 這個(gè)消息發(fā)送applet把消息持久化為一個(gè)string對(duì)象,通過(guò)把這個(gè)對(duì)象序列化到ByteArrayOutputStream,轉(zhuǎn)化這個(gè)stream到一個(gè)byte數(shù)組,基于這個(gè)byte數(shù)組構(gòu)建一個(gè)ByteArrayInputStream,然后通過(guò)這個(gè)stream和一個(gè)名為text的key調(diào)用方法setStream()。該applet用這個(gè)名為text的key調(diào)用getStream()取回這個(gè)消息,然后反序列化這個(gè)InputStream。在Firefox中,被持久化后的消息對(duì)在不同窗口或面版上運(yùn)行的applet都是可以被訪(fǎng)問(wèn)的。這種消息對(duì)不同session(也就是說(shuō),F(xiàn)irefox的不同實(shí)例)中運(yùn)行的applet是不能被訪(fǎng)問(wèn)的,因?yàn)槊總€(gè)session只與它自己的Java Plug-in實(shí)例和內(nèi)部持久性存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)進(jìn)行通信。提示 出于安全考慮,使用不同codebase的applet不能訪(fǎng)問(wèn)對(duì)方的stream。了解cookieWeb瀏覽器和web服務(wù)器經(jīng)常發(fā)送小的數(shù)據(jù)包給對(duì)方進(jìn)行交互。這些包,也就是大家知道的cookie,可以被用來(lái)跟蹤用戶(hù)的喜好,幫用戶(hù)自動(dòng)登錄站點(diǎn)等。Java Plug-in結(jié)合web 瀏覽器可以讓applet訪(fǎng)問(wèn)cookie。例如,Java Plug-in讓簽名applet去查看從web服務(wù)器發(fā)送到web瀏覽器的cookie。Java Plug-in5.0文檔中談及對(duì)cookie的支持時(shí),給出了幾個(gè)與cookie交互的代碼片段。因?yàn)槟憧赡芟朐赼pplet中測(cè)試這些代碼片段,還有就是可能你不確定該怎樣把它們轉(zhuǎn)變成簽名applet,所以下面我給出了一個(gè)用來(lái)查看cookie的簽名applet。在討論完這些重要的代碼后,我將帶你學(xué)習(xí)怎樣建立和簽名applet。最后,我們會(huì)在Firefox web瀏覽器中運(yùn)行這個(gè)applet。下面就是代碼。Listing 4. CookieDetect.java// CookieDetect.javaimport java.awt.BorderLayout;import java.awt.event.*;import java.net.*;import java.util.*;import javax.swing.*;public class CookieDetect extends JApplet implements ActionListener{ private JTextArea txtaStatus; private JTextField txtURL; public void init () { // Build the applet's GUI JPanel pnl = new JPanel (); pnl.add (new JLabel ('Enter URL:')); txtURL = new JTextField (20); txtURL.addActionListener (this); pnl.add (txtURL); getContentPane ().add (pnl, BorderLayout.NORTH); txtaStatus = new JTextArea (10, 40); getContentPane ().add (new JScrollPane (txtaStatus)); } public void actionPerformed (ActionEvent e) { try { URL url = new URL (txtURL.getText ()); URLConnection conn = url.openConnection (); conn.connect (); Map headers = conn.getHeaderFields (); List values = headers.get ('Set-Cookie'); if (values == null) { txtaStatus.setText ('No cookies detectedn'); return; } txtaStatus.setText (''); for (Iterator iter = values.iterator (); iter.hasNext();) txtaStatus.setText (txtaStatus.getText () + iter.next () + 'n'); txtaStatus.setText (txtaStatus.getText () + 'n'); } catch (Exception e2) { System.out.println (e2); } }} CookieDetect.java生成的GUI主要由兩個(gè)條目構(gòu)成:一個(gè)接受URL的文本框,和一個(gè)顯示cookie的文本域。無(wú)論何時(shí)用戶(hù)按下Enter鍵和這個(gè)文本框獲得了輸入的光標(biāo),文本框的action listener的方法actionPerformed()都會(huì)被調(diào)用。方法actionPerformed()首先用文本框中的URL建立一個(gè)URL對(duì)象。然后調(diào)用這個(gè)對(duì)象的openConnection()方法返回一個(gè)表示該applet和該URL相互連接的URLConnection對(duì)象。繼續(xù)往下面看,URLConnection()的方法connect()建立這個(gè)連接,它的getHeaderFields()方法可以得到不會(huì)改變的一組HTTP頭和相對(duì)應(yīng)的值,Map的方法get()返回與頭Set-Cookie相對(duì)應(yīng)的值組成的List。一個(gè)循環(huán)列舉出了該List中的值;每個(gè)值表示一個(gè)cookie,被陸續(xù)加入文本區(qū)域中。假使CookieDetect.java存放在當(dāng)前目錄c:appletsCookieDetect中,完成下面的操作,建立和簽名這個(gè)查看cookie的applet:· 編譯 CookieDetect.java: javac CookieDetect.java. · 把上步得到的CookieDetect.class替換成一個(gè)jar文件,jar cvf CookieDetect.jar CookieDetect.class。· 在一個(gè)新keytore中創(chuàng)建一個(gè)新key:keytool -genkey -keystore ks -alias me。當(dāng)彈出來(lái)后,輸入testtest作為keystore的密碼,你的姓和名,你所在行業(yè)(比如IT),你公司的名字,你所在城市名,所在州或省的名字,你的行業(yè)代碼 ,不管你剛才輸入的信息是否真實(shí),當(dāng)彈出窗口時(shí)選擇Yes。當(dāng)彈出窗口讓你輸入me的密碼 時(shí),單擊Enter。這樣可以讓密碼與keystore 中的密碼(testtest)相同。所有這些信息都被放在文件ks中,這個(gè)文件需要我們自己簽名的測(cè)試認(rèn)證。· 創(chuàng)建一個(gè)簽名的測(cè)試認(rèn)證:keytool -selfcert -alias me -keystore ks。當(dāng)被彈出后,輸入testtest作為keystore的密碼。這個(gè)認(rèn)證就被放進(jìn)ks中了。Alias me (在前一步,這步,和下一步中)提醒你這個(gè)認(rèn)證已被簽名,僅僅用來(lái)被測(cè)試。換句話(huà)說(shuō),不要在公共站點(diǎn)上用這個(gè)測(cè)試認(rèn)證來(lái)發(fā)布簽名applet。· 用這個(gè)測(cè)試認(rèn)證來(lái)簽名這個(gè)jar文件:jarsigner -keystore ks CookieDetect.jar me。當(dāng)彈出后,輸入testtest作為keystore的密碼。這個(gè)工具更新該jar文件的META-INF目錄以包含認(rèn)證信息和CookieDetect.class的一個(gè)數(shù)字簽名。讓我們運(yùn)行這個(gè)applet。從本文附的代碼中找到CookieDetect.html,然后放進(jìn)目錄c:appletsCookieDetect下。該HTML文件的中包含一個(gè)archive屬性來(lái)標(biāo)識(shí)CookieDetect.jar文件。打開(kāi)Firefox,然后輸入該HTML文件的URL:c:appletsCookieDetectCookieDetect.html。一段時(shí)間后,圖5的安全對(duì)話(huà)框就會(huì)出現(xiàn)在你眼前。 Figure 5. 安全對(duì)話(huà)框讓你有權(quán)信任這個(gè)簽名的applet。單擊yes鍵響應(yīng)該安全對(duì)話(huà)框。然后這個(gè)applet被顯示。輸入U(xiǎn)RL:http://javaworld.com,然后按下回車(chē)。如圖6所示,網(wǎng)站JavaWorld 不會(huì)發(fā)送cookie。 Figure 6. 你不會(huì)從 JavaWorld 取得cookie與JavaWorld 相比,網(wǎng)站JavaLobby會(huì)發(fā)送一個(gè)cookie。輸入http://javalobby.org,圖7中就會(huì)顯示有這樣一個(gè)cookie,id 是SESSIONID。 Figure 7. JavaLobby 發(fā)送了一個(gè)簡(jiǎn)單的cookie一些網(wǎng)站會(huì)發(fā)送出大量的cookie,比如像kasssamba。如圖8所顯示的,該站點(diǎn)發(fā)送了4個(gè)cookie到web瀏覽器。 Figure 8. Kasamba 發(fā)送了不少的cookie到web瀏覽器我極力建議你繼續(xù)去體會(huì)cookie的使用,把余下的三段代碼(來(lái)源于Java Plug-in 5.0文檔中對(duì)cookie支持的標(biāo)題)也轉(zhuǎn)換成簽名applet。小竅門(mén) 訪(fǎng)問(wèn) http://www.cookiecentral.com/faq/ 可以學(xué)到更多關(guān)于cookie的內(nèi)容。 理解 hood 許多人在讓Firefox識(shí)別Java Plug-in時(shí)會(huì)遇到困難。說(shuō)來(lái)說(shuō)去,就是指applet不能運(yùn)行。通過(guò)理解Firefox與Java Plug-in怎樣進(jìn)行交互,你能避開(kāi)許多類(lèi)似的麻煩。在后續(xù)部分,我會(huì)為你講解Firefox如何探測(cè)Java Plug-in,JRE的 NP*.dll 插件文件,和一些被稱(chēng)為OJI的東西。探測(cè)Java Plug-in在前面你已經(jīng)安裝了一個(gè)簡(jiǎn)單的JRE(它包含了Java Plug-in),現(xiàn)在要安裝Firefox。你可以運(yùn)行那個(gè)瀏覽器,上網(wǎng)沖浪,打開(kāi)那些使用了applet的網(wǎng)頁(yè),那些applet就會(huì)運(yùn)行起來(lái)了。。不久后,你會(huì)思考Firefox是怎樣找到Java Plug-in,讓applet運(yùn)行起來(lái)的。畢竟說(shuō)來(lái),F(xiàn)irefox只檢索它自己的插件列表來(lái)查找插件,而JRE把它自己的Java Plug-in放在它自身的bin目錄下。在這樣的安排下,F(xiàn)irefox怎么可能檢測(cè)到Java Plug-in呢?當(dāng)Firefox開(kāi)始運(yùn)行時(shí),它的目錄服務(wù)提供器就接到一個(gè)任務(wù),在windows平臺(tái)上的安裝目錄中去找adobe Acrobat, Apple Quicktime, Microsoft Windows Media Player, 和 Sun Java plug-in。Java Plug-in的安裝目錄一經(jīng)找到,目錄服務(wù)提供器將會(huì)傳遞以下信息給plugin.scan.SunJRE:用戶(hù)的個(gè)人設(shè)置名稱(chēng)和該設(shè)置的值(要求的最低JRE版本)。更進(jìn)一步,security.enable_java 這個(gè)用戶(hù)設(shè)置必須存在,而且它的布爾值必須為true。假如plugin.scan.SunJRE 和 security.enable_java存在,還假設(shè)security.enable_java的值是true,目錄服務(wù)提供器會(huì)在windows的注冊(cè)表中列出所有版本號(hào)作為HKEY_LOCAL_MACHINESoftwareJavaSoftJava Plug-in的子鍵。最新版本號(hào)識(shí)別出Firefox所使用的JRE/Java Plug-in,這個(gè)版本號(hào)必須要比plugin.scan.SunJRE的值要大或相等.版本號(hào)子鍵自身的JavaHome子鍵包含了被識(shí)別出的JRE根目錄路徑。目錄服務(wù)提供器把bin附加在這個(gè)目錄后,這時(shí)Firefox就知道了Java Plug-in的安裝路徑了。有點(diǎn)糊涂了?我會(huì)用一個(gè)例子來(lái)?yè)荛_(kāi)這一層霧。我的Firefox瀏覽器給出我的plugin.scan.SunJRE值為1.3。它同時(shí)也指定security.enable_java值為真。在啟動(dòng)時(shí),目錄服務(wù)提供器掃描我的windows注冊(cè)表;相關(guān)的設(shè)置如下:HKEY_LOCAL_MACHINE Software JavaSoft Java Plug-in 1.5.0 JavaHome 'C:Program FilesJavajre1.5.0'目錄服務(wù)提供器列舉出所有版本號(hào)的子鍵,在Java Plug-in子鍵下面,那個(gè)子鍵所示的最高版本號(hào)就大于或等于1.3了。我僅有一個(gè)子鍵大于或等于1.3:1.5.0。因此,目錄服務(wù)提供器含有子鍵值為1.5.0的JavaHome子鍵—C:Program FilesJavajre1.5.0—然后把bin附加在這個(gè)值的后面。這就意味著Firefox會(huì)在目錄c:Program FilesJavajre1.5.0bin下去找Java Plug-in。因?yàn)镕irefox1.0的plugin.scan.SunJRE用戶(hù)設(shè)置用1.3作為它的默認(rèn)值,所以Java Plug-in版本低于1.3的不會(huì)被識(shí)別。這就是為什么Firefox只支持Java Plug-in 1.3.0_01和更高的版本。NP*.dll文件仔細(xì)查看你的JRE的 bin目錄,你會(huì)發(fā)現(xiàn)不少文件名以NP開(kāi)頭,以.dll結(jié)尾的文件。例如,我的平臺(tái)下就列出了下面這些文件:NPJava11.dllNPJava12.dllNPJava13.dllNPJava14.dllNPJava32.dllNPJPI150.dllNPOJI610.dll 上面列出的文件是Netscape的插件文件。加上你可能在你的JRE的bin目錄下發(fā)現(xiàn)的其他NP*.dll文件,和也應(yīng)該被列出的若干個(gè)jpi*.dll文件,他們一起構(gòu)成了Java Plug-in。每個(gè)NP*.dll文件有相同的大小,因?yàn)樗麄兓旧隙际亲龅耐瑯拥氖虑椋核cjpi*.dll文件中的一個(gè)協(xié)同工作,下載虛擬機(jī),讓java環(huán)境運(yùn)行起來(lái)。每一個(gè)NP*.dll文件能識(shí)別一種或多種MIME(多用途網(wǎng)際郵件擴(kuò)展協(xié)議)類(lèi)型。當(dāng)遇到某種MIME類(lèi)型時(shí),這種類(lèi)型會(huì)告訴Firefox去裝載一個(gè)相應(yīng)的具體NP*.dll文件。例如,思考下面的標(biāo)簽: 注意type屬性的application/x-java-applet;version=1.1 MIME類(lèi)型。當(dāng)Firefox遇到這種MIME類(lèi)型,它就會(huì)選擇相應(yīng)的NP*.dll文件。因?yàn)镹PJava11.dll標(biāo)記了那種MIME類(lèi)型,NPJava11.dll會(huì)去裝載——而不是其他的NP*.dll裝載。NPJava11.dll與jpi*.dl文件一起讓java環(huán)境運(yùn)行。當(dāng)Firefox遇見(jiàn)標(biāo)簽時(shí),它到底表示的是哪種MIME類(lèi)型?我認(rèn)為當(dāng)Firefox 遇到 標(biāo)簽時(shí),application/x-java-vm就是MIME類(lèi)型:測(cè)試顯示出只有擁有那個(gè)MIME類(lèi)型的NPOJI610.dll會(huì)去裝載。什么是OJI?你可能已經(jīng)注意到在NPOJI610.dll中有OJI,想知道這三個(gè)字母代表什么。OJI表示Open JVM Integration ,這是個(gè)Mozilla project/API,它允許外部的JVM能夠插入一個(gè) Mozilla瀏覽器(就像Firefox這樣)。除了沒(méi)有被綁定在內(nèi)部虛擬機(jī)上,這個(gè)瀏覽器也沒(méi)有被綁定在sun指定的外部虛擬機(jī)上——瀏覽器能夠通過(guò)其他途徑與虛擬機(jī)進(jìn)行交互,只要這些虛擬機(jī)支持OJI。OJI有許多特性,包括允許用戶(hù)通過(guò)web瀏覽器來(lái)顯示java主控臺(tái)。OJI也會(huì)更改一個(gè)applet的生命周期:一旦一個(gè)applet網(wǎng)頁(yè)被打開(kāi),這個(gè)applet的init() 和 start()方法就會(huì)被調(diào)用。為了讓你能看到這個(gè)過(guò)程,先編譯Listing 5的 LifeCycle.java源代碼,在Firefox下運(yùn)行這個(gè)applet,打開(kāi)java主空臺(tái),然后不停在網(wǎng)頁(yè)之間進(jìn)行切換。在你每次進(jìn)入這個(gè)applet網(wǎng)頁(yè)的時(shí)候,你將注意到對(duì)這個(gè)applet構(gòu)造器的調(diào)用,它表明一個(gè)新的LifeCycle對(duì)象被生成了。Listing 5. LifeCycle.java // LifeCycle.javapublic class LifeCycle extends java.applet.Applet{ public LifeCycle () { System.out.println ('constructor called'); } public void init () { System.out.println ('init() called'); } public void start () { System.out.println ('start() called'); } public void stop () { System.out.println ('stop() called'); } public void destroy () { System.out.println ('destroy() called'); }} 總結(jié)即使講完上面所有的內(nèi)容,我也僅僅是做了淺層次的講解。其實(shí)還有很多東西我想寫(xiě)下來(lái)。可能只有在以后,我再寫(xiě)另一篇后續(xù)文章來(lái)完成了?;蛘吣阋部梢詫?xiě)那篇文章。不管怎樣,都讓我們繼續(xù)拓展我們對(duì)Sun的 Java Plug-in技術(shù)的理解吧。 關(guān)于作者Jeff Friesen 是軟件發(fā)展的自由撰稿人,同時(shí)也是C, C++, 和 Java技術(shù)的研究員。資源列表 · 下載這篇文章中的代碼: http://www.javaworld.com/javaworld/jw-06-2005/plugin/jw-0627-plugin.zip · 瀏覽Java Plug-in 5.0的文檔: http://java.sun.com/j2se/1.5.0/docs/guide/plugin/index.html · 學(xué)習(xí)Mozilla.org的 nsPluginDirServiceProvider.cpp 目錄服務(wù)提供器C++ 寫(xiě)的代碼 : http://lxr.mozilla.org/mozilla1.7/source/modules/plugin/base/src/nsPluginDirServiceProvider.cpp · 查看 Mozilla.org的 OJI站點(diǎn) : http://www.mozilla.org/oji/ · 'Plug into Java with Java Plug-in,' Jeff Friesen (JavaWorld, June 1999): http://www.javaworld.com/javaworld/jw-06-1999/jw-06-plugin.html · 查看 Sun的 Java Plug-in 主頁(yè): http://java.sun.com/products/plugin/index.html · Jeff Friesen, 'Talk with Me Java,' (JavaWorld, June 2004): http://www.javaworld.com/javaworld/jw-06-2004/jw-0621-talk.html · 非官方的 Cookie FAQ: http://www.cookiecentral.com/faq/ Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd 摘要這篇文章與Jeff Friesen前一篇關(guān)于Java Plug-in的文章'Plug into Java with Java Plug-in' (JavaWorld, 6月 1999)是一個(gè)系列的。它專(zhuān)注于Firefox Web瀏覽器的最近的Java Plug-in其
標(biāo)簽:
Java
上一條:Java中Collection Frame中常用集合簡(jiǎn)析(ArrayList,Vector,HashSet,TreeSe下一條:讓你的Java會(huì)說(shuō)話(huà)-用Java實(shí)現(xiàn)IRC文本到語(yǔ)音轉(zhuǎn)換
相關(guān)文章:
1. Java訪(fǎng)問(wèn)控制符原理及具體用法解析2. 教你怎么用JSP統(tǒng)計(jì)網(wǎng)站訪(fǎng)問(wèn)人數(shù)3. PHP基礎(chǔ)之類(lèi)和對(duì)象6——訪(fǎng)問(wèn)控制:public/protected/private4. 解決Python訪(fǎng)問(wèn)MySQL數(shù)據(jù)庫(kù)速度慢的問(wèn)題5. Python使用Kubernetes API訪(fǎng)問(wèn)集群6. uwsgi+nginx代理Django無(wú)法訪(fǎng)問(wèn)靜態(tài)資源的解決7. docker 突然不能被外網(wǎng)訪(fǎng)問(wèn)的解決方案8. 三步解決python PermissionError: [WinError 5]拒絕訪(fǎng)問(wèn)的情況9. 在vue中配置不同的代理同時(shí)訪(fǎng)問(wèn)不同的后臺(tái)操作10. Java類(lèi)的訪(fǎng)問(wèn)權(quán)限關(guān)鍵字用法說(shuō)明
排行榜
