目录
[一、RMI 核心概念](#一、RMI 核心概念)
[RMI 的核心组件](#RMI 的核心组件)
[2.1 项目结构说明](#2.1 项目结构说明)
[2.2 核心代码实现与解析](#2.2 核心代码实现与解析)
[编写 DAO 层(数据库操作)](#编写 DAO 层(数据库操作))
[启动 RMI 服务端](#启动 RMI 服务端)
[编写 RMI 客户端](#编写 RMI 客户端)
[2.3 运行流程与结果](#2.3 运行流程与结果)
一、RMI 核心概念
RMI(Remote Method Invocation)是Java提供的远程方法调用机制,允许在不同Java虚拟机(JVM)之间进行对象方法调用,是实现Java分布式应用的核心技术。但其仅适用于 Java 环境,无法实现与其他编程语言(如 Python、C++ 等)的跨语言分布式通信,限制了其在异构系统中的应用。
RMI 的核心组件
- 远程接口(Remote Interface) :继承
java.rmi.Remote
,定义可远程调用的方法(需抛出RemoteException
)。 - 远程对象(Remote Object) :实现远程接口,继承
UnicastRemoteObject
(用于将远程对象导出,使其能够接收来自客户端的调用请求)。 - RMI 注册表(Registry):类似 "服务注册中心",用于存储远程对象的引用,供客户端查找。
- 客户端(Client):通过注册表获取远程对象引用,调用其方法。
二、案例:用户登录验证案例
2.1 项目结构说明
服务端项目结构(IDEA)

客户端项目结构(Eclipse)

2.2 核心代码实现与解析
定义远程接口
创建IData
接口,继承Remote
,声明可远程调用的方法(如查询信息、登录验证)。
- 必须继承
java.rmi.Remote
接口 - 所有方法必须声明抛出
RemoteException
- 接口需要同时在服务端和客户端定义(包名和类名必须一致)
java
package com.demo.data.interfaces;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 远程接口定义
* 必须继承Remote接口,所有方法必须抛出RemoteException
*/
public interface IData extends Remote {
// 查询系统信息
public String queryMessage() throws RemoteException;
// 用户登录验证
public String checkLogin(String username,String userpwd) throws RemoteException;
}
实现远程对象(服务端逻辑)
创建UserDataImpl
类,继承UnicastRemoteObject
并实现IData
接口,编写业务逻辑(如数据库登录验证)。
- 继承
UnicastRemoteObject
:自动将对象 "导出" 为远程对象,允许客户端远程调用。 - 构造方法必须抛出
RemoteException
:父类UnicastRemoteObject
的构造方法会抛出该异常。
java
package com.demo.impl;
import com.demo.dao.Dao;
import com.demo.data.interfaces.IData;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* 远程对象实现类:
* 1. 继承UnicastRemoteObject(自动导出为远程对象)
* 2. 实现IData接口
*/
public class UserDataImpl extends UnicastRemoteObject implements IData {
// 必须声明构造方法,并抛出RemoteException
public UserDataImpl() throws RemoteException {
}
@Override
public String queryMessage() throws RemoteException {
return "RMI分布式从远程传过来的数据为:RMI、webservice、hessian、thrift、googleRPC、Dubbo";
}
@Override
public String checkLogin(String username, String userpwd) throws RemoteException {
Dao dao = new Dao();
// 调用Dao层验证登录(实际连接数据库)
if(dao.checkLogin(username,userpwd)>0)
{
return "登录成功";
}
return "登录失败";
}
}
编写 DAO 层(数据库操作)
创建Dao
类,负责数据库连接与登录验证逻辑(需提前在数据库中创建jk202508
数据库和t_emp
表)。
java
package com.demo.dao;
import java.sql.*;
/**
* DAO层:数据库操作
*/
public class Dao {
Connection conn;
public Dao()
{
try {
// 加载MySQL驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 建立数据库连接
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jk202508", "root", "123456");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 验证用户登录
public int checkLogin(String username,String userpwd)
{
String sql ="select count(ename) from t_emps where ename = ? and epwd =?";
int count = 0;
try {
PreparedStatement pstmt = this.conn.prepareStatement(sql);
pstmt.setString(1,username);
pstmt.setString(2,userpwd);
ResultSet rs = pstmt.executeQuery();
while(rs.next())
{
count = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
if(null!=conn)
{
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return count;
}
}
启动 RMI 服务端
创建ServerRMI
类,负责:
-
实例化远程对象。
-
启动 RMI 注册表(端口
9200
)。 -
将远程对象绑定到注册表,供客户端查找。
核心 API 说明:
LocateRegistry.createRegistry(端口号)
:在指定端口启动 RMI 注册表。Naming.bind(url, obj)
:将远程对象绑定到注册表,url
是客户端查找的地址。
java
package com.demo.serverrmi;
import com.demo.data.interfaces.IData;
import com.demo.impl.UserDataImpl;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
/**
* RMI服务端:启动服务并注册远程对象
*/
public class ServerRMI {
public static void main(String[] args) {
try {
// 1. 实例化远程对象
IData dataService = new UserDataImpl();
// 2. 启动RMI注册表(端口9200)
LocateRegistry.createRegistry(9200);
System.out.println("RMI注册表已启动,端口:9200");
// 3. 将远程对象绑定到注册表(URL格式:rmi://IP:端口/名称)
Naming.bind("rmi://127.0.0.1:9200/userdatas",dataService);
System.out.println("Java的RMI服务已经启动成功,等待客户端连接...");
} catch (RemoteException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (AlreadyBoundException e) {
e.printStackTrace();
}
}
}
编写 RMI 客户端
创建Test
类,作为客户端:
-
通过
Naming.lookup()
从注册表获取远程对象引用。 -
调用远程对象的方法(如
queryMessage()
、checkLogin()
)。
核心逻辑:
Naming.lookup(url)
:根据 URL 从注册表获取远程对象引用,强制转换为IData
接口。- 调用
data.queryMessage()
和data.checkLogin()
:与本地方法调用语法完全一致,RMI 会自动处理远程通信。
java
package com.demo.javarmiclient;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Scanner;
import com.demo.data.interfaces.IData;
/**
* RMI客户端:调用远程对象方法
*/
public class Test {
// 远程对象引用(静态初始化,确保启动时就获取)
static IData data = null;
static {
try {
// 从注册表查找远程对象
data = (IData) Naming.lookup("rmi://127.0.0.1:9200/userdatas");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 调用远程方法:查询信息
public void queryMsg() {
try {
String message = data.queryMessage();
System.out.println("客户端远程调用服务端的结果为:" + message);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 调用远程方法:登录验证
public void checkLogin(String username, String userpwd) {
try {
String result = data.checkLogin(username, userpwd);
System.out.println("客户端远程调用服务端登录的结果为:" + result);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Test t = new Test();
// t.queryMsg();
System.out.println("请输入用户姓名:");
Scanner s1 = new Scanner(System.in);
String username = s1.next();
System.out.println("请输入用户密码:");
Scanner s2 = new Scanner(System.in);
String userpwd = s2.next();
t.checkLogin(username, userpwd);
}
}
2.3 运行流程与结果
RMI 是 Java 分布式通信的 "入门级" 方案,它通过远程接口 + 远程对象 + 注册表的组合,实现了 "像调用本地方法一样调用远程方法" 的效果。本文通过 "用户登录验证" 案例,演示了 RMI 的完整开发流程:
-
定义远程接口(
IData
) -
实现远程对象(
UserDataImpl
) -
启动服务端并注册对象(
ServerRMI
) -
客户端查找并调用远程方法(
Test
)
启动服务端

启动客户端
