Java RMI 远程调用

本文详细介绍了RMI(远程方法调用)的实现过程,包括接口定义、服务端及客户端编程技巧,并提供了一种简化部署的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天看一天的RMI终于搞懂了,到底是怎么回事了。

RMI网上有很多说明,大概就是这样的。
  1、 编写并且编译接口的Java代码
  2、 编写并且编译接口实现的Java代码
  3、 从接口实现类中生成 Stub 和 Skeleton 类文件
  4、 编写远程服务的主运行程序
  5、 编写RMI的客户端程序
  6、 安装并且运行RMI系统

先讲一种网上最常见的(参考资料来源Java RMI Tutorial)
首先编写服务断对外提供的接口,必须继承 java.rmi.Remote。
接口代码如下:

import java.rmi.*;
/**
* Remote Interface for the "Hello, world!" example.
*/
public interface HelloInterface extends Remote {
/**
* Remotely invocable method.
* @return the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the remote invocation fails.
*/
public String say() throws RemoteException;
}


再来就是对该接口的实现,这里有两种方式(一种是必须实现该接口,必继承java.rmi.server.UnicastRemoteObject,另一种是只实现该接口,但是必须调用UnicastRemoteObject.exportObject方法),采用第一种代码如下:

import java.rmi.*;
import java.rmi.server.*;
/**
* Remote Class for the "Hello, world!" example.
*/
public class Hello extends UnicastRemoteObject implements HelloInterface {
private String message;
/**
* Construct a remote object
* @param msg the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the object handle cannot be constructed.
*/
public Hello (String msg) throws RemoteException {
message = msg;
}
/**
* Implementation of the remotely invocable method.
* @return the message of the remote object, such as "Hello, world!".
* @exception RemoteException if the remote invocation fails.
*/
public String say() throws RemoteException {
return message;
}
}

分别编译文件。

编译完成后,要从接口实现类中生成 Stub 和 Skeleton 类文件,这时就要用到
rmic Hello
命令,如果出现错误,请讲Hello.class的路径设置到classpath路径下。

然后编写客户器端代码:
  /**
* Client program for the "Hello, world!" example.
* @param argv The command line arguments which are ignored.
*/
public static void main (String[] argv) {
try {
HelloInterface hello =
(HelloInterface) Naming.lookup ("//172.0.0.1/Hello");
System.out.println (hello.say());
} catch (Exception e) {
System.out.println ("HelloClient exception: " + e);
}
}

然后编译。

然后编写服务端代码,

/**
* Server program for the "Hello, world!" example.
* @param argv The command line arguments which are ignored.
*/
public static void main (String[] argv) {
try {
Naming.rebind ("Hello", new Hello ("Hello, world!"));
System.out.println ("Hello Server is ready.");
} catch (Exception e) {
System.out.println ("Hello Server failed: " + e);
}
}

然后编译,

开始启动服务器,这里是最麻烦的,
首先开启RMI Registry(注册表),
输入命令行:rmiregistry &
完成后放在一边保持不动,重新开启一个终端。
然后运行:
java HelloServer &
完成后放在一边保持不动,再重新开启一个终端。
最后再
java HelloClient。
终于成功显示。

这样太麻烦了,还容易出错,有没有简单方法呢?
有下面 我就来介绍介绍:
前面还是一样的,我重新写了代码:如下

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

public interface TestInterfactRemote extends Remote {

public String echo(String message) throws RemoteException;
}

import java.rmi.RemoteException;

public class TestInterfaceRemoteImpl implements TestInterfactRemote {

public String echo(String message) throws RemoteException {
if("quit".equalsIgnoreCase(message.toString())){
System.out.println("Server will be shutdown");
System.exit(0);
}
System.out.println("Message from client:"+ message);
return "server response" + message;
}
}


不同的地方在于服务端和客户端,仔细看:

public class Server {
public Server() {
try {
int port = 9527;
String name = "testDemo";
TestInterfactRemote testInterfactRemote = new TestInterfaceRemoteImpl();
//完成对象的绑定
UnicastRemoteObject.exportObject(testInterfactRemote, port);
//完成注册表的开启
Registry registry = LocateRegistry.createRegistry(1099);
//这里没有用Naming绑定,运用的是registry提供的绑定方法
registry.rebind(name, testInterfactRemote);
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args[]) {
new Server();
}
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import test.TestInterfactRemote;

public class Client {
public static void main(String args[]) {
try {
//获得登记注册表的位置
Registry registry = LocateRegistry.getRegistry("localhost");
String name = "testDemo";
//运用注册表进行对象的查找
TestInterfactRemote testInterfactRemote = (TestInterfactRemote) registry.lookup(name);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
String reponse = testInterfactRemote.echo(input);
System.out.println(reponse);
} catch (Exception e) {
e.printStackTrace();
}
}
}


直接编译完成后运行试试结果是怎么样的?

这样很简单吧!又好理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值