Java RMI

Java Rmi


目录
1 JAVA RMI 1
1.1 RMI简介 1
2 JAVA RMI的实现 1
2.1 JAVA RMI简单实现 1

1 Java RMI
1.1 RMI简介
Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。

RMI的工作原理:正常情况下,在同一个Java虚拟机中一个对象调用另一个对象的方法,要向该方法传递对象参数,以及获取方法返回值对象,这些都可以通过引用(指向Java虚拟机内存中的对象)来完成,这称为传引用。但是RMI远程调用方法是在不同虚拟机中来完成方法调用,这种传值方法就不适用了。因为不同Java虚拟机中同一个引用值指向的对象是不一样的,同时也可能不同的虚拟机引用的实现方式完全不同和不兼容。
因此为了实现向远程方法传递参数和获取远程方法返回结果,可以使用三种机制来实现,这取决于所传递的数据类型:
简单数据类型(int,Boolean,double等)是按值传递来完成的,这和本地java方法调用的值传递一样。
远程对象的引用(即实现了Remote接口的对象)是以远程引用(Remote Reference)传递来完成的,即允许接收方调用远程对象上的方法。这与本地java方法调用传递对象引用有些相似。
没有实现Remote接口的对象是按值来传递的,即通过对象序列化来传递整个对象的副本。
Java Rmi的通信机制就是根据上面传递机制来实现的。

2 JAVA RMI的实现
要实现RMI远程对象调用需要大部分类都在java.rmi,java.rmi.server和java.rmi.registry包中。
Java.rmi包定义了客户端所见的类,接口和异常。
Java.rmi.server包定义了服务器端可见的类,接口和异常。
Java.rmi.registry包定义了用于查找和命名远程对象的类,接口和异常。

2.1 Java RMI简单实现
HelloRmi:rmi服务接口
HelloRmiImpl:rmi服务实现类
Server:RMI服务器端类
Client:RMI客户端类

HelloRmi实现如下:

package com.rmi;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
* 定义一个rmi服务接口,rmi接口必须继承Remote接口,
* 其中需要远程调用的方法必须抛出RemoteException异常
* @author xmong
*/
public interface HelloRmi extends Remote{

/**
* 简单实现的say hi方法
* @param name
* @return
* @throws RemoteException
*/
public String sayHi(String name) throws RemoteException;

}


HelloRmiImpl实现如下:


package com.rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
* rmi接口实现,rmi实现继承了UnicastRemoteObject类,
* UnicastRemoteObject类提供了很多支持远程调用的方法。
* @author xmong
*/
public class HelloRmiImpl extends UnicastRemoteObject implements HelloRmi{



/**
* 序列化对象
*/
private static final long serialVersionUID = 1L;


/**
* 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,
* 因此这里默认的构造方法必须写,必须声明抛出RemoteException异常
* @throws RemoteException
*/
protected HelloRmiImpl() throws RemoteException {
super();
}

/**
* 传入一个客户端名称字符串,对该名称问候,输出客户端名称和 ip
* 返回客户端名称“Server”
*/
@Override
public String sayHi(String name) throws RemoteException{
try {
//UnicastRemoteObject的getClientHost()获取客户端主机名
System.out.println("Server: Hi "+name+" "+getClientHost());
} catch (ServerNotActiveException e) {
e.printStackTrace();
}
return "Server";
}

}


Server实现如下:

package com.rmi;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/**
* 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。
* @author xmong
*/
public class Server {


public static void main(String[] args) {

try {
//创建远程服务对象
HelloRmi hr = new HelloRmiImpl();
/**
* 在本机上注册远程服务端口9999,这一步必不可少,
* 缺少注册表创建,则无法绑定远程服务对象到远程注册表上 ,启动时会抛出Connection refused异常。
* java默认端口为1099,可以通过Registry.REGISTRY_PORT来获取这个值
*/

LocateRegistry.createRegistry(9999);
/**
* 把远程服务对象注册到服务器上命名为:hello
* /绑定的URL标准格式为:rmi://host:port/name
* 其中协议名可以省略,即[rmi:]可以省去
*/
Naming.bind("rmi://localhost:9999/hello", hr);
System.out.println("Rmi Server bind success");
} catch (RemoteException e) {
System.out.println("创建远程服务对象异常!");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("绑定远程URL发生异常!");
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println("发生重复绑定异常!");
e.printStackTrace();
}

}
}

Client实现如下:

package com.rmi;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/**
* 客户端测试,客户端远程访问服务对象方法。
* @author xmong
*/
public class Client {


public static void main(String[] args) {
try {
/**
* 在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法
*/
HelloRmi hr = (HelloRmi)Naming.lookup("rmi://localhost:9999/hello");
//调用服务方法
System.out.println("Client: Hi "+hr.sayHi("Client"));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}



执行结果如下:
运行Server
Server输出:
Rmi Server bind success

运行Client
Client输出:
Client: Hi Server

Server输出:
Server: Hi Client 172.30.39.227
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值