第五章Client Search(查找客户)

一个客户利用lookup service支持的ServiceRegistrar对象查找lookup service上的服务:


  public Class ServiceRegistrar {
    public java.lang.Object lookup(ServiceTemplate tmpl)
                            throws java.rmi.RemoteException;
    public ServiceMatches lookup(ServiceTemplate tmpl,
                                 int maxMatches)
                            throws java.rmi.RemoteException;
							}
方法lookup用ServiceTemplate类来描述要寻找的服务:

   package net.jini.core.lookup;
   
   public Class ServiceTemplate {
    public ServiceID serviceID;
    public java.lang.Class[] serviceTypes;
    public Entry[] attributeSetTemplates;
    
    ServiceTemplate(ServiceID serviceID, 
                    java.lang.Class[] serviceTypes, 
                    Entry[] attrSetTemplates);
	}

如果不知道,serviceID为null。attributeSetTemplates是一个执行属性匹配的Entry集合。 方法lookup中主要的参数是一组serviceTypes。每个输出的服务是一个类的实例;但是在查找中不需使用 类实例,因为那时客户已经得到了该实例,不需要查找了!下一个重要的东西是Class对象,因为输出服务要 被检查是否是某个类的实例。但是如果你要得到某个类对象,为什么不在客户端简单的用new生成呢?一般来说, 输出类是要求类的子类,并且这些子类将提供比客户用new生成类更多的东西。所以客户将要求一个超类或一个 接口对象。为了更具体些,例如一个toaster应该被定义为接口(interface):


public interface Toaster { 
   void setDarkness(int dark);
   void startToasting();
}
而一个具体的Breville ``Extra Lift'' toaster要具体的实现该接口,其他的toasters也是一样。

public Class BrevilleExtraLiftToaster implements Toaster {
    void setDarkness(int dark) {
        ...
    }
    void startToasting() {
        ...
    }
}
烤面包机(toaster)开始时,它输出一个类BrevilleExtraLiftToaster对象到lookup service。但是客户并不知道toaster的类型,所以会有如下的请求:


	Class[] toasterClasses = new Class[1];
    Toaster toaster = null;
    try {
        toasterClasses[0] = new Class.forName("Toaster");
    } catch(ClassNotFoundException e) {
        System.err.exit(1);
    }
    ServiceTemplate template = new ServiceTemplate(null, classes, 
                                                   null);
    try {
        toaster = (Toaster) registrar.lookup(template);
    } catch(java.rmi.RemoteException e) {
        System.err.exit(2);
    }
注意lookup方法可以抛出一个例外。如果要求的服务不可序列化,该例外就会发生。 最后,传送到客户端的对象是实现接口Toaster,被强制转换成该类型。这个对象有两个方法setDarkness() 和startToasting()。关于烤面包机没有其他信息可用,因为该接口没有指定更多的方法, 在这种情况下属性集合为null。所以客户可以调用:

	 toaster.setDarkness(1);
     toaster.startToasting();

1、ServiceMatches

如果客户想查找多个来自指定lookup service的匹配服务,就应该在对象ServiceMatches中指定 要求返回的匹配数目。


package net.jini.core.lookup;
public Class ServiceMatches {
    public ServiceItem[] items;
    public int totalMatches ;
}
数组items中的元素数目和totalMatches值相同。但是,并不是该数组中的所有元素都必须非空! 当用户只要求一个服务的时候,如果该服务是不可序列化的,则出现例外;但是如果要求多个服务, 即使其中一个服务是不可序列化的,也不会产生例外,因为其他服务还是可用的,这时该服务就是 空的(null)。


    ServiceMatches matches = registrar.lookup(template, 10);
    for (int n = 0; n < matches.totalMatches; n++) {
        Toaster toaster = (Toaster) matches.items[n];
	if (toaster != null) {
	    toaster.setDarkness(1);
	    toaster.startToasting();
        }
    }