1.RMI的概述:
RMI(remote method invocation) , 可以认为是RPC的java版本
RMI使用的是JRMP(Java RemoteMessageing Protocol), JRMP是专门为java定制的通信协议,所以踏实纯java的分布式解决方案
2. RMI的主要概念
- Registry 即注册中心,负责注册服务;
- Server 是提供服务的地方,真正实现约定接口的地方;
- Client 是你的调用方,需要使用服务的一方。
三者之间的关系如下:
3.实现一个RMI程序
- 创建远程接口, 并且继承java.rmi.Remote接口
- 实现远程接口,并且继承:UnicastRemoteObject
- 创建服务器程序: createRegistry()方法注册远程对象
- 创建客户端程序 (获取注册信息,调用接口方法)
3.1本文用获取用户信息为简单案例
1.用户实体
import java.io.Serializable;
/**
* @author zpoison
* @data 2018/5/31/031 18:10
*/
public class User implements Serializable {
private String name;
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
2.UserService接口提供业务处理方法:
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* @author zpoison
* @data 2018/6/1/001 9:00
*/
public interface UserService extends Remote {
//每一个定义的方法都必须抛出一个RemoteException异常对象
//我们可供远程调用的方法就是通过这里开公开
//同过姓名获取用户信息
public String getUserInfo(String name) throws RemoteException;
}
3.UserServiceImpl接口实现这里提供了一个简单的用户验证逻辑
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* @author zpoison
* @data 2018/6/1/001 9:03
*/
public class UserServiceImpl extends UnicastRemoteObject implements UserService {
protected UserServiceImpl() throws RemoteException {
}
@Override
public String getUserInfo(String name) throws RemoteException {
//模拟数据查询功能
User user =new User();
user.setAge(19);
user.setName("小明");
user.setSex("男");
//验证用户是否存在
if (user.getName().equals(name)){
return user.toString();
}
return "用户:"+name+"不存在";
}
}
4.注册服务
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
/**
* @author zpoison
* @data 2018/6/1/001 9:10
*/
public class UserServer {
public static void main(String[] args) {
try {
UserService userService =new UserServiceImpl();
LocateRegistry.createRegistry(8888);
Naming.bind("rmi://localhost:8888/UserService", userService);
System.out.println("server start success");
} catch (RemoteException e) {
e.printStackTrace();
} catch (AlreadyBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
5.客户端调用服务(需要依赖服务接口)
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
/**
* @author zpoison
* @data 2018/6/1/001 9:13
*/
public class UserClient {
public static void main(String[] args) {
try {
UserService userService=(UserService) Naming.lookup("rmi://localhost:8888/UserService");
System.out.println(userService);
System.out.println(userService.getUserInfo("小明"));
} catch (NotBoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
服务端启动信息:
客户端信息:
注意点:
实体User类必须实现 java.io.Serializable接口(表示可以进行序列化)(序列化反序列化参考上篇文章)
4.注册及调用流程