前言
最近的聯通項目,下一階段可能會涉及到和各省間的RMI接口,所以總結一下08年中國移動自動撥測系統用到的RMI技術,以備不時之需。同時也給廣大初哥提供一些學習資料,哈哈。前幾年,一直忙於項目,沒怎麼做系統總結。以後計劃寫一些以前項目用過的Java分布式技術實例教程,如:RMI、 Socket、Mina、SNMP、SOAP、Web Service、Hessian、JMS等。希望和大家一起交流,分享經驗,一起提高。
RMI簡介
RMI,遠程方法調用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java應用程序的方便途徑。RMI是非常容易使用的,但是它非常的強大。
RMI的基礎是接口,RMI構架基於一個重要的原理:定義接口和定義接口的具體實現是分開的。看看jboss-remoting:
基本原理
要實現網絡機器間的通訊,首先得來看看計算機系統網絡通信的基本原理,在底層層面去看,網絡通信需要做的就是將流從一台計算機傳輸到另外一台計算機,基於傳輸協議和網絡IO來實現,其中傳輸協議比較出名的有http、tcp、udp等等,http、tcp、udp都是在基於Socket概念上為某類應用場景而擴展出的傳輸協議,網絡IO,主要有bio、nio、aio三種方式,所有的分布式應用通訊都基於這個原理而實現,只是為了應用的易用,各種語言通常都會提供一些更為貼近應用易用的應用層協議。
主要步驟
分為以下幾個步驟:
1. 創建遠程接口及聲明遠程方法(RmiMonitorService.Java)
2. 實現遠程接口及遠程方法(繼承UnicastRemoteObject)(RmiMonitorServiceImpl.Java)
3. 啟動RMI注冊服務,並注冊遠程對象(RmiServer.Java)
4. 客戶端查找遠程對象,並調用遠程方法(MonitorClIEnt.Java)
5. 運行實例
業務場景
在移動撥測系統管理端中要融合實時顯示。簡單點說就是設備出現告警時,要采用不同方式實時展示。如Web界面(AJax)、GIS等。
主要業務流程設計:
1. 設備告警
2. 調用RMI ClIEnt
3. 調用RMI Server
4. 調用業務處理接口
5. 告警信息入庫
6. 實時顯示(AJax,Gis等技術)
技術設計
接口函數函數名稱: int interactive( int funindex, string param )
參數說明:
funindex 功能號,整型。1為設備告警
param 交互參數,字符串型。
返回:
成功=1,失敗=0。
說明:
param交互參數用鍵值對組成,每個鍵值對以“&”分割,如:Tsid=01&devid=002&warnid=102&warntype=01&warnlevel=1 。
測試點ID(tsid)
設備ID(devid)
告警ID(warnid)
告警類型(warntype)
告警級別(warnlevel)
代碼實現
廢話少說,上代碼,為了演示方便,經過整理,省去了很多get,set之類的東東還有業務的東西以及Spring相關的東西。
Java代碼
RmiMonitorService.Java
package nbpt.ts.manager.message.service;
import Java.rmi.Remote;
import Java.rmi.RemoteException;
/**
* Description: 實時顯示RMI服務接口。
*
* RMI接口必須擴展接口Java.rmi.Remote
*
* @author Peter Wei
* @version 1.0 Feb 25, 2009
*/
public interface RmiMonitorService extends Remote {
/**
* 實時顯示對外接口
*
* @param funindex
* 功能號
* @param param
* 鍵名列表,也就是實際傳輸的內容
* @return
* @throws RemoteException
* 遠程接口方法必須拋出Java.rmi.RemoteException
*/
public int interactive(int funindex, String param) throws RemoteException;
}
RmiMonitorServiceImpl.Java
package nbpt.ts.manager.message.service.impl;
import Java.rmi.RemoteException;
import Java.rmi.server.UnicastRemoteObject;
// import nbpt.ts.manager.base.util.AppContext;
import nbpt.ts.manager.message.service.RmiMonitorService;
import nbpt.ts.manager.message.service.WarnService;
/**
* Description: 實時顯示RMI接口實現。
*
* 實現RMI接口及遠程方法(繼承UnicastRemoteObject)
*
* @author Peter Wei
* @version 1.0 Feb 25, 2009
*/
public class RmiMonitorServiceImpl extends UnicastRemoteObject implements
RmiMonitorService {
private static final long serialVersionUID = -3771656108378649574L;
public static final int SUCCSS = 1;
public static final int FAIL = 0;
public WarnService warnService;
/**
* 必須定義構造方法,因為要拋出RemoteException異常
*
* @throws RemoteException
*/
public RmiMonitorServiceImpl() throws RemoteException {
super();
}
public int interactive(int funindex, String param) throws RemoteException {
int result = FAIL;
switch (funindex) {
// 告警
case (1): {
// warnService = (WarnService) AppContext.getAppContext().getBean(
// “warn.warnService”);
// 實際應用是從Spring應用中獲取告警Service,如上代碼
warnService = new WarnServiceImpl();
// 網絡告警的業務操作
warnService.dealWarn(param);
result = SUCCSS;
}
break;
case (2):
// do other biz
break;
}
// 。..。..
return result;
}
public WarnService getWarnService() {
return warnService;
}
public void setWarnService(WarnService warnService) {
this.warnService = warnService;
}
}
RmiServer.Java
package nbpt.ts.manager.message.service;
import Java.Net.MalformedURLException;
import Java.rmi.AlreadyBoundException;
import Java.rmi.Naming;
import Java.rmi.RemoteException;
import Java.rmi.registry.LocateRegistry;
import nbpt.ts.manager.message.service.impl.RmiMonitorServiceImpl;
/**
* Description: RMI服務端。
*
* @author Peter Wei
* @version 1.0 Feb 25, 2009
*/
public class RmiServer {
public String ip = “localhost”;
public int port = 8889;
/**
* 啟動RMI注冊服務,並注冊遠程對象。實際應用中是在Spring初始化並啟動
*/
public void init() {
try {
LocateRegistry.createRegistry(port);
// 創建一個遠程對象
RmiMonitorService comm = new RmiMonitorServiceImpl();
Naming.bind(“//” + ip + “:” + port + “/comm”, comm);
} catch (RemoteException e) {
System.out.println(“創建遠程對象發生異常!” + e.toString());
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println(“發生重復綁定對象異常!” + e.toString());
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println(“發生URL畸形異常!” + e.toString());
e.printStackTrace();
}
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public static void main(String[] args) {
// 實際應用中是在Spring初始化並啟動
RmiServer rmiServer = new RmiServer();
System.out.println(“RMI服務初始化:”);
rmiServer.init();
}
}
MonitorClIEnt.Java
package nbpt.ts.manager.message.service;
import Java.Net.MalformedURLException;
import Java.rmi.Naming;
import Java.rmi.NotBoundException;
import Java.rmi.RemoteException;
/**
* Description: RMI客戶端。
*
* @author Peter Wei
* @version 1.0 Feb 25, 2009
*/
public class MonitorClIEnt {
public RmiMonitorService monitorService;
public String ip = “localhost”;
public int port = 8889;
public int interactive(int funindex, String param) {
int result = 0;
try {
getMonitorService().interactive(funindex, param);
result = 1;
} catch (RemoteException e) {
e.printStackTrace();
}
return result;
}
public RmiMonitorService getMonitorService() {
try {
// 在RMI服務注冊表中查找名稱為RmiMonitorService的對象,並調用其上的方法
monitorService = (RmiMonitorService) Naming.lookup(“rmi://” + ip
+ “:” + port + “/comm”);
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
return monitorService;
}
public static void main(String args[]) throws RemoteException {
MonitorClient client = new MonitorClIEnt();
System.out.println(“發送告警信息:”);
String msg = “tsid=1022&devid=10001027&warnid=102&warntype=01&warnlevel=1&warnmsg=設備出錯,請檢查。”;
System.out.println(clIEnt.getValue(msg, “warnmsg”));
clIEnt.interactive(1, msg);
}
public String getValue(String content, String key) {
String value = “”;
int begin = 0, end = 0;
begin = content.indexOf(key + “=”);
end = content.indexOf(“&”, begin);
if (end == -1)
end = content.length();
value = content.substring(begin + key.length() + 1, end);
return value;
}
}
WarnService.Java
package nbpt.ts.manager.message.service;
/**
* Description: 告警服務
*
* @author Peter Wei
* @version 1.0 2010-8-22
*/
public interface WarnService {
/**
* 處理告警:告警來時的業務操作,實際操作是解析消息存庫,然後界面AJax定時刷新數據,獲取實時告警展示
*
* @param message
* @return
*/
public int dealWarn(String message);
}
WarnServiceImpl.Java
package nbpt.ts.manager.message.service.impl;
import nbpt.ts.manager.message.service.WarnService;
/**
* Description: 告警服務
*
* @author Peter Wei
* @version 1.0 2010-8-22
*/
public class WarnServiceImpl implements WarnService {
public int dealWarn(String message) {
// 告警處理方法
System.out.println(“已接收網絡告警”);
// …
return 1;
}
}