>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 27920 个阅读者 刷新本主题
 * 贴子主题:  RMI 使用笔记 回复文章 点赞(0)  收藏  
作者:日月光华    发表时间:2019-12-26 08:59:25     消息  查看  搜索  好友  邮件  复制  引用

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());
    }
}

程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->面向对象开发方法概述之开发思想(上)
  JavaWeb开发-->自定义JSP标签(Ⅱ)
  JSP与Hibernate开发-->JPA API的高级用法
  Java网络编程-->用Swing组件展示HTML文档
  精通Spring-->Vue Router路由管理器
  Vue3开发-->绑定表单
  10道Java编程基础练习题
  Java Proxy用法: 让我们创建一个API代理器
  好消息:《精通JPA与Hibernate:Java对象持久化技术详解》出...
  JAVA锁相关知识总结
  Java泛型中的通配符 T,E,K,V,? 你了解吗
  java 中文繁简体转换工具 opencc4j
  Java 冒泡排序算法
  Eclipse的安装配置
  NoClassDefFoundError和ClassNotFoundException的区别
  邀请您一起来祝福和祈祷,祈愿疫情早日消除,平安吉祥
  Eclipse使用指南:创建Java项目的步骤
  Java设计模式:组合模式
  Java入门实用代码:遍历目录
  Java入门实用代码:数组元素的反转
  java使用gzip实现文件解压缩示例
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。