Java RMI 框架的工厂方法模式实现

简介:
大概介绍了Java RMI框架的基础实现,服务器端Server类一开始就预先向RMI表中注册了一定数量的远程服务,被动地等待客户端Client类通过远程访问获得服务器端对应的远程对象的存根。请详看文章“Java RMI 框架(远程方法调用)”http://haolloyin.blog.51cto.com/1177454/332426

这种方式有以下缺点

1、 如果服务器预先创建好远程对象一直都没有被客户访问到,那么就浪费了服务器的一些资源;

2、 而且这种方式使得服务器只能预先提供少量的远程对象,并且服务器很难保证每个远程对象都具有唯一的名字,即服务器可能重复创建同样名称的远程对象。

为了改善这种不足,我们运用工厂方法模式(Factory Method)来实现一下。

具体方案:设计一个专门获取远程对象的工厂类,该工厂类中可以用一个Hashtable对象来 缓存远程对象 。客户端需要远程对象时,根据具体名称来访问服务器端,当该缓存 区存在 以该名称命名的远程对象 ,则返回一个远程对象的存根。否则,该工厂立即创建并注册一个符合客户请求的远程对象 ,这是不是也起到延迟服务器端创建远程对象的作用呢? 当然,我们必须保证该工厂类也是一个远程对象,因为客户端与服务器端的一切交互都从该工厂类开始。

具体类图如下: 

先给出具体的交互时序图:

 

    具体代码实现如下:
import java.rmi.*; 
import java.rmi.server.*; 
import java.util.Hashtable; 
import javax.naming.*; 

//抽象的服务接口,定义远程服务的标准service()方法 
//因为是远程对象类,所以要extends标识的远程接口Remote, 
//而且远程方法要声明抛出RemoteException异常 
interface IService  extends Remote{ 
   public String service(String contents)  throws RemoteException; 


//具体的RMI服务类,实现具体的远程方法服务 
class RMIService  extends UnicastRemoteObject  implements IService{ 
   private String name; 
   //默认的构造函数也要抛出RemoteException异常 
   public RMIService(String name)  throws RemoteException{ 
     super(); 
     this.name = name; 
  } 
    
   //具体的远程方法 
   public String service(String contents)  throws RemoteException{ 
     return  "from " +  this.name +  " >> " + contents; 
  } 


//抽象的工厂类,因为工厂类也需要被远程访问,故扩展Remote接口 
interface IFactory  extends Remote{ 
   //工厂方法,获得服务 
   public IService getService(String name)  throws RemoteException; 


//具体的RMI工厂类 
class RMIFactory  extends UnicastRemoteObject  implements IFactory{ 
   //Hashtable对象作为远程对象的缓冲区 
   private Hashtable<String, IService> remoteObjects; 
    
   public RMIFactory()  throws RemoteException{ 
     this.remoteObjects =  new Hashtable<String, IService>(); 
  } 
    
