当前页面位置: » 丰搜网 » 文档中心 » 详细内容
从firefox访问java plug-in
摘要
这篇文章与jeff friesen前一篇关于java plug-in的文章"plug into java with java plug-in" (javaworld, 6月 1999)是一个系列的。它专注于firefox web浏览器的最近的java plug-in其中之一。在篇文章中,你能学会从firefox怎样访问java plug-in。你也能学到一些关于java plug-in文件对象模块(dom),applet状态持久化,和cookie。除此以外,你还可以学习applet,它在firefox中的运行,这将加强你对这些内容的理解。但那仅仅是开始。难道你曾经不想去探求firefox是怎样与java plug-in(在后台)交互的吗?继续读下去你就会找到答案的。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者: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
关键字:firefox;java;plug-in
从我在javaworld 上写"plug into java with java plug-in" 开始,9年已经过去了。我的前一篇文章给java plug-in下了定义,讲到了怎样.netscape communicator 4.5 和 inte.net explorer 3.02 上怎样安装版本1.2,描述了与java plug-in相关的windows注册表设置,了解了java plug-in的控制面版,考查了两个java主控台,讨论了html 的<embed> 和 <object>标签,还发布了一个基于swing的用于demo的applet。
自从我写了那篇文章后,java和java plug-in已经相继发布了许多个版本。看来那篇文章已显老态,所以我已经写好它的系列篇,它专注于针对firefox web浏览器的最近的java plug-in其中之一。这篇文章首先为你讲解从firefox怎样访问java plug-in。然后讨论java plug-in文件对象模块(dom), applet状态持久化 和cookie。比如在firefox上运行的各种applet,当你在学习这些内容时,将会强化你已经掌握的知识。这篇文章通过探寻firefox 和java plug-in之间的联系,再做归纳。因为对于java plug-in而言,在其他地方会比我在这里所讲的要详细得多,所以我建议可以学习sun的java plug-in文档,你将会学到更多的技术。
这篇文章的实验环境是mozilla firefox 1.0, j2se 5.0, 和windows 98 se。即使你没有这些软件,我仍然建议你读完这篇文章。真诚地希望你能发现一些对你来说还是未知的有兴趣的东西。
java plug-in 和firefox
java plug-in象桥一样服务于浏览器和一个外部的 java运行环境(jre)之间。java plug-in对于在firefox 中运行的applet而言是相当重要的,因为浏览器不能自身为其提供一个jre——其中包括一个jvm。因为这篇文章描述的applet会涉及到不同多个不同的java plug-in内容,还有就是这些applet都是在firefox的环境中运行的,所以我们首先应该看一下如何从firefox中访问java plug-in。
对于初学者来说,你必须确认在你的平台上已经安装了j2se 5.0 和 jre。在我的windows平台上,我用jdk-1_5_0-windows-i586.exe安装文件把j2se 和 jre都安装好了。确定你已经安装了jre,因为jre包含了java plug-in。
在安装好j2se 5.0后,连接firefox 到 java plug-in;首先从firefox的工具菜单中选择options,然后选择web features,最后点击enable java checkbox。
一般情况下,标签<embed> 和 <object>应该指向在java plug-in下运行的applet。这对java plug-in 5.0来说不是必要的,它能运行由简单的<applet>标签指定的applet。在安装时,你有机会屏蔽inte.net explorer 和 mozilla (firefox).netscape web浏览器对applet的执行,如果它们遇到了<applet>标签,而转交给java plug-in处理。如果你放弃这个选项,迟些时候你可以通过java plug-in的控制面版来完成这个变化。比如,打开控制面版,选择标签advanced。然后点击<applet> tag support左边的“+”,再选择mozilla and.netscape选项。关闭这个面版后,当firefox遇到<applet>标签时,它就会交给java plug-in执行。图1给出了这些必要的改变。
选择mozilla and.netscape,所以当firefox遇到<applet>标签时,它就会交给java plug-in执行
提示
我发现在我的平台上选择mozilla and.netscape不是必须的。我的firefox web浏览器不会去管那个复选框的设置,当遇见<applet>时,它就会让java plug-in来执行。java plug-in 5.0的文档谈到这是个奇怪的行为:“如果mozilla 和.netscape 7都被安装好了,负责管理对<applet>标签是否支持的mozilla and.netscape选项没有被选中的情况下,<applet>标签中的内容照样可以在sun vm上运行。这是.netscape 7的自动扫描功能相关的一个bug。”因为我已经安装.netscape 6.2.3,所以我认为我找到了这个bug。如果在你的平台上遇到了这个问题,记住这点就行了。
平台上能驻留多个jre,当firefox遇到<applet>标签时,到底哪一个jre来实现java plug-in?可以从java plug-in控制面版上的java标签上找到答案。在二选一的情况下,我用来进行版本测试的applet给出了答案,同时也证明了firefox是连接了 java plug-in的。图2显示我当前使用的jre版本是1.5.0。(版本1.5.0是j2se 5.0的内部版本号)
图2. 我已经配置好使用jre 1.5.0的java plug-in
listing 1给出了该applet的versiondemo.java文件的源代码。这些代码在系统属性java.version 中设置了jre 的版本。
listing 1. versiondetect.java
// versiondetect.java
import 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);
}
}
为了简洁,在这篇文章中我将不会给出运行这个或者其他
applet的
html。参见这篇文章中的source code 。
提示 firefox只支持
java plug-in 1.3.0_01和更高版本。
调用dom根据www 联合会 (w3c)所说,文件对象模块(dom)是一个api,它针对“有效的
html和合式的
xml文档。它定义了文档的逻辑结构,访问和操作文档的方法。”
java plug-in提供了两种方法来调用dom:
.netscape.
javascript.
jsobject和common dom api。
jsobject为
java applet 和
web 浏览器的
javascript实现之间提供了接口,包含使用了dom 的
javascript 对象。这些对象的例子:document, link, 和 window。我将不会深入
jsobject,因为在我早期的文章"talk with me
java"中,我已经讨论了这个类。因此我专注于在一个
applet中,通过common dom api来遍历dom 。
在
j2se 版本1.4中已经介绍过common dom api,它是一个类和接口的集合,通过这些接口可以让
applet遍历dom实例。因为一个浏览器通过帧和窗口能够显示多个文档,所以会有许多dom实例以备遍历。一般一个
applet就遍历它自己的dom实例—这个与文档相联系的dom实例指定了这个
applet。
访问dom实例的起点就是静态方法getservice(object obj),该方法位于类com.sun.
java.browser.dom.domservice中。一般情况下,一个被唤醒
applet的this指针会被作为一个参数传递给getservice()。这个方法要么返回一个 domservice对象(为这个
applet和它的dom实例之间提供接口),要么抛一个异常:
com.sun.
java.browser.dom.domunsupportedexception (the dom service is not available to the object) 或者 com.sun.
java.browser.dom.dom
accessexception (a security violation has resulted)。例子:domservice service = domservice.getservice (this);。
因为
web浏览器提供了不同的dom实现,所以访问一个dom实例不是
线程安全的,除非那个访问是发生在dom
access dispatch
线程。为了确保
线程安全性,domservice提供了两个方法来保证访问只是发生在dom
access dispatch
线程—invokelater() 和 invokeandwait()。
两种方法都用实现了接口com.sun.
java.browser.dom.domaction的对象作为参数,来提供方法run()。invokelater()在dom dispatch
线程中异步执行run(),invokeandwait()在dom dispatch
线程中同步执行run()。
方法run()用实现了接口com.sun.
java.browser.dom.dom
accessor的对象作为其唯一参数,然后返回一个基本的object引用。方法run()经常唤醒dom
accessor的getdocument()方法,传递一个
applet的指针做getdocument()的object参数。作为回应,getdocument()会返回一个实现org.w3c.dom.document接口的对象。那个对象中就包含了这个文档的信息。对于
html文档而言,它会把document向下转型为
htmldocument(位于org.w3c.dom.
html中),然后调用
htmldocument的方法去获取这个文档的标题,域,
applet集,和一些其他的。在调用属性方法后,run()返回一个包含文档信息(比如
htmldocument的标题)的object对象。那个object随后又从invokeandwait()和invokelater()方法中返回。
为了梳理上面讨论的内容,我写了一个从一个
html文档中提取标题的
applet,然后把标题显示给用户。下面就是它的代码。
listing 2. titleextract.java // titleextract.java
import 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()方法调用了
htmldocument的gettitle()方法去获取
html文档的标题。随后显示该标题。例如,当在titleextract.
html(参见本文的source code)中遇到元素时,gettitle()返回“extract the title”。图3中显示了firefox中的结果。
图3。 显示一个文档的标题
注意 当从标签<
applet> 中调用titleextract时,firefox要求mayscript属性需要被给出。否则,由于firefox的dom实现依赖于
jsobject,
java plug-in会抛出各种异常。
applet在firefox session中的持久状态java plug-in 5.0的文档提到许多有趣的课题。其中之一就是
applet的持久性api,它可以让一个
applet保存其状态以备在后来的相同的
web浏览器session中使用。state被保存在由
java plug-in控制的一个内部持久性存储数据结构中;一个session是指某个
web浏览器被打开运行开始到这个浏览器被关闭结束。
在
j2se 1.4中介绍的
applet持久性api ,由声明在接口
java.
applet.
appletcontext中的三个方法构成:
· void setstream(string key, inputstream stream) throws ioexception 需要当前
applet上下文的一个具体key和具体的stream作为参数。如果一个新的stream对应了当前的key,这个新stream将会取代那个旧的stream。如果新stream的size超出了内部size的限制,将会抛出一个异常ioexception。
· inputstream getstream(string key)返回与当前
applet key相联系的inputstream。如果没有指向该key的stream就返回null。
· iterator<string> getstreamkeys()返回一个迭代器,它包括了指向当前
applet中stream的所有key。
通过调用setstream()来保存状态。这个方法把一个key(它可以方便地标识一个输入流)和一个inputstream的引用存储到一个内部数据结构中去,比如一个hashmap。取出某状态可以通过相应的标识key调用getstream()。它会返回一个inputstream(如果这个key存在)以恢复到这个状态。
因为
java plug-in5.0文档没有提供例子来指出怎样使用
applet持久性api,所以我准备了一个例子。它给出了一个消息传送
applet的两个实例,其中的一个使用
applet持久性api发送消息给另一个。图4中,用户在左边实例的 message to send文本框中输入一个消息,然后点击该实例的send按扭。然后用户点击右边实例的receive按扭,这个消息就会在该实例的message received文本框中显示。
图4 .
applet的持久性api使
applet之间相互发送消息给对方。点击“最大化”
消息发送发生在下面代码的action listener中。
listing 3. messagetransfer.java // messagetransfer.java
import 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 ());
}
}
}
}
这个消息发送
applet把消息持久化为一个string对象,通过把这个对象序列化到bytearrayoutputstream,转化这个stream到一个byte数组,基于这个byte数组构建一个bytearrayinputstream,然后通过这个stream和一个名为text的key调用方法setstream()。该
applet用这个名为text的key调用getstream()取回这个消息,然后反序列化这个inputstream。
在firefox中,被持久化后的消息对在不同窗口或面版上运行的
applet都是可以被访问的。这种消息对不同session(也就是说,firefox的不同实例)中运行的
applet是不能被访问的,因为每个session只与它自己的
java plug-in实例和内部持久性存储数据结构进行通信。
提示 出于
安全考虑,使用不同codebase的
applet不能访问对方的stream。
了解cookieweb浏览器和
web服务器经常发送小的数据包给对方进行交互。这些包,也就是大家知道的cookie,可以被用来跟踪用户的喜好,帮用户自动登录站点等。
java plug-in结合
web 浏览器可以让
applet访问cookie。例如,
java plug-in让签名
applet去查看从
web服务器发送到
web浏览器的cookie。
java plug-in5.0文档中谈及对cookie的支持时,给出了几个与cookie交互的代码片段。因为你可能想在
applet中
测试这些代码片段,还有就是可能你不确定该怎样把它们转变成签名
applet,所以下面我给出了一个用来查看cookie的签名
applet。在讨论完这些重要的代码后,我将带你学习怎样建立和签名
applet。最后,我们会在firefox
web浏览器中运行这个
applet。
下面就是代码。
listing 4. cookiedetect.java// cookiedetect.java
import 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<string, list<string>> headers = conn.getheaderfields ();
list<string> values = headers.get ("set-cookie");
if (values == null)
{
txtastatus.settext ("no cookies detected\n");
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主要由两个条目构成:一个接受url的文本框,和一个显示cookie的文本域。无论何时用户按下enter键和这个文本框获得了输入的光标,文本框的action listener的方法actionperformed()都会被调用。
方法actionperformed()首先用文本框中的url建立一个url对象。然后调用这个对象的openconnection()方法返回一个表示该
applet和该url相互连接的urlconnection对象。继续往下面看,urlconnection()的方法connect()建立这个连接,它的getheaderfields()方法可以得到不会改变的一组http头和相对应的值,map的方法get()返回与头set-cookie相对应的值组成的list。一个循环列举出了该list中的值;每个值表示一个cookie,被陆续加入文本区域中。
假使cookiedetect.
java存放在当前目录c:\
applets\cookiedetect中,完成下面的操作,建立和签名这个查看cookie的
applet:
· 编译 cookiedetect.
java:
javac cookiedetect.
java.
· 把上步得到的cookiedetect.class替换成一个jar文件,jar cvf cookiedetect.jar cookiedetect.class。
· 在一个新keytore中创建一个新key:keytool -genkey -keystore ks -alias me。当弹出来后,输入testtest作为keystore的密码,你的姓和名,你所在行业(比如it),你公司的名字,你所在城市名,所在州或省的名字,你的行业代码 ,不管你刚才输入的信息是否真实,当弹出窗口时选择yes。当弹出窗口让你输入me的密码 时,单击enter。这样可以让密码与keystore 中的密码(testtest)相同。所有这些信息都被放在文件ks中,这个文件需要我们自己签名的
测试认证。
· 创建一个签名的
测试认证:keytool -selfcert -alias me -keystore ks。当被弹出后,输入testtest作为keystore的密码。这个认证就被放进ks中了。alias me (在前一步,这步,和下一步中)提醒你这个认证已被签名,仅仅用来被
测试。换句话说,不要在公共站点上用这个
测试认证来发布签名
applet。
· 用这个
测试认证来签名这个jar文件:jarsigner -keystore ks cookiedetect.jar me。当弹出后,输入testtest作为keystore的密码。这个工具更新该jar文件的meta-inf目录以包含认证信息和cookiedetect.class的一个数字签名。
让我们运行这个
applet。从本文附的代码中找到cookiedetect.
html,然后放进目录c:\
applets\cookiedetect下。该
html文件的<
applet>中包含一个archive属性来标识cookiedetect.jar文件。打开firefox,然后输入该
html文件的url:
c:\
applets\cookiedetect\cookiedetect.
html。一段时间后,图5的
安全对话框就会出现在你眼前。
figure 5.
安全对话框让你有权信任这个签名的
applet。
单击yes键响应该
安全对话框。然后这个
applet被显示。输入url:http://
javaworld.com,然后按下回车。如图6所示,网站
javaworld 不会发送cookie。
figure 6. 你不会从
javaworld 取得cookie
与
javaworld 相比,网站
javalobby会发送一个cookie。输入http://
javalobby.org,图7中就会显示有这样一个cookie,id 是sessionid。
figure 7.
javalobby 发送了一个简单的cookie
一些网站会发送出大量的cookie,比如像kasssamba。如图8所显示的,该站点发送了4个cookie到
web浏览器。
figure 8. kasamba 发送了不少的cookie到
web浏览器
我极力建议你继续去体会cookie的使用,把余下的三段代码(来源于
java plug-in 5.0文档中对cookie支持的标题)也转换成签名
applet。
小窍门 访问 http://www.cookiecentral.com/faq/ 可以学到更多关于cookie的内容。
理解 hood 许多人在让firefox识别
java plug-in时会遇到困难。说来说去,就是指
applet不能运行。通过理解firefox与
java plug-in怎样进行交互,你能避开许多类似的麻烦。在后续部分,我会为你讲解firefox如何探测
java plug-in,jre的 np*.dll 插件文件,和一些被称为oji的东西。
探测java plug-in在前面你已经安装了一个简单的jre(它包含了
java plug-in),现在要安装firefox。你可以运行那个浏览器,上网冲浪,打开那些使用了
applet的网页,那些
applet就会运行起来了。。不久后,你会思考firefox是怎样找到
java plug-in,让
applet运行起来的。毕竟说来,firefox只检索它自己的插件列表来查找插件,而jre把它自己的
java plug-in放在它自身的bin目录下。在这样的安排下,firefox怎么可能检测到
java plug-in呢?
当firefox开始运行时,它的目录服务提供器就接到一个任务,在windows平台上的安装目录中去找adobe acrobat, apple quicktime, microsoft
windows media player, 和 sun
java plug-in。
java plug-in的安装目录一经找到,目录服务提供器将会传递以下信息给plugin.scan.sunjre:用户的个人设置名称和该设置的值(要求的最低jre版本)。更进一步,security.enable_
java 这个用户设置必须存在,而且它的布尔值必须为true。
假如plugin.scan.sunjre 和 security.enable_
java存在,还假设security.enable_
java的值是true,目录服务提供器会在windows的
注册表中列出所有版本号作为hkey_local_machine\\software\\
javasoft\\
java plug-in的子键。最新版本号识别出firefox所使用的jre/
java plug-in,这个版本号必须要比plugin.scan.sunjre的值要大或相等.版本号子键自身的
javahome子键包含了被识别出的jre根目录路径。目录服务提供器把\bin附加在这个目录后,这时firefox就知道了
java plug-in的安装路径了。有点糊涂了?我会用一个例子来拨开这一层雾。
我的firefox浏览器给出我的plugin.scan.sunjre值为1.3。它同时也指定security.enable_
java值为真。在启动时,目录服务提供器扫描我的windows
注册表;相关的设置如下:
hkey_local_machine
software
javasoft
java plug-in
1.5.0
javahome "c:\program files\
java\jre1.5.0"
目录服务提供器列举出所有版本号的子键,在
java plug-in子键下面,那个子键所示的最高版本号就大于或等于1.3了。我仅有一个子键大于或等于1.3:1.5.0。因此,目录服务提供器含有子键值为1.5.0的
javahome子键—c:\program files\
java\jre1.5.0—然后把\bin附加在这个值的后面。这就意味着firefox会在目录c:\program files\
java\jre1.5.0\bin下去找
java plug-in。
因为firefox1.0的plugin.scan.sunjre用户设置用1.3作为它的默认值,所以
java plug-in版本低于1.3的不会被识别。这就是为什么firefox只支持
java plug-in 1.3.0_01和更高的版本。
np*.dll文件
仔细查看你的jre的 bin目录,你会发现不少文件名以np开头,以.dll结尾的文件。例如,我的平台下就列出了下面这些文件:
np
java11.dll
np
java12.dll
np
java13.dll
np
java14.dll
np
java32.dll
npjpi150.dll
npoji610.dll
上面列出的文件
.netscape的插件文件。加上你可能在你的jre的bin目录下发现的其他np*.dll文件,和也应该被列出的若干个jpi*.dll文件,他们一起构成了
java plug-in。每个np*.dll文件有相同的大小,因为他们基本上都是做的同样的事情:它与jpi*.dll文件中的一个协同工作,下载虚拟机,让
java环境运行起来。
每一个np*.dll文件能识别一种或多种mime(多用途网际邮件扩展协议)类型。当遇到某种mime类型时,这种类型会告诉firefox去装载一个相应的具体np*.dll文件。例如,思考下面的<embed>标签:
<embed code="versiondetect.class" width="200" height="200"
pluginspage="."
type="application/x-java-applet;version=1.1">
注意type属性的application/x-
java-
applet;version=1.1 mime类型。当firefox遇到这种mime类型,它就会选择相应的np*.dll文件。因为np
java11.dll标记了那种mime类型,np
java11.dll会去装载——而不是其他的np*.dll装载。np
java11.dll与jpi*.dl文件一起让
java环境运行。
当firefox遇见<
applet>标签时,它到底表示的是哪种mime类型?我认为当firefox 遇到<
applet> 标签时,application/x-
java-vm就是mime类型:
测试显示出只有拥有那个mime类型的npoji610.dll会去装载。
什么是oji?你可能已经注意到在npoji610.dll中有oji,想知道这三个字母代表什么。oji表示open jvm integration ,这是个mozilla project/api,它允许外部的jvm能够插入一个 mozilla浏览器(就像firefox这样)。除了没有被绑定在内部虚拟机上,这个浏览器也没有被绑定在sun指定的外部虚拟机上——浏览器能够通过其他途径与虚拟机进行交互,只要这些虚拟机支持oji。
oji有许多特性,包括允许用户通过
web浏览器来显示
java主控台。oji也会更改一个
applet的生命周期:一旦一个
applet网页被打开,这个
applet的init() 和 start()方法就会被调用。为了让你能看到这个过程,先编译listing 5的 lifecycle.
java源代码,在firefox下运行这个
applet,打开
java主空台,然后不停在网页之间进行切换。在你每次进入这个
applet网页的时候,你将注意到对这个
applet构造器的调用,它表明一个新的lifecycle对象被生成了。
listing 5. lifecycle.java // lifecycle.java
public 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");
}
}
总结即使讲完上面所有的内容,我也仅仅是做了浅层次的讲解。其实还有很多东西我想写下来。可能只有在以后,我再写另一篇后续文章来完成了。或者你也可以写那篇文章。不管怎样,都让我们继续拓展我们对sun的
java plug-in技术的理解吧。
关于作者jeff friesen 是软件发展的自由撰稿人,同时也是c, c++, 和
java技术的研究员。
资源列表 · 下载这篇文章中的代码:
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 · 学习mozilla.org的 nsplugindirserviceprovider.cpp 目录服务提供器c++ 写的代码 :
http://lxr.mozilla.org/mozilla1.7/source/modules/plugin/base/src/nsplugindirserviceprovider.cpp
· 查看 mozilla.org的 oji站点 :
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 主页:
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/