RMI简例

1人阅读 评论(0) 收藏 举报
分类:

声明:本案例使用的IDE是Eclipse,客户端程序和服务器程序位于同一个project中。

一、基本原理

RMI是Remote Method Invoke的缩写,是JDK提供的一个完善的、简单易用的远程调用框架,它要求客户端和服务器端都是Java程序。下面简述RMI的基本原理:如下图所示,RMI采用代理来负责客户端和服务器之间socket通信的细节。RMI框架分别为远程对象生成了客户端代理和服务器端代理,位于客户端的代理称为存根(Stub),位于服务器端的代理称为骨架(Skeleton)。

远程对象会在客户端生成存根对象。当客户端调用远程对象的方法时,实际上是调用本地存根的相应方法。然后,存根会把被访问的远程对象名、方法名以及参数编组后发送给服务器,由骨架去调用相应的远程方法并把返回值或异常返回给客户端。

二、基本步骤

一般来说,只要继承java.rmi.server.UnicastRemoteObject类和实现java.rmi.Remote 接口就可以成为远程对象。由于java的单继承,继承了UnicastRemoteObject类之后就不能继承其他的类,这时可以在构造方法中调用exportObect()方法,同样可以将其导为远程对象。实际上,UnicastRemoteObject的构造器也会去调用自身的exportObect()的静态方法。下面是创建一个RMI程序的基本步骤:
(1)创建远程接口,继承java.rmi.Remote接口;
(2)创建远程类,实现远程接口;
(3)创建服务器程序,在rmiregistry注册表中注册远程对象;
(4)创建客户端程序,负责定位远程对象,并且调用远程方法。

*创建远程接口

远程接口中声明了可以被客户端访问的远程方法,远程接口应符合以下条件:
(1)直接或间接继承java.rmi.Remote接口;
(2)接口中的所有方法声明抛出java.rmi.RemoteException异常或父异常。
[java] view plain copy
  1. package main;  
  2.   
  3. import java.rmi.Remote;  
  4. import java.rmi.RemoteException;  
  5. // Inherit the java.rmi.Remote interface  
  6. public interface HelloService extends Remote {  
  7.     // Remote method should throw RemoteException  
  8.     public String service(String data) throws RemoteException;  
  9. }  

三、创建远程类

远程类应符合以下条件:
(1)继承java.rmi.server.UnicastRemoteObject类并实现远程接口;
(2)构造器必须抛出java.rmi.RemoteException异常。
[html] view plain copy
  1. package main;  
  2.   
  3. import java.rmi.RemoteException;  
  4. import java.rmi.server.UnicastRemoteObject;  
  5. // Inherit UnicastRemoteObject and implement HelloService interface  
  6. public class HelloServiceImpl extends UnicastRemoteObject  
  7.         implements HelloService {  
  8.   
  9.     private static final long serialVersionUID = 1L;  
  10.     private String name;  
  11.   
  12.     public HelloServiceImpl(String name) throws RemoteException {  
  13.         super();  
  14.         this.name = name;  
  15.         // UnicastRemoteObject.exportObject(this, 0);  
  16.     }  
  17.   
  18.     @Override  
  19.     public String service(String data) throws RemoteException {  
  20.         return data + name;  
  21.     }  
  22. }  

四、创建服务器程序

在这里要介绍几个方法:
  • bind(String name, Object obj): 注册对象,把对象与服务名绑定。如果该服务名已与其他对象绑定,则会抛出NameAlreadyBoundException异常。
  • rebind(String name, Object obj): 注册对象,把对象与服务名绑定。如果该服务名已与其他对象绑定,不会抛异常,而是将新的对象绑定到该服务名上。
  • lookup(String name): 查找对象,返回与指定名称相同的对象。

服务器端首先要创建注册表实例,然后将远程对象注册到注册表上。服务器程序运行就绪之后,不会立即结束,而是去监控客户端的连接。关于服务名的命名格式,推荐使用“rmi://主机名:端口号/实例名”的方式,这样可以避免在远程对象很多的时候因服务名一致而引发的冲突。默认的端口号1099可以省略。

