Java 遠端呼叫RMI 簡單例項之一
這兩天在玩java的遠端呼叫,因為之前一直沒有接觸過,也沒有寫過demo。玩起來還是走了很多彎路的,在網上搜了很多blog,很多技術大牛的blog寫的很不錯,但對於新手來說,有些問題還是沒有講解清楚。花了蠻多時間,終於整理出自己的一個demo。因此附上,供以後學習之用。 在java 基礎講義部分並沒有提及java RMI技術,在Head First Java一書中有一章將java 提到RMI技術,但內容不多。大部分RMI技術的知識我獲取渠道是網上。所列出知識點是個人能接受的。 RMI遠端方法呼叫(Remote Method Invocation)。能夠讓在某個Java虛擬機器上的物件像呼叫本地物件一樣呼叫另一個java 虛擬機器中的物件上的方法。 RMI遠端呼叫步驟:
1,客戶物件呼叫客戶端輔助物件上的方法
2,客戶端輔助物件打包呼叫資訊(變數,方法名),通過網路傳送給服務端輔助物件
3,服務端輔助物件將客戶端輔助物件傳送來的資訊解包,找出真正被呼叫的方法以及該方法所在物件
4,呼叫真正服務物件上的真正方法,並將結果返回給服務端輔助物件
5,服務端輔助物件將結果打包,傳送給客戶端輔助物件
6,客戶端輔助物件將返回值解包,返回給客戶物件
7,客戶物件獲得返回值
RMI遠端服務搭建步驟:1、建立遠端介面,建立遠端介面並繼承Remote介面。
2、實現遠端介面。
3、利用rmic工具對實現類產生stub存根類和skeleton骨架類。
4、註冊RMI服務。
5、啟動服務。
6、編寫客戶端程式碼
看例子,在Eclipse中搭建Java專案。
服務端:
專案結構:
1、 建立遠端介面:繼承Remote介面,Remote介面沒有任何方法,是一個標記性介面。
package com.rmi.remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiInterface extends Remote {
/**
* 遠端呼叫服務方法
*@Date 2017年8月2日
* @param name
* @return
* @throws RemoteException
*/
public String doService(String name) throws RemoteException;
/**
* 遠端呼叫sum方法
*@Date 2017年8月2日
* @param a
* @param b
* @return
* @throws RemoteException
*/
public int sum(int a, int b) throws RemoteException;
}
2、實現遠端介面:
package com.rmi.service;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import com.rmi.remote.RmiInterface;
public class ServiceImp extends UnicastRemoteObject implements RmiInterface{
/**
*
*/
private static final long serialVersionUID = 257078182179512007L;
public ServiceImp() throws RemoteException{
super();
}
@Override
public String doService(String name) throws RemoteException {
System.out.println("your name is" + name);
return name+" to";
}
@Override
public int sum(int a, int b) throws RemoteException {
return a+b;
}
}
這裡實現類繼承了UnicastRemoteObject ,目的是將介面連線至RMI系統。這也是建立遠端物件最簡單的方式。實現類也可以不繼承UnicastRemoteObject,而是直接利用在實現類中呼叫UnicastRemoteObject的exportObject(Object obj,int port),注意一定要指定port,可以達到相同的效果。
3、利用rmic工具對實現類產生stub存根類和skeleton骨架類。
jdk1.2以後的RMI可以通過反射API可以直接將請求傳送給真實類,所以不需要skeleton類了
在eclipse中這步驟不需要做,我在搭建專案的時候,沒有做。
4、註冊服務。
5、釋出服務。
package com.rmi.register;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import com.rmi.service.ServiceImp;
/**
* 釋出介面
*
* @author Administrator
* @date 2017年8月2日
*/
public class Main {
public static void main(String[] args) {
try {
ServiceImp serviceImp = new ServiceImp();
LocateRegistry.createRegistry(8888);
Naming.rebind("rmi://:8888/MyService", serviceImp);
System.out.println(">>INFO:遠端MyService物件繫結成功!");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
Main函式執行釋出服務。
因為是本機,所以省略本機的ip,釋出結果如圖:
這時服務類是一直執行的。
6。編寫客戶端
專案結構:
客戶端專案中需要有客戶端輔助物件打包呼叫資訊(變數,方法名)傳送到網路。RmiInterface.java就是客戶端的輔物件,包名,方法都是與服務端的遠端介面一致。
package com.rmi.remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiInterface extends Remote {
/**
* 遠端呼叫服務方法
*@Date 2017年8月2日
* @param name
* @return
* @throws RemoteException
*/
public String doService(String name) throws RemoteException;
/**
* 遠端呼叫sum方法
*@Date 2017年8月2日
* @param a
* @param b
* @return
* @throws RemoteException
*/
public int sum(int a, int b) throws RemoteException;
}
客戶端測試類:
package com.rmi.test;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import com.rmi.remote.RmiInterface;
public class Main {
public static void main(String[] args) {
try {
RmiInterface service = (RmiInterface) Naming.lookup("rmi://:8888/MyService");
System.out.println(service.doService("sb"));
System.out.println(service.sum(5, 8));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}
測試結果
客戶端輸出
服務端輸出
測試成功!