内容


拥有高级搜索功能的服务注册表,第 2 部分

实现

学习如何实现四个核心组件

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 拥有高级搜索功能的服务注册表,第 2 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:拥有高级搜索功能的服务注册表,第 2 部分

敬请期待该系列的后续内容。

简介

在面向服务架构(SOA)中,服务注册表用于发布和发现服务。在典型的注册表中,要执行服务查找,需要精确地匹配服务名和注册表中的现有服务名。在第 1 部分中,您已经了解了为什么必须去掉精确匹配服务名这一限制,因此注册表需要使用高级搜索功能,这样用户不需要知道服务的准确名称就可以在注册表中查找服务。此外,我们了解了提供这种高级搜索功能所需的过程和组件。我们在第一部分中确定的 4 个组件分别为 Classic Registry、Name Parser、Name Composer 和 Dictionary

在第二期文章中,我们将介绍如何实现第一部分中识别的 4 个组件。下面就将描述这些实现。

典型注册表

典型注册表提供了两个重要的功能,即发布服务和搜索/发现已发布的服务。在本系列中,我们将仅关注注册表的搜索/发现特性。包括 WebSphere Registry and Repository (WSRR) 在内的几乎所有商用注册表都提供了某种形式的搜索/发现功能,允许注册表用户通过提供服务的精确名称或 id 来查找包含服务接口和实现的服务描述。我们将这种包含有限的搜索/发现特性的注册表称为典型注册表。图 1 对这种典型注册表的功能进行了总结。由于所有商用注册表都提供了这种功能,因此本文不会讨论它的实现。相反,我们将主要关注如何在此功能之上构建具有高级搜索功能的注册表。

图 1. 典型注册表的搜索功能
典型注册表的搜索功能
典型注册表的搜索功能

Name Parser

name parser 组件使用服务名(通常由几个单词组成)作为输入,并返回一个列表,列出了组成服务名的几个单词。例如,如果输入名为 GetCarPrice,输出则为包含 getcarprice 几个单词的列表。图 2 展示了 Name Parser 组件的功能。

图 2. Name Parser 组件的功能
典型注册表的搜索功能
典型注册表的搜索功能

Name Parser 组件的实现利用了命名服务时使用的约定。例如,命名服务的一个常见约定是使用大写字母来分离/区分服务名中的单词。此类服务名的一个例子就是 GetCarPrice。在这个名称中包含 getcarprice 三个单词,分别使用 GCP 三个大写字母加以区分。这种命名约定非常类似于 Java 编程语言的命名约定。利用这种命名约定可以非常轻松地解析服务名。例如,清单 1 中的示例代码将解析遵循 Java 命名约定的服务名并返回构成服务名的单词的列表(Array)。

清单 1. 解析服务名的 Java 代码
 public Class NameParser
  {
	public static ArrayList parseName ( String serviceName) 
	{
		String name = serviceName;
		int len = name.length();
		int l = 0;
		ArrayList list = new ArrayList ();
		String constituentWord = "";
		char c = null;	
		for ( int k = 0; k < len;  k++)
		{
			c = name.charAt (k);

			if ( c < 'A'  || k == 0 )
			{
				constituentWord = constituentWord + c;
			}
			else
			{
				list.add (l, constituentWord);
				l++;
				constituentWord = "" + c;
			}
		}
		
		list.add (l, constituentWord);

		return list;
	}
  }

另一个常见的命名约定遵循 C/C++ 编程语言的命名约定。对于这个约定,构成服务名的单词使用下划线分隔。可以使用非常类似于清单 1 的代码来分隔单词。事实上,可以使用很简单的方法将以上代码变得更通用,这样可以同时处理这两种命名约定以及其他类似的约定。

Name Composer