[html] view plain copy
  1. package main;  
  2.   
  3. import java.rmi.RemoteException;  
  4. import java.rmi.registry.LocateRegistry;  
  5.   
  6. import javax.naming.Context;  
  7. import javax.naming.InitialContext;  
  8. import javax.naming.NamingException;  
  9.   
  10. public class Server {  
  11.   
  12.     public static void main(String[] args) {  
  13.         try {  
  14.             LocateRegistry.createRegistry(1099);  
  15.   
  16.             HelloService service1 = new HelloServiceImpl("service1");  
  17.             Context namingContext = new InitialContext();  
  18.             namingContext.rebind("rmi://localhost:1099/HelloService1",  
  19.                     service1);  
  20.         }  
  21.         catch (RemoteException | NamingException e) {  
  22.             // TODO Auto-generated catch block  
  23.             e.printStackTrace();  
  24.         }  
  25.         System.out.println("Successfully register a remote object.");  
  26.   
  27.     }  
  28. }  

五、创建客户端程序

[html] view plain copy
  1. package main;  
  2.   
  3. import java.rmi.RemoteException;  
  4.   
  5. import javax.naming.Context;  
  6. import javax.naming.InitialContext;  
  7. import javax.naming.NamingException;  
  8.   
  9. public class Client {  
  10.     public static void main(String[] args) {  
  11.         // TODO Auto-generated method stub  
  12.         String url = "rmi://localhost:1099/";  
  13.         try {  
  14.             Context namingContext = new InitialContext();  
  15.             HelloService serv = (HelloService) namingContext.lookup(  
  16.                     url + "HelloService1");  
  17.             String data = "This is RMI Client.";  
  18.             System.out.println(serv.service(data));  
  19.         }  
  20.         catch (NamingException | RemoteException e) {  
  21.             // TODO Auto-generated catch block  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25. }  
客户端先根据服务名查找远程对象,然后才能调用远程方法。因此,此处的服务名必须与在服务器中注册的服务名称一致,否则将无法找到远程对象。

六、运行

在Eclipse中先启动Server,然后启动Client即可。

转自:https://blog.csdn.net/xiaoyaoyulinger/article/details/51452674

查看评论

MFC2014-mfc实例-刘东明制作.rar

  • 2015年03月22日 15:25
  • 33.4MB
  • 下载

顺序栈的实现例程

说明:一直对栈似是而非的理解,因此写出其实现,但是就这个简单的程序中,我发现存在着很多缺陷,谁有兴趣帮我更正,本人非常感谢。另外我发现仅就顺序栈而言,都存在着多个变种:)////////-------...
  • SuperXu_swjtu
  • SuperXu_swjtu
  • 2006-11-13 14:00:00
  • 738

JDBC连接数据库工具类以及测试

1. 数据库连接工具代码package com.zzm.db;import java.sql.*;/** * Created by ming on 2017/6/13. */ public ...
  • windzzm
  • windzzm
  • 2017-06-13 14:15:50
  • 206

linux下C语言实现ARP数据包发送

  • 2012年07月27日 17:48
  • 5KB
  • 下载

C 语言socket编程基础/memset()

         memset()的函数, 它可以一字节一字节地把整个数组设置为一个指定的值。 memset()函数在mem.h头文件中声明,它把数组的起始地址作为其第一个参数,第二个参数是设置数组每...
  • u011146511
  • u011146511
  • 2016-07-13 08:59:48
  • 376

关联规则--CARMA 算法

  • 2011年03月04日 12:42
  • 1.03MB
  • 下载

线程池ThreadPoolExecutor简例

步骤一: 线程池初始化类:import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor;...
  • Fasure_Smile
  • Fasure_Smile
  • 2016-08-12 11:18:39
  • 1688

一周学习简单总结

一周又过去了……距离noip似乎又近了一些…… 做个简单的总结吧。。 每天都在考试,,考试的成绩都不大好, 我似乎一直在训练分析题目? 有挺多题想出了正解还是挺不错的。。233 大概...
  • ThinFatty
  • ThinFatty
  • 2017-10-21 14:30:26
  • 254

如何创建简单ATL服务应用

废话不多说,直接开始吧VS2005新建项目时选中ATL项目 ATL项目向导中选择服务(EXE)选项 至于属性化,个人建议勾选,方便集中管理你的服务的初始化创建完成后,你会得到以下两个工程(如图) 其中...
  • falx2004
  • falx2004
  • 2010-02-27 15:05:00
  • 1665

cc2430开发_简例

  • 2008年06月27日 22:06
  • 1005KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 9145
    积分: 445
    排名: 11万+
    最新评论