Rmi远程服务调用简述

RMI是什么

RMI(Remote Method Invocation)意为远程方式调用,顾名思义,是Java版的RPC实现技术,是建立分布式Java应用程序的方便途径。RMI是基于接口的,一般是接口定义和实现分开在不同的工程中。

相似:Hessian,Burlap,Httpinvoker,webservice

为什么使用RMI

它允许运行在一台虚拟机上的方法调用运行在另一台虚拟机上的对象方法,这样可以让每个任务运行在更适合的虚拟机上。

RMI怎么用

  • 定义一个java.rmi.Remote的子接口,也就是定义一个接口AnimalService,继承自Remote,接口中的所有方法必须显式的抛出java.rmi.RemoteException异常,否则服务会注册失败,谨记!
  • 创建AnimalService的实现类DogServiceImpl,这个类需要继承java.rmi.server.UnicastRemoteObject
  • 将服务AnimalService注册到rmi中心
  • 客户端引用接口定义jar包
  • 客户端获取AnimalService的远程服务
  • 进行相关方法调用

缺点

因为RMI是Java版的RPC通讯技术,所以他只适用于Java程序上,如果想跨语言通讯,那就只能另谋它法了

代码

  • 接口(工程:rmi-api)
1
2
3
4
5
6
7
8
9
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface AnimalService extends Remote {

// 接口中所有的方法必须声明throws RemoteException
void laugh() throws RemoteException;

}
  • 实现(工程:rmi-service)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import cc.kevinlu.spidemo.spi.AnimalService;

public class DogServiceImpl extends UnicastRemoteObject implements AnimalService {

protected DogServiceImpl() throws RemoteException {
super();
}

@Override
public void laugh() throws RemoteException {
System.out.println("汪汪!");
}
}

Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

import cc.kevinlu.spidemo.spi.AnimalService;

public class Server {

public static void main(String[] args) throws Exception {
AnimalService dogService = new DogServiceImpl();
AnimalService lionService = new LionServiceImpl();
// 设置服务提供的端口
LocateRegistry.createRegistry(8891);
// 设置rmi的host为127.0.0.1,否则可能会出现connect refused错误
System.setProperty("java.rmi.server.host", "127.0.0.1");
// 发布服务
Naming.bind("rmi://127.0.0.1:8891/dogs", dogService);
System.out.println("dog service publish success!");

}

}
  • 客户端(rmi-client:引用rmi-api)
  1. 正常情况

    1
    2
    AnimalService dogService = (AnimalService) Naming.lookup("rmi://127.0.0.1:8891/dogs");
    dogService.laugh();
  2. 反射的方式去回调方法

    1
    2
    3
    Object obj = Naming.lookup("rmi://127.0.0.1:8891/dogs");
    Method method = obj.getClass().getMethod("laugh");
    method.invoke(obj, null);