Name Composer 组件提供的基本功能恰好与 name parser 组件的功能相反。它使用一个单词列表作为输入,并按照适当的顺序组合它们来提供一个服务名。例如,输入可以是一个包含 getcarprice 三个单词的列表,那么其输出则为服务名 GetCarPrice。图 3 展示了 Name Composer 的基本功能。在实际中,Name Composer 提供的功能要比基本功能更多一些。Name Composer 组件不会使用一个单词列表作为输入,而是使用多个单词列表作为输入并返回所有可能的服务名的列表。

图 3. Name Composer 组件的基本功能
Name Composer 组件的基本功能
Name Composer 组件的基本功能

下面的清单 2 展示了一些示例 Java 代码,可用于构建同等的服务名。该清单中的代码最多可以接受三个单词列表作为输入。每个列表包含构成原始服务名的单词的同义词。代码输出的是一个包含同等服务名的数组。但是,这段特定的代码被限制为最多对服务名使用三个单词,显然可以很容易将其修改为允许使用更多的单词。

清单 2. 构成同等服务名的 Java 代码
public class NameComposer
{
	public ArrayList composeNames ( ArrayList list1, ArrayList list2, ArrayList list3)
	{
		String serviceName = null;
		String word1 = null;
		String word2 = null;
		String word3 = null;
		int size1 = 0;
		int size2 = 0;
		int size3 = 0;
		ArrayList serviceNames = new ArrayList (); 

		if ( list1 != null )
			size1 = list1.size ();

		if ( list2 != null )
			size2 = list2.size ();

		if ( list3 != null )
			size3 = list3.size ();


		for  (int i = 0; i < size1;  i++)
		{
			word1 = (String) list1.get(i);
			word1 = upperFirstChar (word1);
		
			if ( size2 == 0)
			{
				servicesNames.add(word1);
				continue;
			}

			for ( int j = 0;  j < size2;  j++)
			{
				word2 = (String) list2.get(j);
				word2 = upperFirstChar (word2);
				if ( size3 == 0)
				{
					serviceNames.add (word1 + word2);
					continue;
				}
				for ( int k = 0;  k < size3;  k++)
				{
					word3 = (String) list3.get(k);
					word3 = upperFirstChar (word3);
					serviceName = word1 + word2 + word3;
					serviceNames.add (serviceName);
				} 
			}
		}

		return serviceNames;
	}

	private String upperFirstChar (String word)
	{
		char c = word.charAt (0);
		c = char.toUpperCase (c);
		StringBuffer sbuff = new StringBuffer (word);
		sbuff.setCharAt (0, c);
		return sbuff.toString ();
	}
}

Dictionary

在目前的上下文中,Dictionary 组件包含一个单词作为输入。dictionary 的输出是一组与初始单词含义相同或类似的单词的列表。例如,如果输入为单词 get,那么输出将为包含单词 getfetchobtain 的列表。dictionary 组件的功能如图 4 所示。

图 4. Dictionary 组件的功能
Dictionary 组件的功能
Dictionary 组件的功能

我们可以根据 dictionary 的内容对 dictionary 组件进行分类。

  • 特定于某个组织(例如大型公司或企业)的受限制的 dictionary
  • 一个更通用的特定于行业的 dictionary,该 dictionary 可以满足特定行业的需求,比如汽车行业
  • 非常通用的 dictionary,可以由任何组织跨行业使用。

有两种主要的方式可以实现 dictionary 组件。(1) 基于关系数据库的 dictionary,(2) 基于文件的 dictionary。我们现在就将讨论这两种实现 dictionary 组件的方法。

基于关系数据库的 Dictionary

关系数据库使用表格存储信息。表中的每个行都存储一组相关数据,并且存储在行中的数据被称为记录。要为我们的系统实现一个使用关系数据库的 dictionary,每个单词及其同义词都将存储在行中。为了提高搜索性能,第一个列将被索引。例如,要存储单词 car 及其两个同义词 automobilevehicle,数据库将在表中包含三个行,每一行将包含相同的同义词集,但是使用不同的同义词开头,如表 1 所示。必须注意数据库 dictionary 的一个限制。同义词的最大数量必须在表创建时指定。我们随后将看到,基于文件的 dictionary 克服了这一限制。