   //关键:可以延迟远程对象的创建 
   public IService getService(String name)  throws RemoteException{ 
    IService object =  this.remoteObjects.get(name); 
     //若为空,则说明不存在客户端需要的远程对象,立即创建以满足客户要求 
     if(object ==  null){ 
      System.out.println( "客户要访问的远程对象" + name +  "不存在!立即创建!"); 
      object =  new RMIService(name); 
       this.remoteObjects.put(name, object); 
    } else { 
      System.out.println( "客户要访问的远程对象" + name +  "已存在!"); 
    } 
     return object; 
  } 
}

Server类:

import java.rmi.*; 
import javax.naming.*; 
//测试类 
public  class Client { 
   public  static  void main(String[] args) { 
    String url =  "rmi://localhost/"; 
//    Server.registerFactory(); 
    try { 
      Context namingContext = new InitialContext(); 
      //远程访问,获得工厂的存根 
      IFactory factory = (IFactory)namingContext.lookup(url + "factory"); 
        
      IService service01 = factory.getService("service01"); 
      System.out.println(service01.service("访问服务器 ...")); 
        
      IService service02 = factory.getService("service02"); 
      System.out.println(service02.service("访问服务器 ...")); 
        
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
}
Client类:

import java.rmi.*; 
import javax.naming.*; 
//服务器端,一定需要预先向服务器注册一个工厂对象,以备客户的远程访问 
public  class Server{    
   public  static  void main(String [] args) { 
    registerFactory(); 
  } 
    
   //这里使用了静态方法来注册工厂对象, 
   public  static  void registerFactory(){ 
    String url =  "rmi://localhost/"; 
    try { 
      IFactory factory = new RMIFactory(); 
      Context namingContext = new InitialContext(); 
      namingContext.rebind(url + "factory", factory); 
      System.out.println("服务器注册了一个工厂!"); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
}
测试,先在命令行下输入“ start rmiregistry ”;再“ start java Server ”,最后才是“ java Client ”。过程如下:

    第二次运行 Client类: 

还可以根据需要自己多测试几次,就可以明白工厂方法模式对文章前面所指出的不足之处的改进了,而且也运用到了一个模式,何乐而不为?


本文转自 xxxx66yyyy 51CTO博客,原文链接:http://blog.51cto.com/haolloyin/334233,如需转载请自行联系原作者
相关文章
|
1天前
|
SQL 缓存 Java
Java一分钟之-Hibernate:ORM框架实践
【5月更文挑战第15天】Hibernate是Java的ORM框架,简化数据库操作。本文列举并解决了一些常见问题: 1. 配置SessionFactory,检查数据库连接和JDBC驱动。 2. 实体类需标记主键,属性映射应匹配数据库列。 3. 使用事务管理Session,记得关闭。 4. CRUD操作时注意对象状态和查询结果转换。 5. 使用正确HQL语法,防止SQL注入。 6. 根据需求配置缓存。 7. 懒加载需在事务内处理,避免`LazyInitializationException`。理解和避免这些问题能提升开发效率。
18 0
|
1天前
|
Java 数据安全/隐私保护 Spring
Java 中 Spring Boot 框架下的 Email 开发
Java 中 Spring Boot 框架下的 Email 开发
18 2
|
1天前
|
XML Java 数据库连接
Java一分钟之MyBatis:持久层框架基础
【5月更文挑战第15天】MyBatis是Java的轻量级持久层框架,它分离SQL和Java代码,提供灵活的数据库操作。常见问题包括:XML配置文件未加载、忘记关闭SqlSession、接口方法与XML映射不一致、占位符使用错误、未配置ResultMap和事务管理不当。解决这些问题的关键在于正确配置映射文件、管理SqlSession、避免SQL注入、定义ResultMap以及确保事务边界。遵循最佳实践可优化MyBatis使用体验。
12 2
Java一分钟之MyBatis:持久层框架基础
|
1天前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
12 1
|
1天前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
6 0
|
1天前
|
存储 安全 Java
Java一分钟之-集合框架进阶:Set接口与HashSet
【5月更文挑战第10天】本文介绍了Java集合框架中的`Set`接口和`HashSet`类。`Set`接口继承自`Collection`,特征是不允许重复元素,顺序不确定。`HashSet`是`Set`的实现,基于哈希表,提供快速添加、删除和查找操作,但无序且非线程安全。文章讨论了`HashSet`的特性、常见问题(如元素比较规则、非唯一性和线程安全性)以及如何避免这些问题,并提供了代码示例展示基本操作和自定义对象的使用。理解这些概念和注意事项能提升代码效率和可维护性。
12 0
|
1天前
|
存储 安全 算法
Java一分钟之-Java集合框架入门:List接口与ArrayList
【5月更文挑战第10天】本文介绍了Java集合框架中的`List`接口和`ArrayList`实现类。`List`是有序集合,支持元素重复并能按索引访问。核心方法包括添加、删除、获取和设置元素。`ArrayList`基于动态数组,提供高效随机访问和自动扩容,但非线程安全。文章讨论了三个常见问题:索引越界、遍历时修改集合和并发修改,并给出避免策略。通过示例代码展示了基本操作和安全遍历删除。理解并正确使用`List`和`ArrayList`能提升程序效率和稳定性。
8 0
|
1天前
|
前端开发 安全 Java
使用Spring框架加速Java开发
使用Spring框架加速Java开发
56 0
|
1天前
|
存储 安全 Java
深入理解Java集合框架
深入理解Java集合框架
11 0
|
1天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
102 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式