今天看一天的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();
}
}
}
直接编译完成后运行试试结果是怎么样的?
这样很简单吧!又好理解。