RMI 使用笔记
Java 远程方法调用,即 Java RMI( Java Remote Method Invocation ) 。顾名思义,可以使客户机上运行的程序能够调用远程服务器上的对象(方法)。
下面主要介绍一下使用步骤:
1.定义远程接口(服务端)
远程接口定义出可以让客户远程调用的方法。
此接口必须实现 java.rmi.Remote
接口,来表示其支持远程调用;同时其中声明的所有方法,需要抛出RemoteException
异常,因为远程调用的不稳定性(如网络原因等),这样可以让客户端在调用失败时进行相应的处理。
public interface DemoService extends Remote {
String sayHello() throws RemoteException;
}
2.实现远程接口(服务端)
远程接口的实现类如果想要被远程访问,可以有如下实现方式:
继承java.rmi.server.UnicastRemoteObject
类
public class DemoServerImpl extends UnicastRemoteObject implements DemoService{
public DemoServerImpl() throws RemoteException {
// 因为 UnicastRemoteObject 构造器抛出 RemoteException
// 所以此处只能声明一个构造器并抛出对应异常
}
@Override
public String sayHello() throws RemoteException {
return "Hello World";
}
}
如果不想继承UnicastRemoteObject
类,则需要使用 UnicastRemoteObject
类的静态方法exportObject(Remote obj, int port)
将对象导出
其中如果端口设为 0 的话,则表示任何合适的端口都可用来监听客户连接
public class DemoServerImpl implements DemoService{
public DemoServerImpl() throws RemoteException {
UnicastRemoteObject.exportObject(this, 0);
}
@Override
public String sayHello() throws RemoteException {
return "Hello World";
}
}
这两者方法本质上是一样的,在UnicaseRemoteObject
类的构造方法中,其实也是调用了exportObject
方法
// UnicaseRemoteObject中的部分源码
protected UnicastRemoteObject() throws RemoteException
{
this(0);
}
// if port is zero, an anonymous port is chosen
protected UnicastRemoteObject(int port) throws RemoteException
{
this.port = port;
exportObject((Remote) this, port);
}
3.启动 RMI 注册表
注册表就像一个电话簿,启动后即可将提供的服务注册到其中,客户可以通过它查询到服务来进行调用
启动注册表有两种方法,一种是通过命令行rmiregistry
来启动,另一种方式是通过LocateRegistry.createRegistry(int port)
方法。
4.注册开启远程服务
注册服务共有三种方式:
LocateRegistry 类的对象的 rebind() 和 lookup() 来实现绑定注册和查找远程对象的
利用命名服务 java.rmi.Naming 类的 rebind() 和 lookup() 来实现绑定注册和查找远程对象的
利用JNDI(Java Naming and Directory Interface,Java命名和目录接口) java.naming.InitialContext 类来 rebind() 和 lookup() 来实现绑定注册和查找远程对象的
其中第二种方式实际是对第一种方式的简单封装,在内部仍是调用Registry
类的bind
方法
// Naming 类的部分源码 (为了节省篇幅,去除了抛出异常部分)
public static void bind(String name, Remote obj) throws ...
{
ParsedNamingURL parsed = parseURL(name);
Registry registry = getRegistry(parsed);
if (obj == null)
throw new NullPointerException("cannot bind to null");
registry.bind(parsed.name, obj);
}
服务测试类:
public class ServerTest {
public static void main(String[] args) throws Exception{
String name = "rmi.service.DemoService";
// 创建服务
DemoService service = new DemoServerImpl();
// 创建本机 1099 端口上的 RMI 注册表
Registry registry1 = LocateRegistry.createRegistry(1099); /***************** 以下为注册方法一 ************/
// 将服务绑定到注册表中
registry1.bind(name, service); /***************** 以下为注册方法二 ************/
// Naming.bind(name, service); /***************** 以下为注册方法三 ************/
//Context namingContext = new InitialContext();
//namingContext.bind("rmi:" + name, service); // 此方式 name 需要以 rmi: 开头 }
}
客户端测试类:
public class ClientTest {
public static void main(String[] args) throws Exception {
String name = "rmi.service.DemoService";
/***************** 以下为查找服务方法一 ************/
// 获取注册表
Registry registry = LocateRegistry.getRegistry("localhost", 1099);
// 查找对应的服务
DemoService service = (DemoService) registry.lookup(name); /***************** 以下为查找服务方法二 ************/
// DemoService service = (DemoService) Naming.lookup(name); /***************** 以下为查找服务方法三 ************/
//Context namingContext = new InitialContext();
//DemoService service = (DemoService) namingContext.lookup("rmi:" + name); // 调用服务
System.out.println(service.sayHello());
}
}
参考文章:https://segmentfault.com/a/1190000004494341
最新文章
- Ubuntu 14 如何打开 .chm格式文档?
- Android 手势滑动,多点触摸放大缩小图片
- SPOJ CNTPRIME 13015 Counting Primes (水题,区间更新,求区间的素数个数)
- Android之屏幕测试
- Word2003中如何使封面和目录中不插入页码
- bootstrap 笔记01
- CI框架源代码阅读笔记5 基准測试 BenchMark.php
- SQL server 2008数据库的备份与还原、分离(转)
- solr6.4.1搜索引擎同步mysql数据库
- mysql数据类型double和decimal区别详解
- html日历(1)
- 详细分析SQL语句逻辑执行过程和相关语法
- Win10系列:C#应用控件进阶4
- window.requestAnimationFrame与Tween.js配合使用实现动画缓动效果
- javaScript遍历对象、数组总结
- UVALive - 6440(模拟)
- HTTP协议学习笔记(三)
- MyEclipse反向生成Java代码 ,Reverse Engineering-->;Java Source Folder-->;没有提供任何条目
- 使用jstl的Foreach 和jquery的each()的index属性
- Object-C 基础笔记4---ARC内存管理
热门文章
- 基于osg的python三维程序开发(一)
- 工作5年了还说不清bean生命周期?大厂offer怎么可能给你!
- Pending 打断点
- Jmeter Agent自动化
- IDEA 激活码,IDEA 注册码,IDEA 2019.3 激活码
- 【简说Python WEB】flask-mail电子邮件异步Asynchronous
- 更新Linux服务器时间
- [二分,multiset] 2019 Multi-University Training Contest 10 Welcome Party
- Java基础语法(4)-流程控制
- Building Applications with Force.com and VisualForce(Dev401)(七):Designing Applications for Multiple users:Managing your users' experience I