RMI(Remote Method Invocation),遠程方法調用。使得客戶端的程序可以遠程調用服務器中的對象實現遠程方法調用的函數接口。接觸到這個是在做手寫實現一個簡單的分佈式系統的時候。簡單記錄一下用RMI實現的第一個例子sayHello。
1.概述
RMI總的來講有就三個部件,Server端,Client端,還是一個負責完成註冊。
過程是這樣的,可以被調用的對象先在服務器上進行註冊,並和端口綁定。
在本機創建註冊表實例並且綁定端口用來接收客戶端發送過來的請求。客戶端功能實現,遠程調用方法。
step1
定義一個遠程接口,定義client可以調用的函數,繼承remote:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloRmi extends Remote{
public String sayHello(String name)throws RemoteException;
}
step2
定義一個遠程類,實現上面提到的遠程調用的函數;
import java.rmi.RemoteException;
public class HelloRmilmpl implements HelloRmi{
public HelloRmilmpl()throws RemoteException{
super();
}
@Override //覆蓋原來的sayHello函數
public String sayHello(String name) throws RemoteException {
System.out.println(name+" call rmi!");
return name+"say:hello this is rmi";
}
private static final long serialVersionUID=1L;
}
step3
寫服務器端Server的程序:
package com.rmi;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import com.rmi.HelloRmilmpl;
public class RMIServer {
public static void main(String[] args) {
try{
HelloRmi hello=new HelloRmilmpl();//具備遠程函數的遠程類
HelloRmi stub=(HelloRmi) UnicastRemoteObject.exportObject(hello,9999);//導出遠程對象並且在服務器本地保留一個存根stub,方便客戶端的調用和訪問,這個端口用來接收遠程方法調用
LocateRegistry.createRegistry(1099);//註冊表接收請求端口爲1099
Registry registry=LocateRegistry.getRegistry();//默認註冊表端口1099的本地主機的遠程對象
registry.bind("hellow",stub);//將對象和一個名字進行綁定,客戶端通過這個名字來訪問
System.out.println("綁定成功");
}catch (RemoteException e){
e.printStackTrace();
}catch (AlreadyBoundException e){
e.printStackTrace();
}
}
}
step4
client端:
package com.rmi;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIClient {
public static void main(String[] args) {
try{
Registry registry= LocateRegistry.getRegistry("localhost");//返回註冊表註冊爲localhost
HelloRmi hello=(HelloRmi) registry.lookup("hellow");//在註冊表中查找名爲hellow的遠程對象,並且返回這個遠程對象在服務器中的存根
String ret = hello.sayHello("111 ");
System. out.println(ret);
}catch(RemoteException e){
e.printStackTrace();
}catch(NotBoundException e){
e.printStackTrace();
}
}
}
step5
開始演示一下,首先開啓服務器Server
開啓client
調用了遠程類的sayHello,實現了輸出。
這時候可以再看一下服務器端的狀態:
服務器當中記錄下了這個sayHello過程的執行經過。
step6(10.23更新)
在原來只有一個遠程類和工頭請求調用遠程函數的基礎上,在服務器上面寫成了遠程類列表,工頭處申請兩個訪問,距離最終目的還是會有不少的距離,但是也還是有一些進展。
記錄一下更改的內容:
Server端更改:
ArrayList<HelloRmi> hel=new ArrayList<HelloRmi>();
ArrayList<HelloRmi> stub=new ArrayList<HelloRmi>();
ArrayList<HelloRmi> s;
int mypor=9880;
LocateRegistry.createRegistry(1099);
Registry registry=LocateRegistry.getRegistry();
for (int i=0;i<10;i++){
hel.add(new HelloRmilmpl());
HelloRmi temp=hel.get(i);
stub.add((HelloRmi)UnicastRemoteObject.exportObject(temp,mypor++));
registry.bind("hellow"+i,stub.get(i));
System.out.println("worker"+(i+1)+"綁定成功,port:"+(mypor-1));
}
client端更改:
Registry registry= LocateRegistry.getRegistry("localhost");
HelloRmi hello=(HelloRmi) registry.lookup("hellow1");
String ret = hello.sayHello("Hello111 ");
System. out.println(ret);
HelloRmi hello1=(HelloRmi) registry.lookup("hellow2");
String ret1 = hello.sayHello("Hello222 ");
System. out.println(ret1);
這裏直接定義了兩個工頭來進行調用遠程方法。