表 1. 包含单词及其同义词的关系数据库表
单词同义词 1同义词 2
CarAutomobileVehicle
AutomobileCarVehicle
VehicleAutomobileCar

图 5 中的流程图很好地解释了此类 dictionary 的工作原理。首先,使用 sql 或基于 sql 的工具创建表,其中包含足够多的列来存放每个单词最大数量的同义词。每个列必须具有足够多的指定存储空间来存放每个单词长度最大的同义词。然后,使用 sql 将每个单词的同义词输入到表中。为每个单词输入的行的数量将等于该单词的同义词的数量。每一个这些行将使用不同的同义词开头。从客户机接收到对给定单词的同义词的请求后,使用 sql 形成一个数据库查询来搜索给定单词的同义词。对数据库执行查询后,以列表形式返回查询结果,如果没有找到同义词的话则返回 null。

图 5. 基于数据库的 dictionary 的流程
基于数据库的 dictionary 的流程

基于文件的 Dictionary

对于基于文件的 Dictionary,dictionary 数据以文件形式存储在计算机硬盘中。文件中的每一行将包含一个单词及其同义词,并且使用空格或其他一些已知的标记分隔。因此,要存储 car 一词的所有三个同义词,将使用三个行,每个行使用不同的同义词开头,如清单 3 所示。

清单 3. 包含单词及其同义词的示例文件
Car Automobile Vehicle
Automobile Car Vehicle
Vehicle Automobile Car
...
...

图 6 所示的流程图很好地解释了此类 dictionary 的工作原理。首先,使用一个文本编辑器创建一个文件,其中每行包含一个常用词及其同义词。该单词及其同义词使用一个已知的标记分隔。文件存储在计算机硬盘中。第二步,在 dictionary 应用程序或子程序启动时,将文件中的每一行以字符串形式读入到计算机内存。然后,将字符串解析为单个单词并以列表形式存储到内存中。将这些列表复制到一个映射且使用列表的第一个单词(键)标识每个列表条目。在收到对给定单词的同义词的请求后,使用给定单词作为键来搜索映射。如果发现与输入单词相对应的列表,那么该列表将被返回给客户机,否则将返回 null。

图 6. 基于文件的 dictionary 的流程
基于文件的 dictionary 的流程

需要注意,对于基于数据库的 dictionary,同义词的最大数量在数据库模式的设计阶段就已经确定。但是对于基于文件的 dictionary 则没有这类限制。文件中可以存储任意数量的同义词。还要注意,对于基于数据库的 dictionary,每个列的长度在数据库模式的设计阶段就已经固定。这将约束每个同义词的最大大小。基于文件的 dictionary 则不存在此类存储限制。每个同义词都可以按照理想的大小保存。另一个区别在于基于数据库的 dictionary 需要使用一个工具/定制工具来将同义词放入数据库。基于文件的 dictionary 则不需要使用此类工具。任何文本编辑器都可用于基于文件的 dictionary。

结束语

在本期文章中,我们讨论了 SOA 注册表的四个具有高级搜索功能的核心组件。高级搜索功能允许在注册表中查找服务的开发时和运行时信息,即使您不知道服务的精确名称。需要注意,这些核心组件的概念和实现都包含在 IBM 正在申请的两个专利中。在最后一期文章即本系列的第 3 部分,我们将描述将这些组件部署为运行在一个或多个服务器上的单个或多个应用程序时所使用的可能配置。在第 3 部分中,我们还将描述第 5 个组件的实现,即 Controller,它可用于某些配置。Controller 组件将控制这四个核心组件的协同工作方式,从而提供用户所需的高级搜索功能。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services
ArticleID=604574
ArticleTitle=拥有高级搜索功能的服务注册表,第 2 部分: 实现
publish-date=12222010