RMI入门篇

来源:互联网 发布:蓝月传奇龙魂升阶数据 编辑:程序博客网 时间:2024/05/19 16:35

本文章出处  http://lavasoft.blog.51cto.com/62575/91679

RMI的概念

RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外 一台计算机上的对象来获取远程数据。RMI是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。在过去,TCP/IP套接字通讯是远程通讯的主要手段,但此开发方式没有使用面向对 象的方式实现开发,在开发一个如此的通讯机制时往往令程序员感觉到乏味,对此RPC(Remote Procedure Call)应运而生,它使程序员更容易地调用远程程序,但在面对复杂的信息传讯时,RPC依然未能很好的支持,而且RPC未能做到面向对象调用的开发模 式。针对RPC服务遗留的问题,RMI出现在世人面前,它被设计成一种面向对象的通讯方式,允许程序员使用远程对象来实现通信,并且支持多线程的服务,这 是一次远程通讯的革命,为远程通信开辟新的里程碑。

 

RMI的开发步骤

  1. 先创建远程接口及声明远程方法,注意这是实现双方通讯的接口,需要继承Remote
  2. 开发一个类来实现远程接口及远程方法,值得注意的是实现类需要继承UnicastRemoteObject
  3. 把远程对象注册到rmi服务机上绑定URL
  4. 最后客户端查找远程对象,并调用远程方法

一 定义一个model
首先为服务建立一个Model层,注意因为此对象需要现实进行远程传输,所以必须继承Serializable
//注意对象必须继承Serializable  
public class PersonEntity implements Serializable {
/**

*/
private static final long serialVersionUID = 3419502472456341709L;
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public PersonEntity(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public PersonEntity() {
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PersonEntity other = (PersonEntity) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}


}

二  定义接口
/** 
* Created by IntelliJ IDEA. 
* User: admin 
* Date: 2008-8-7 21:50:02 
* 定义一个远程接口,必须继承Remote接口,其中需要远程调用的方法必须抛出RemoteException异常 
*/ 
public interface PersonService extends Remote{
/**

* @return
* @throws RemoteException
*/
 public List<PersonEntity> GetList() throws RemoteException;
}

建立PersonServiceImpl实现远程接口,注意此为远程对象实现类,需要继承UnicastRemoteObject
public class PersonServiceImpl extends UnicastRemoteObject implements PersonService {


private static final long serialVersionUID = 2287315087512423812L;
/**

* 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,因此这里默认的构造方法必须写,
* 必须声明抛出RemoteException异常

* @throws RemoteException
*/
public PersonServiceImpl() throws RemoteException {
}


/**
* 简单的业务方法
*/
@Override
public List<PersonEntity> GetList() throws RemoteException {
List<PersonEntity> personList = new LinkedList<PersonEntity>();
personList.add(new PersonEntity(0, "Leslie", 25));
personList.add(new PersonEntity(1, "Rose", 26));
return personList;
}


}


四 注册rmi服务暴露接口

public static void main(String[] args) {
// TODO Auto-generated method stub  
        try {  
            PersonService personService=new PersonServiceImpl();  
            //本地主机上的远程对象注册表Registry的实例,并指定端口为6600,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 
            //注册通讯端口  
            LocateRegistry.createRegistry(6600);  
            //注册通讯路径  
            //绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) 
//            Naming.bind("rmi://localhost:8888/RHello",rhello); 
//            Naming.bind("//localhost:8888/RHello",rhello); 
            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();  
        }  
}

五 客户端通过url 调远程方法

 先打包PersonService  接口和PersonEntity 放到客户端工程中

try {
// 调用远程对象,注意RMI路径与接口必须与服务器配置一致
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();
}
执行结果
ID:0 Age:25 Name:Leslie
ID:1 Age:26 Name:Rose
总结:
从上面的过程来看,RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。
这也是RMI的局限性之一。这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。
RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现。

更多信息
http://docs.huihoo.com/java/rmi/whitepage/index.html




原创粉丝点击