2010年2月7日 星期日

如何製做可外掛的 Java 程式

有很多的 Java 程式都可以使用外掛來擴充功能,
最有名的應該就是 NetBeans 和 Eclipse 了,那麼
要怎麼樣自己製作可以外掛的 Java 程式呢?

其實很簡單,首先要規範這個外掛必須要有的項目。
比如說必須要有一個方法可以顯示設定視窗,有一個
方法可以用來呼叫這個外掛的某項功能,而主程式就要透過
這些開口去對外掛作存取。

有很熟悉的感覺吧? 沒錯, Java 的 interface 就可以拿來利用。



首先,要先定義外掛規範,因為無法直接得知外掛的 MainClass
所以我們可以規定,外掛必需都放置在 plugins/ 目錄中,檔名是
MainClass 的完整名稱(包含套件名稱),並且附檔名需為 .jar

接著,定義一個 interface ,裡面包含標準的外掛必須要有哪些
方法:

package fhcrc.darkk6.plugin;
public interface MyPlugin
{
/* 放置 Plugin 必要的方法和資料 */
void showInfo();
void doSomeThing();
String getPluginName();
boolean isMethodOK(String data);
}

並且將這個 interface 發布出去,讓其他設計師可以根據這個 interface
設計套件,標準的設計就是:

package org.ker;
import fhcrc.darkk6.plugin.*;
public class KerKer implements MyPlugin
{
public KerKer()
{
System.out.println("Ker Ker 建構子");
}
public void showInfo()
{
System.out.println("科科科科科科");
}
public void doSomeThing(){System.out.println("KerKer do something");}

public String getPluginName(){return "KerKer";}

public boolean isMethodOK(String data)
{
System.out.println("KerKer 收到:"+data);return true;
}
}

當這個 class 完成之後,只要打包成 jar檔,並且放置在主程式指定的位置底下
並且命名為:org.ker.KerKer.jar
就可以在執行時取得這個套件,並且使用它。

置於主程式的寫法,提供一個簡單的範例:
(礙於版面配置,詳情參考附件)

package fhcrc.darkk6;
import java.io.*;
import java.net.*;
import java.util.*;
import fhcrc.darkk6.plugin.*;
public class Main
{
//儲存所有 plugin 的 Vector
private static Vector<MyPlugin> plugins;
public static void main(String[] args) throws Exception
{
System.out.println("程式開始");
System.out.println("尋找套件...");
File f=new File("plugins");
/* 自行加入檔案是否存在以及是否為 jar 檔
等判斷,這邊假設一切正常*/
File[] pluginFiles=f.listFiles();
URL[] pluginPacks=new URL[pluginFiles.length];
for(int i=0;i<pluginPacks.length;i++)
pluginPacks[i]=pluginFiles[i].toURI().toURL();
/*將 plugins 目錄底下的 jar 檔交給 URLClassLoader 載入*/
URLClassLoader classLoader=URLClassLoader.newInstance(pluginPacks);
plugins=new Vector<MyPlugin>();
for(File tmp:pluginFiles)
{
//取代掉 .jar 的副檔名,這樣就剩主要 Class 的完整名稱
String className=tmp.getName().replaceAll("\\.jar","");
try{
Class cls=classLoader.loadClass(className);
Object obj=cls.newInstance();
if(obj instanceof MyPlugin)
plugins.add((MyPlugin)(obj));
else
System.out.println(className+" 不是合法的套件");
}catch(ClassNotFoundException e){
System.out.println("找不到 Class:"+className);
}
}
/**== 到此 plugins 載入完成 ==*/
System.out.println("\n\n=== Main 載入 plugins 完成 ===\n");

//呼叫套件範例
//呼叫所有套件的 showInfo 方法
for(MyPlugin tmp:plugins)
{
tmp.showInfo();
System.out.println("============\n");
}
}
}

載入所有的套件後,將其以 MyPlugin 的方式儲存於List中,
如果需要由 "名稱" 來取得 "套件" 實體,可以使用 Map 來做,會
方便很多。

簡單的製作一個外掛的 Java 程式就是如此輕鬆。

範例檔案:http://w5.loxa.com.tw/kk6/share/Plugin.rar

沒有留言:

張貼留言