各位好,很久沒更新了,今天來談談Java Applet的一個 特別的應用方式。以前Java Applet並沒有太多可供討論的地方, 因為之前applet的執行受到瀏覽器的jvm的限制,基本上只能秀一些 簡單的圖形介面,很難有更多的功能,加上applet本身的安全性限制, 都綁住了applet的能力。然而,在java plugin開始推出之後,一方面 可以使用最新的jvm,一方面有一個較好的安全認證機制,讓擁有電子簽名 的applet可以在使用者的同意下存取更多的資源。如此一來,applet可以發揮 更大的公用。 我們先簡單的提一下applet的簽章機制。如果要做正式的產品,我們 必須向中立的機構付費先取得電子簽章,如果只是測試用途,我們可以使用jdk 內建的keytool來產生電子簽章。經過電子簽章的applet,在執行的時候,會顯示 出一個詢問視窗,詢問使用者是否願意信任這個電子簽章,如果使用者信任的話, 這個applet以及從這個applet產生的執行緒會被當成安全的本地端程式,擁有很大 的執行權限。不論透過任何方式取得電子簽章,我們都可以先利用jar這個工具把 applet的class檔案封裝起來,然後利用jdk內建的jarsigner工具來對這個jar檔案 做簽章的動作。 理論上,簽章過的applet一但獲得使用者的信任,即使要寫入本地的檔案系統 都沒有問題。不過我們想做更多的變化,把applet拿來當作類似ActiveX control那樣 ,配合script language來使用。我們看看這個範例程式: ======================================================== ======================================================== 假設writeToLocalFileSystem()這個函式會寫入使用者的檔案系統。很可惜的是, 這個做法會失敗。雖然applet被使用者信任了,但是這個script並不會被使用者信任,因此 從這個script呼叫appletObj.writeToLocalFileSystem()的這個動作處在不被信任的執行緒中, 所以會被攔截下來。解決的辦法很簡單,因為writeToLocalFileSystem()這個函式是被不信任 的執行緒所呼叫的,我們只能讓他做很簡單的動作,我們可以讓他來設定applet裡面的某個變數 資料。然後,因為applet本身是被信任的,我們可以從applet內部產生一個受信任的執行緒, 讓這個執行緒監視前述的變數資料,然後來執行寫入檔案系統的動作就可以了。詳細的做法請參考 下列程式: ======================================================== package appletTest; import java.applet.*; import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.*; import java.util.*; public class testApplet extends Applet implements Runnable { private int value=0; private int counter=0; private Vector fileLoadingQueue=null; private Hashtable fileLoadingTable=null; private boolean running=true; public testApplet() { fileLoadingQueue=new Vector(); fileLoadingTable=new Hashtable(); } public int getValue(){return value;} public void setValue(int value){this.value=value;} public void stop() { running=false; super.stop(); } public void start() { new Thread(this).start(); } public Element testObject(String filename) { try{ DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); DocumentBuilder db=dbf.newDocumentBuilder(); return db.parse(new java.io.File(filename)).getDocumentElement(); }catch(Exception e){return null;} } public helperObject getHelperObject() { return new helperObject(); } public synchronized String testDom(String fileName) { String id=""+counter; counter++; LoadingEntry entry=new LoadingEntry(); entry.fileName=fileName; entry.id=id; fileLoadingQueue.add(entry); notifyAll(); while(fileLoadingTable.get(id)==null) { try{ wait(); }catch(Exception e){} } Document dom=(Document)(fileLoadingTable.get(id)); fileLoadingTable.remove(id); return dom.getDocumentElement().getNodeName(); } public void run() { while(running) { try{ synchronized(this) { if(fileLoadingQueue.size()==0) { wait(); continue; } LoadingEntry entry=(LoadingEntry)(fileLoadingQueue.remove(0)); String fileName=entry.fileName; DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); DocumentBuilder db=dbf.newDocumentBuilder(); Document dom=db.parse(new java.io.File(fileName)); fileLoadingTable.put(entry.id,dom); FileOutputStream fileOutput=new FileOutputStream("c:\\test.dat"); PrintStream output=new PrintStream(fileOutput); output.println("test."); output.close(); notifyAll(); } } catch(SecurityException e1){throw e1;} catch(Exception e){} } } } class LoadingEntry { public String fileName=null; public String id=null; public boolean equals(Object obj) { if(!(obj instanceof LoadingEntry) || id==null) return false; LoadingEntry entry=(LoadingEntry)obj; if(entry.id==null) return false; return id.equals(entry.id); } public int hashCode() { int i1=0; int i2=0; if(fileName!=null) i1=fileName.hashCode(); if(id!=null) i2=id.hashCode(); return (i1+i2)%47; } } ========================================================