|
I的概念
RMI(Remote Method
Invocation)遠(yuǎn)程方法調(diào)用是一種計算機之間利用遠(yuǎn)程對象互相調(diào)用實現(xiàn)雙方通訊的一種通訊機制。使用這種機制,某一臺計算機上的對象可以調(diào)用另外
一臺計算機上的對象來獲取遠(yuǎn)程數(shù)據(jù)。RMI是Enterprise
JavaBeans的支柱,是建立分布式Java應(yīng)用程序的方便途徑。在過去,TCP/IP套接字通訊是遠(yuǎn)程通訊的主要手段,但此開發(fā)方式?jīng)]有使用面向?qū)?象的方式實現(xiàn)開發(fā),在開發(fā)一個如此的通訊機制時往往令程序員感覺到乏味,對此RPC(Remote Procedure
Call)應(yīng)運而生,它使程序員更容易地調(diào)用遠(yuǎn)程程序,但在面對復(fù)雜的信息傳訊時,RPC依然未能很好的支持,而且RPC未能做到面向?qū)ο笳{(diào)用的開發(fā)模
式。針對RPC服務(wù)遺留的問題,RMI出現(xiàn)在世人面前,它被設(shè)計成一種面向?qū)ο蟮耐ㄓ嵎绞剑试S程序員使用遠(yuǎn)程對象來實現(xiàn)通信,并且支持多線程的服務(wù),這
是一次遠(yuǎn)程通訊的革命,為遠(yuǎn)程通信開辟新的里程碑。
RMI的開發(fā)步驟
- 先創(chuàng)建遠(yuǎn)程接口及聲明遠(yuǎn)程方法,注意這是實現(xiàn)雙方通訊的接口,需要繼承Remote
- 開發(fā)一個類來實現(xiàn)遠(yuǎn)程接口及遠(yuǎn)程方法,值得注意的是實現(xiàn)類需要繼承UnicastRemoteObject
- 通過javac命令編譯文件,通過java -server 命令注冊服務(wù),啟動遠(yuǎn)程對象
- 最后客戶端查找遠(yuǎn)程對象,并調(diào)用遠(yuǎn)程方法
簡單實例
首先為服務(wù)建立一個Model層,注意因為此對象需要現(xiàn)實進(jìn)行遠(yuǎn)程傳輸,所以必須繼承Serializable
- package rmi.model;
- import java.io.Serializable;
- //注意對象必須繼承Serializable
- public class PersonEntity implements Serializable {
- private int id;
- private String name;
- private int age;
- public void setId(int id) {
- this.id = id;
- }
- public int getId() {
- return id;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public int getAge() {
- return age;
- }
- }
創(chuàng)建遠(yuǎn)程接口PersonService,注意遠(yuǎn)程接口需要繼承Remote
- package rmi.service;
- import java.rmi.Remote;
- import java.rmi.RemoteException;
- import java.util.List;
- import rmi.model.*;
- //此為遠(yuǎn)程對象調(diào)用的接口,必須繼承Remote類
- public interface PersonService extends Remote {
- public List<PersonEntity> GetList() throws RemoteException;
- }
建立PersonServiceImpl實現(xiàn)遠(yuǎn)程接口,注意此為遠(yuǎn)程對象實現(xiàn)類,需要繼承UnicastRemoteObject
- package rmi.serviceImpl;
- import java.rmi.RemoteException;
- import java.rmi.server.UnicastRemoteObject;
- import java.util.LinkedList;
- import java.util.List;
- import rmi.model.PersonEntity;
- import rmi.service.*;
- //此為遠(yuǎn)程對象的實現(xiàn)類,須繼承UnicastRemoteObject
- public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {
- public PersonServiceImpl() throws RemoteException {
- super();
- // TODO Auto-generated constructor stub
- }
- @Override
- public List<PersonEntity> GetList() throws RemoteException {
- // TODO Auto-generated method stub
- System.out.println("Get Person Start!");
- List<PersonEntity> personList=new LinkedList<PersonEntity>();
-
- PersonEntity person1=new PersonEntity();
- person1.setAge(25);
- person1.setId(0);
- person1.setName("Leslie");
- personList.add(person1);
-
- PersonEntity person2=new PersonEntity();
- person2.setAge(25);
- person2.setId(1);
- person2.setName("Rose");
- personList.add(person2);
-
- return personList;
- }
-
- }
建立服務(wù)器端,在服務(wù)器端注冊RMI通訊端口與通訊路徑,然后通訊javac命令編譯文件,通過java -server
命令注冊服務(wù)。以下面代碼為例,如果閣下將項目建立于D://RMI/RemotingService文件夾上時,則先輸入D://RMI
/RemotingService/src>javac
rmi/remotingservice/Program.java獲取Program.class(如何閣下使用的MyEclipse等開發(fā)工具,可跳
過此步,直接在*/bin文件夾中直接調(diào)用已經(jīng)生成的Program.class),然后輸入D://RMI/RemotingService
/src>java rmi/remotingservice/Program啟動服務(wù)。
- package rmi.remotingservice;
- import java.rmi.Naming;
- import java.rmi.registry.LocateRegistry;
-
- import rmi.service.*;
- import rmi.serviceImpl.*;
- public class Program{
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- try {
- PersonService personService=new PersonServiceImpl();
- //注冊通訊端口
- LocateRegistry.createRegistry(6600);
- //注冊通訊路徑
- Naming.rebind("rmi://127.0.0.1:6600/PersonService", personService);
- System.out.println("Service Start!");
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
最后建立客戶端進(jìn)行測試,注意客戶調(diào)用的RMI路徑必須服務(wù)器配置一致
- package rmi.remotingclient;
- import java.rmi.Naming;
- import java.util.List;
- import rmi.model.PersonEntity;
- import rmi.service.*;
- public class Program {
- public static void main(String[] args){
- try{
- //調(diào)用遠(yuǎn)程對象,注意RMI路徑與接口必須與服務(wù)器配置一致
- PersonService personService=(PersonService)Naming.lookup("rmi://127.0.0.1:6600/PersonService");
- List<PersonEntity> personList=personService.GetList();
- for(PersonEntity person:personList){
- System.out.println("ID:"+person.getId()+" Age:"+person.getAge()+" Name:"+person.getName());
- }
- }catch(Exception ex){
- ex.printStackTrace();
- }
- }
- }
常見錯誤
- 在命令提示符調(diào)用java命令時,顯示并無此命令。這是因為未在“環(huán)境變量”中綁定JAVA的JDK命令造成的,你首先單擊“計算機右
鍵”->“屬性”->“高級”->“環(huán)境變量”。在系統(tǒng)變量Path設(shè)置中加載為JDK的路徑 .;D:/Program
Files/Genuitec/Common/binary/com.sun.java.jdk.win32.x86_1.6.0.013/bin。然后
在ClassPath加載服務(wù)器端的Program.class地址 .;D://RMI/RemotingService/bin
- 在調(diào)用javac命令時出現(xiàn)“javac 找不到文件 ..... ”此錯誤,可能是因為閣下輸入的文件路徑出現(xiàn)錯誤造成,注意不要把D://RMI/RemotingService/src>javac rmi/
remotingservice/
Program.java寫錯為D://RMI/RemotingService/src>javac rmi.
remotingservice.
Program.java
- 在調(diào)用D://RMI/RemotingService/bin>java
rmi/remotingservice/Program命令時出現(xiàn)“Exception in thread 'main'
java.lang.NoClassEdfoundError”錯誤,第一這可能是閣下把Program
錯寫為Program.class
,注意java命令不需要加后綴名。第二可能是閣下把“java rmi/
remotingservice/
Program”錯寫為“java rmi/
remotingservice/
Program"。
原代碼
(下載
)
|