spring封裝了rmi後,使我們得到幾點便利:
不用調用rmic編譯stub和skeleton
不用直接實現remote介面
不需要啟動命名服務rmiregistry
但,卻不支援原來rmi的回調功能。查閱許多網頁也不得其解。
今天,想到一招,共用出來,如果大家有好辦法歡迎回貼共用。
正常做法是:
回調一般是用在一群client端需要server來通知的情況,一般server就用Vector來儲存client對象。
server端需要提供一個方法,client把對象傳過來後,儲存到Vector中,以後就可以通知client們了:
register (ClientObject obj);
在spring裡,基本做法是一樣的,唯一不同是,在這個方法裡,client不能傳對象,我們就傳一個client提供出來的rmi對象的url:
register(String url);
在client端,就如正常使用先獲得server對象,再調用這個方法,注意組成url的代碼:
NodeService service = (NodeService) factory.getAPIObject("nodeServiceProxy");
String name = null;
try {
name = "rmi://" + InetAddress.getLocalHost().getHostName() + "/NodeNotifyService";
} catch (Exception ue) {}
int result = service.registerFlower (name);
logger.info ("result="+result);
在server端registerFlower處理裡,根據url動態建立這個對象,代碼如下:
public class NodeServiceImpl implements NodeService {
public static final Logger logger = LoggerFactory.getLogger(NodeServiceImpl.class);
public NodeNotifyService service = null;
public int registerFlower (String url) {
logger.info (url);
RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
rmiProxyFactoryBean.setServiceInterface(NodeNotifyService.class);
logger.info ("begin set url");
rmiProxyFactoryBean.setServiceUrl(url);
try {
logger.info ("begin set");
rmiProxyFactoryBean.afterPropertiesSet();
} catch (Exception ex) {
logger.info ("exception");
}
if (rmiProxyFactoryBean.getObject() instanceof NodeNotifyService) {
service = (NodeNotifyService) rmiProxyFactoryBean.getObject();
}
return 0;
}
}
這樣就從url轉換成client對象了,當然了,還是需要在client和server各自設定檔裡配置RmiServiceExporter,這一步很簡單,和正常的spring的rmi是一樣的了。
做到這步後,我還想把所有介面檔案放到一個JAR裡,client和server的實現,以及各自邏輯放到各自的JAR中,這樣各自改實現就不需要兩邊更新包。改介面的話,就更新介面所在JAR。不知道這樣安排是否合理?