不知諸位有沒有想過用Applet來組織Web的程序界面?小弟最近整理了一些雜碎的思路,思想完全開放,歡迎批評。
先說一下可能遇到的問題:
1 安全性:Applet對本地資源的操作需要相應的安全許可;
2 庫資源的下載:如何下載及管理支持本地Applet的庫資源;
3 通信:Applet如何與后臺的Servlet進行通信;
4 圖形的加載:如何利用Applet動態的實例化并展現界面。
下面一一展開討論
(一)保障安全性
安全性的主要解決方案是利用Java提供的keytool生成一個keystore,并利用這個keystore對jar包進行signjar的操作。
整個對Java文件的編譯,打包和signjar過程可以利用Ant來完成,比如下面的Ant腳本片段就是用來處理signjar的,大家也可以通過相應的Java命令直接處理:
<
target
name
="signjar"
depends
="jar"
>
<
signjar
jar
="example.jar"
keystore
="${basedir}/yangyi.keystore"
storepass
="mypassword"
alias
="mykey"
></
signjar
>
</
target
>
如果直接用命令,則其形式為:
jarsigner [ options ] jar-file alias
具體的操作方法可以參考下面的鏈接:
http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/jarsigner.html
通過這個signjar的操作,我們就給這個包中的類進行了一次數字簽名,這樣,當Applet進行默認許可之外的操作時,窗口將彈出這個數字簽名要求本地用戶進行確認,只有在確認后,用戶才可以繼續進行操作。
這樣我們可以在第一次用戶運行Applet程序時,在用戶的許可下動態地在用戶的$user.home/.java.policy下生成一個授權文件,以后就可以執行需要的操作了,為保證客戶端的安全性,僅賦予用戶執行特定文件夾權限的權利,如(僅作為例子,可以根據需要自己配置文件和Socket訪問權限):
grant codeBase "file:/home/yiyang/test/×" {
java.security.AllPermission;
};
(二)下載并管理庫支持
這個過程可以通過Java的URL類提供的openConnection方法來獲取一個InputStream從而獲取到遠程的資源(包括支持庫和配置文件兩部分)
1)對于配置文件,因為其內容都比較少,而且比較簡單,可以直接通過輸入流來獲取,這是沒有異議的;
2)對于庫文件,在下載之前先到我們管理的庫的目錄下找到版本索引文件(我們設定一個版本索引文件來管理升級),這個版本索引文件如下所示:
time={資源獲取的時間戳}
lib1.jar=1.0
lib2.jar=1.1
其中,服務器端也保留有一份這樣的版本文件,當下載庫文件時,首先對客戶端和服務端的庫的總時間戳進行比較,如果客戶端大于或等于服務端,則不需下載,否則,如果客戶端對應項目為空或者其總的時間戳小于服務端,則進一步比較內部庫文件的版本,發現版本低的庫或在客戶端不存在的庫后,自動到服務器上進行下載,在下載成功后,更新客戶端的索引文件。
(三)通信
這個問題小弟曾在以往的blog中有過詳細的討論,可以到http://yangyi.blogjava.net中的相應隨筆中找到答案。總的來說,在類型協議并不復雜,且客戶端,服務端均為Java開發的情況下,應用Hessian是一個好的解決方案,需要指出的是Hessian中的代碼對客戶端來說并不是全部必須的,大家可以根據客戶端的使用情況對這個庫進行瘦身。只保留作為客戶端必要的類即可。
(四)動態的實例化及插件結構
我們要實現用戶界面的集成,從根本上說要解決下面的幾個問題:
1)菜單集成
2)支持庫集成
3)集成點
4)輸出變量
對于客戶端為Applet開發的插件,我們把上面的四項配置統一在XML文件中進行描述定義。
這里需要注意的是菜單要提供名稱,支持庫要提供下載路徑或者本地路徑,集成點我們希望是一個JPanel。
在定義好XML后,可以到網址:http://www.flame-ware.com/xml2xsd/去獲得一個對應的schema,利用這個schema和JAXB提供的xjc工具,我們就可以生成對應的XML操作類,來對配置進行處理。
對于菜單的集成可以動態地在JMenu中添加MenuItem(表示插件的功能)
根據配置的支持庫的位置,我們可以通過Java的URLClassLoader對庫進行動態的加載,然后根據相應的集成點,獲取實例,這個過程的示例代碼如下所示:
File f
=
new
File(
"
a.jar
"
);
//
a.jar是我們從配置文件中讀取的支持庫
URL url
=
null
;
Class lib
=
null
;

try
{
url
=
f.toURI().toURL();
lib
=
Class.forName(
"
Lib
"
,
true
,
new
URLClassLoader(

new
URL[]
{ url }
));
//
Lib是我們從配置文件中讀取的集成點
JPanel plugin_panel
=
(JPanel)lib.newInstance();
return
plugin_panel;

}
catch
(Exception e)
{
e.printStackTrace();
}
對于輸出變量,其主要作用是用戶各個插件之間的信息交互,我們可以通過一個總的HashMap來實現,為避免變量值出現沖突,在變量名前自動加上插件名的前綴。
如plug_in1的變量var1,其系統名稱為:plug_in1__var1.
解決了上面的四個障礙,我們就可以把精力投入到具體的功能實現上了。
@2008 楊一. 版權所有. 保留所有權利