3 分钟
Java远程方法调用
一、HelloWord
1、代码目录结构
.
├── client
│ └── HelloClient.java
├── server
│ ├── HelloImpl.java
│ └── HelloServer.java
└── service
└── Hello.java
2、远程方法接口
远程方法调用的接口,继承Remote标记接口。客户端服务端都应该加载此接口。
在此接口定义需要的方法
service/Hello.java
package service;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
public String sayHello(String name) throws RemoteException;
}
3、服务端接口的实现和服务器的搭建
服务端对远程方法调用的接口的实现类(此类仅需要服务端加载)
server/HelloImpl.java
package server;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import service.Hello;
public class HelloImpl extends UnicastRemoteObject implements Hello {
private static final long serialVersionUID = -271947229644133464L;
public HelloImpl() throws RemoteException{
super();
}
public String sayHello(String name) throws RemoteException {
return "Hello,"+name;
}
}
服务器的实现(对远程方法对象的注册)
server/HelloServer.java
package server;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import service.Hello;
public class HelloServer {
public static void main(String[] args) {
try{
Hello h = new HelloImpl();
//创建并导出接受指定port请求的本地主机上的Registry实例。
LocateRegistry.createRegistry(12312);
/** Naming 类提供在对象注册表中存储和获得远程对远程对象引用的方法
* Naming 类的每个方法都可将某个名称作为其一个参数,
* 该名称是使用以下形式的 URL 格式(没有 scheme 组件)的 java.lang.String:
* //host:port/name
* host:注册表所在的主机(远程或本地),省略则默认为本地主机
* port:是注册表接受调用的端口号,省略则默认为1099,RMI注册表registry使用的著名端口
* name:是未经注册表解释的简单字符串
*/
//Naming.bind("//host:port/name", h);
Naming.bind("rmi://localhost:12312/Hello", h);
System.out.println("HelloServer启动成功");
}catch(Exception e){
e.printStackTrace();
}
}
}
4、客户端的搭建
client/Client.java
package client;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import service.Hello;
public class HelloClient {
public static void main(String[] args) {
try {
Hello h = (Hello)Naming.lookup("rmi://localhost:12312/Hello");
System.out.println(h.sayHello("zx"));
} catch (MalformedURLException e) {
System.out.println("url格式异常");
} catch (RemoteException e) {
System.out.println("创建对象异常");
e.printStackTrace();
} catch (NotBoundException e) {
System.out.println("对象未绑定");
}
}
}
5、编译HelloWorld
#进入项目目录
javac ./*/*.java
6、运行测试HelloWorld
打开另个终端,在一个终端上启动服务器
java server.HelloServer
在另一个终端启动服务端
java client.HelloClient
7、另一种方式注册表单独运行
以上代码server/HelloServer.java
中,LocateRegistry.createRegistry(12312); 是创建并运行注册表程序。还有另一种方式,让注册表程序独立运行
添加文件server/HelloServer2.java
如下
package server;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import service.Hello;
public class HelloServer2 {
public static void main(String[] args) {
try{
Hello h = new HelloImpl();
//创建并导出接受指定port请求的本地主机上的Registry实例。
//LocateRegistry.createRegistry(12312);
/** Naming 类提供在对象注册表中存储和获得远程对远程对象引用的方法
* Naming 类的每个方法都可将某个名称作为其一个参数,
* 该名称是使用以下形式的 URL 格式(没有 scheme 组件)的 java.lang.String:
* //host:port/name
* host:注册表所在的主机(远程或本地),省略则默认为本地主机
* port:是注册表接受调用的端口号,省略则默认为1099,RMI注册表registry使用的著名端口
* name:是未经注册表解释的简单字符串
*/
//Naming.bind("//host:port/name", h);
Naming.bind("rmi://localhost:12312/Hello", h);
System.out.println("HelloServer启动成功");
}catch(Exception e){
e.printStackTrace();
}
}
}
编译
javac server/HelloServer2.java
运行服务端注册表程序(必须先执行,而且不能关闭)
rmiregistry 12312
运行服务端程序
java server.HelloServer2
运行客户端程序
java client.HelloClient
二、相关类和接口
1、Remote
java.rmi.Remote
一个标记接口,所有远程方法接口必须继承自此接口
2、Naming
java.rmi.Naming
(1)常用方法
static void bind(String name, Remote obj)
将指定 name 绑定到远程对象。static String[] list(String name)
返回在注册表中绑定的名称所组成的数组。static Remote lookup(String name)
返回与指定 name 关联的远程对象的引用(一个 stub)。static void rebind(String name, Remote obj)
将指定名称重新绑定到一个新的远程对象。static void unbind(String name)
销毁与远程对象关联的指定名称的绑定。
3、UnicastRemoteObject
服务器端实现远程方法接口必须继承此方法