利用RMi進行分布式開發
bromon原創 著作權
RMI是J2EE中一項非常重要的技術,全稱是遠程方法調用(Remote Method Invokation),是EJB(Enterprise JavaBean)的基礎。利用它可以很輕鬆的編寫基於純java(pure java)的分布式應用程式,使得表現層、邏輯層和資料層互相分離,便於程式的維護和資料的管理。下面使用RMI編寫一個簡單的分布式程式,介紹一下RMI的使用方法。為了使程式更具有參考價值,我們不局限於實現一個“hello,world”的簡單例子。我們將在Rmi中傳遞一個較為複雜的對象,具體來講就是伺服器經使用者請求後串連MSsql資料庫,讀取資料產生一個視窗,在用戶端顯示。程式涉及java中的RMI、swing組件、jdbc-odbc bridge串連資料庫等技術,所以讀者最好具備一些java的基礎知識。
一、開發環境
首先需要一個jdk,版本越高越好,建議使用j2sdk1.4.1,可以在java.sun.com下載;伺服器端需要安裝mssql,版本在7.0及以上為佳。用戶端需要有jre(java運行環境,java run environment)支援,不過大多數作業系統都內建了(windows xp除外,需要安裝外掛程式,可以在java.sun.com下載),不過使用新的jre可以避免很多莫名其妙的問題。雖然NotePad足以讓我們完成所有代碼的編寫,但是一個好的編輯工具可以讓你更加高效,推薦使用EditPlus 2。
由於jdk的安裝不是本問重點,所以只簡單講述一下jdk在windows下的安裝。下載j2sdk1.4.1後運行,一路next即可,預設安裝在c:j2sdk1.4.1。為windows設定環境變數,在path中加入;c:j2sdk1.4.1in,然後建立一個變數set classpath=c:j2sdk1.4.1lib ools.jar。如果你的安裝目錄是自訂的,做相應修改即可。登出一次使環境變數生效,開啟一個控制台視窗(win98下開啟msdos視窗),輸入java,可以看到java的參數列表,表示安裝沒有問題。
在mssql中建立資料庫及表格。假設資料庫名稱為db1,表格名稱為table1,並建立一個String欄位name,任意添加一條記錄。為該資料庫建立資料來源,假設資料來源名為data。
準備工作到此為止,Let’s go!
二、一個完整的Rmi程式包括三個部分:主介面、伺服器端和用戶端。我們一邊寫一邊講解。
首先是定義一個介面:
//myInterface.java
import java.rmi.*; //所有的rmi程式都必須引入rmi包
import javax.swing.*; //建立可視化環境需要引入的包
public class myInterface extends Remote
{
JFrame getData() throws RemoteException;
}
這個介面定義了遠端可供調用的方法getData(),它返回一個JFrame,也就是一個swing視窗。這個方法必須拋出RemoteException異常。將檔案儲存為myInterface.java。到控制台下編譯該檔案:javac myInterface.java,會產生一個myInterface.class的檔案。
然後編寫伺服器端:
//server.java
import java.rmi.*;
import javax.swing.*;
import java.sql.*; //串連資料庫需要使用的包
import java.rmi.server.UnicastRemoteObject; //引入一個伺服器端啟用程式的包
public class Server extends UnicastRemoteObject implements myInterface
{
static JFrame S_window=null;
static JTextArea JTA=null;
public Server() throws RemoteException{}
public static void connect()
{
try
{
String url="jdbc:odbc:data";
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn=DriverManager.getConnection(url,"sa","");
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery("select * from table1”);
if(rs.next())
{
JTA.append(rs.getString(1).trim());
}else
{
JTA.append(“資料庫中沒有資料”);
}
stmt.close();
conn.close();
}catch(Exception se)
{
System.out.println(“資料庫連接出現錯誤”);
}
}
public JFrame getData() throws RemoteException
{
S_window=new JFrame(“test”);
JTA=new JTextArea(“”,10,5);
Connect();
JPanel JP=new JPanel();
JP.add(JTA);
S_window.getContentPane().add(JP);
return(S_window);
}
public static void main(String args[])
{
try{
S_window s=new S_window();
Naming.rebind(“rmi:///myInterface”,s);
}catch(Exception e)
{
e.getStackTrace();
}
}
}
伺服器端首先拋出RemoteException異常,然後實現我們剛纔則主介面中定義的方法getData()。使用Naming.rebind()方法註冊RMI伺服器,並與我們定義的s對象綁定,這樣一來當我們在用戶端向rmi://localhost/myInterface發出請求的時候,伺服器端會自動調用s對象來處理請求。檔案儲存為server.java,編譯它:javac server.java,產生server.class。
最後我們來寫用戶端,非常簡單:
//client.java
packge client
import java.rmi.*;
import javax.swing.*;
public class client
{
static JFrame C_window=null;
public static void main(String args[])
{
try{
myInterface mi=(myInterface)Naming.lookup(“rmi://localhost/myInterface”);
C_window=mi.getData();
}catch(Exception e)
{
e.getStackTrace();
}finally{
C_window.setBounds(0,0,400,300);
C_window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
C_window.show();
}
}
}
程式首先在本地定義一個swing視窗C_window,這個本機物件將接收遠端對象的資料,在本地顯示給使用者,從而使得伺服器端可以響應多個串連,如果不建立這個本機物件,而直接使用mi.getData().show()來顯示視窗的話,程式一樣可以運行,但是此時伺服器端只會響應最後一個串連串連。Naming.lookup()是用來尋找指定地址的Rmi服務的,通過調用它的getData()方法來運行伺服器端的程式。
檔案儲存為clieng.java,編譯它:javac client.java
程式就編寫完畢,下面讓我們來部署它。到控制台下切換到程式所在目錄,運行rmic server,會產生兩個檔案:server_stub.class和server_skel.class。請大家注意,server_stub.class是RMI服務在本地機器上的副本,叫做殘根,用戶端是通過它來和伺服器建立串連,所以需要把它和client下面的所有.class檔案一起安裝到客戶機。而server_skel.class是負責在伺服器端等候串連,叫做架構,它將代表格服務器與server_stub.class進行串連,將它和server下面的所有.class檔案一起安裝到伺服器端。jdk1.2以上版本內建了架構,不需要自行產生,但是我們需要相容低版本的jdk。部署完畢,現在註冊rmi服務:控制台下運行start rmiregistry,不要關閉彈出的視窗;運行start java server啟動伺服器端,不要關閉彈出的視窗,然後運行java client啟動用戶端,如果順利將產生一個swing視窗,含有一個文本區,裡面將顯示從資料庫中讀取的內容。
利用Rmi開發分布式程式有很多好處,可以實現程式的多層結構,程式比較安全,即使用戶端程式被反編譯也不會造成泄密。RMI對伺服器要求不高,只要能運行java即可,不像EJB那樣需要另外安裝容器。程式靈活,可以根據自己的需要在伺服器端提供任何需要的服務而不用考慮許可權問題。易於管理和維護,只需在伺服器端做出修改就可以更改用戶端的介面和功能。擴充性很強,利用伺服器端進行i/o操作可以實現簡單的web服務,利用伺服器端與其他機器通過網路進行socket串連可以實現簡單的Proxy 伺服器,等等。