SharePoint Web Services 入门

阅读数:5548 2008 年 6 月 18 日

SharePoint 通过一系列 Web Services 来支持互操作和远程调用,这里的 SharePoint,我指的是 WSS 3.0(Windows SharePoint Services)和 MOSS 2007(Microsoft Office SharePoint Server)。有好几种方法来编程访问 SharePoint,比如对象模型、Web Services、RPC over HTTP、以及 WebDAV,所有这些方式基于应用程序的需要都有它们各自的优点和适用范围。SharePoint RPC 协议很有用也很强大,特别在添加内容到服务器的时候,它确实有它的优势。对象模型比 Web Service 更健全特性更丰富,但是它不能提供远程操作的支持,因此若想使用对象模型,你的代码必须运行在 SharePoint 服务器上,并且你必须使用.NET 语言来开发。之所以要进行 SharePoint 数据的远程操作,有几个不同方面的原因,无论是管理脚本,还是诸如运行在客户端机器上需要访问 SharePoint 内容的应用程序,或者在企业中的非 SharePoint 应用程序,都需要对 SharePoint 进行原创操作。SharePoint 的 Web Services 构建于对象模型之上,暴露了对象模型里可用特性的一个子集,允许任何能“消费”Web Services 的语言和平台进行远程操作。对于大部分任务,SharePoint 所提供的 Web Services 都能满足,但是你也会发现一些对象模型中必需的操作没有在 Web Services 中出现,其要用自定义 Web Service 实现的方式来扩展。在这篇文章中,我们将会谈到在 WSS3 和 MOSS 2007 中存在的一些开箱即用的 Web Services,并讲述如何从 Java 和.NET 中“消费”它们。

我不会过于深入 WSS 和 MOSS 之间的不同点,已经有大量的文章很好地解释了这个东西了,我们这里需要关心的只是 Web Services 的区别。记住 MOSS 2007 是构建于 WSS 3.0 之上的,其有构建于 ASP.NET,并运行于 IIS(Internet Information Server)中。对 IIS 和 ASP.NET 有深入的了解是重要的,其有助于理解和使用 SharePoint。我们将要讨论的大部分 SharePoint 的 Web Services 是包含于 WSS 3.0 中,但也有一部分额外的是包含于 MOSS 2007 中,其利用了 MOSS 2007 所提供的额外特性,如更高级的企业搜索特性。

SharePoint Web Services 使用 ASP.NET Web Services (ASMX)来实现,所以你会在"web server extensions\12\ISAPI"(其通常位于 C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI")之下的"Microsoft Shared"目录中找到这些 Web Services 中大部分的物理文件。用于管理中心工具的管理 Web Service 位于 ADMISAPI 文件夹中,其在管理中心控制台里是一个名为"_vti_adm"的虚拟目录。当你创建了一个 SharePoint 站点时,它将包含一个名为"_vti_bin"的虚拟目录,以指向这个位置。IIS 不为子站点包含任何应用程序或虚拟目录,它们只是包含通过 SharePoint 元数据和 HttpModules 实现的对 _vti_bin 虚拟目录的映射。

对于任何服务,你都能找到一个 *.wsdl.aspx 文件,其可以生成服务的 WSDL(Web Services Description Language),一个 *.disco.aspx 文件提供访问发现实现,以及一个实际的 *.asmx 端点文件,它们中的大部分只是包含了一个引用到实际实现服务功能的 SharePoint 程序集和类型的页面指示符。

服务文件类型 描述
*.wsdl.aspx (search.wsdl.aspx) 在 SharePoint 中生成 WSDL(Web Services Description Language)的文件
*.disco.aspx (seach.disco.aspx) 提供发现实现的文件
*.asmx (search.asmx) Web Services 端点文件,它们中大部分只是包含一个引用到实际实现服务功能的 SharePoint 程序集和类型的页面指示符

开箱即用的服务

在 SharePoint 中,有很多 Web Services 是以 OOTB(开箱即用,Out Of The Box)的方式实现的,这可以完成大部分通用而基本的任务:从管理任务到搜索,到处理列表数据等等。下面是一个可供你引用的 SharePoint Web Services 的列表,和它们的大致解释。类似这样的简单列表通过让我对所有的服务和方法有一个快速的了解,从而帮助我更好的使用这些 Web Services。

消费查询服务

现在,我们已经对 SharePoint Web Services 有了初步的了解,以其通读用户手册还不如踢踢轮胎就开车上路了【译者注:意指先实际操作一下比读完帮助手册好】。我们没有太多时间来深入这些 Web Services 的所有方面,这些将会在下一篇文章中来详细讨论。基于某些原因,SharePoint 的很多 Web Services 不是返回 XML Node 就是 XML 编码字符串,不过不幸的是,它并不能返回类型化的 Schema,因此相关工具就不能通过分析来自动生成更好的代理对象了。我曾经看到过使用字符串格式的实现来解决类型化结构的缺陷,也花了很多时间和精力来找出可以描述这些服务传入和返回的 XML 的一种 Schema。我最终创建了 queryresponse.xsd,它是我综合了文档和服务传入和返回 XML 的信息后,推断出的一种 Schema;它允许我使用.NET 中的 xsd.exe 及 java 中的 JAXB 来生成代理类。

注意:我们之前讨论了两个不同的搜索 Web Services,MOSS 中的 search.asmx 和 WSS 中的 spsearch.asmx。这两个服务在 Schema 方面非常相似,但尝试对运行 MOSS 的机器调用 spsearch.asmx,会得到一个异常,这是由于 WSS 索引和查询服务被禁用了,其已经被 MOSS 中更高级的搜索特性所替代了。

使用.NET 的例子

从.NET 中消费 SharePoint Web Services 是相当简单而直接的,你只需简单地添加 Web 引用,并使用生成的代理。不过,我们将多做一步来用 XSD 生成一组表示查询和应答的类,其能序列化出发送和返回的 XML。

配置 Visual Studio 2005 来添加 XSD.exe 到菜单中

Visual Studio 包含了一个名为 XSD.exe 的工具,其能被用于根据 XSD 生成.NET 类型。不过这是一个命令行工具,但我喜欢把他添加为 Visual Studio 的一个菜单选项,以便能在 IDE 中执行它。如果你已经完成了这个步骤,或者你已经有一些添加插件这样的经验,你就可以跳过这步。

  1. 打开 Visual Studio 的“Tools”菜单上的“External Tools”对话框
  2. 点击“Add”
  3. 设置需要的属性并点击“OK”
属性
Command XSD >> CSharp
Title C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\xsd.exe
Arguments $(ItemPath) /c
Initial Directory $(ItemDir)
Use Output Window Checked

下载 XSD 文件

这里下载用于生成处理请求和响应过程中序列化成和反序列化的代理类的 XSD 文件。把下载的文件解压到工作目录;这个文件也包含了和完整的项目一起的 XSD。

创建一个项目,并从 XSD 中生成.NET 类型。现在我们已经有了 XSD,我们将创建一个 Windows Forms 项目,并从下载的 XSD 中生成.NET 类型。在打开 Microsft.Search.Query.xsd 之后,到工具菜单中选择我们上一步创建的 XSD 菜单项,以生成 Microsoft_Search_Query.cs 文件。

添加 Web 引用

我们现在可以通过在“solution explorer”右键点击我们项目的“references”节点, 来添加针对搜索 Web Service 的 Web 引用了。这里我们将选择“Add Web Reference”,在 URL 文本框中输入“http:///_vti_bin /spsearch.asmx”,然后点击“Go”。可能会提示你登录到 SharePoint 服务器,随后即可得到这个服务提供的方法列表。设置“Web Reference Name”为“SPSearch”,并点击“Add Reference”。

生成代理子类

为了进一步简化开发,我们将生成我们自己的代理子类,以便我们能使用我们从 XSD 生成的类来包装 QueryService,以隐藏 Query 方法传递和返回的 XML 的验证、序列化和反序列化工作。

创建调用服务的应用程序

现在,我们可以简单地实例化一个查询类和一个 QueryService 类,然后传递查询对象给 QueryService 类上的 Query 方法。

SPSearch.QueryService search = new SPSearch.QueryService();

Microsoft_Query_Request request = new Microsoft_Query_Request();

search.Query(request);

使用 Java 的例子

通过 Java 来消费 SharePoint 的 Web Services,没有太大的不同;基础步骤基本是相同的,从我提供的 XSD 中生成我们的类,生成 Web Services 代理,并构建应用程序。通过 Java 来消费 SharePoint 的 Web Services,你所要面对的大部分挑战是登录验证和 SharePoint 的 Web Services 中的 DataSet 的使用。有大量的 Java IDE 可以简化 Web Services 的操作,但是由于我目前我主要工作于.NET 中,所以我将演示一个使用 SDK 的例子,而在这个例子中对于 IDE 选择只好留给你了。

注意:: 这个例子是使用 J2SE 6.0 Update 3 来构建和测试的。

Java SharePoint 示例项目目录和根文件

完整的项目和生成文件包含了一些批处理文件以便构建和运行这个例子。你需要编辑"xjc-build.bat"和"build-run.bat",设置其中的 HOME 变量为你的 JDK 的安装目录,以便能正常运行这些批处理文件;另外,在构建和运行示例之前,还要使用你的服务器配置信息(端点、用户名和密码)来编辑 wsspsample/Main.java。

导入服务的 WSDL

由于几个原因,我一开始就把 WSDL 从我的 SharePoint 服务器上取到了我的开发机器上。首先,我需要编辑使用 ADO.NET 数据集的任何 WSDL,以使相关工具能正确处理它。其次,访问位于 SharePoint 服务器上的 WSDL 一般需要进行验证,而 Java 生成的代理在构造器中就需要访问 WSDL,这会为我带来一些验证方面的问题。

获取搜索服务的 WSDL

在 Internet Explorer 打开 Windows SharePoint Services 3.0 的搜索服务,并导航到“Error! Hyperlink reference not valid”上,然后从 File 菜单中选择 Save As...,把这个这个页面保存到工作目录中,命名为 spsearch.wsdl。如果你工作于 MOSS 2007,那么你将使用“Error! Hyperlink reference not valid”。

编辑搜索服务的 WSDL

MOSS 2007 的 QueryEx 方法和 GetSearchMetaData 方法都返回了 ADO.NET 数据集。ADO.NET 数据集是动态包装和表示 WSDL 中对 Schema 属性的循环引用的,所以这会引起我们使用的 JAXB wsimport 工具的一些问题。我发现这个问题在 Java JDK 以前的版本能正常处理,反而我现在使用的这个版本不正常。不过,我选择通过在记事本中编辑 WSDL 来解决这个问题,就是在“element”元素中查找 ref 为"s:schema 的"实例,然后删除循环引用并保留 Schema 中的“any”元素。

<s:sequence>

<s:element ref="s:schema"/>

<s:any/>

</s:sequence>

被更改为如下格式:

<s:sequence>

<s:any minOccurs="0" maxOccurs="unbounded"/>

</s:sequence>

导入 WSDL

现在,我们已经有一个本地的 WSDL 文件了,并进行了恰当的修改,这样我们就可以使用 JAXB 的 wsimport.exe 工具来生成代理类了。

wsimport -p wsspsample.webref.spsearch -keep spsearch.wsdl

wsimport -p wsspsample.webref.search -keep search.wsdl

我们使用 -keep 标志,在导入的时候可以保留 java 代码以便我们能为我们的应用程序调整生成的代码。这个工具使用绝对路径来生成代码,所以如果你打算移动应用程序到不同的目录下,并把 WSDL 和应用程序一起进行保存,那么我们需要编辑"webref\search \QueryService.java"的 Url,并自己构造它。为了解决这个问题,我们只需简单地使用相对路径来代替绝对路径。

url = new URL("file:search.wsdl");

生成请求响应类

为了生成请求和响应类,你需要使用 4 个我创建好的"Microsoft.Search"XSD 文件,以及 JAXB 的 xjc.exe 工具。在下面,我们取消了包级别标注的生成过程,而是指定了一个目标包,并用这个工具创建出我们需要的类。

xjc -npa -p wsspsample.xom.query -d . Microsoft.Search.Query.xsd

xjc -npa -p wsspsample.xom.response -d . Microsoft.Search.Response.xsd

使用生成的类

我们已经有了代表传递到和从 QueryService 服务的 Query 方法返回的查询和响应数据包的类,以及 Query 服务的代理。现在,是时候来把它们用于应用程序里了。我们需要做的第一件事情是创建 QueryService 的实例,这个对象的构造器将获取我们本地的 WSDL 副本,并加载其中的设置。从 QueryService 实例中,我们能通过 getQueryServiceSoap 方法获取到 QueryServiceSoap 的实例。注意,你需要保持 getQueryServiceSoap 的实例,并在我们处理 qsp 变量的时候使用它,这是因为 getQueryServiceSoap 方法总是会返回新的实例。在这里我们能编辑端点地址,以便实现比 WSD 所包含功能更多的事情,这样可以让我们的应用程序更加灵活,从而允许这个应用程序能连接到 WSDL 中未设置的其他 SharePoint 站点和子站点上。

QueryService qs = new QueryService();

QueryServiceSoap qsp = qs.getQueryServiceSoap();

BindingProvider bp = (BindingProvider)qsp;



//bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "Administrator");

//bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "pass@word1");

bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,

"http://barbie/_vti_bin/spsearch.asmx");

现在,我们创建序列化查询数据包和反序列化响应数据包的方法。

public static String SerializeQuery(QueryPacket qp)

{

try

{

JAXBContext jc =JAXBContext.newInstance("wsspsample.xom.query");

Marshaller ma = jc.createMarshaller();

ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);

ByteArrayOutputStream os = new ByteArrayOutputStream();

ma.marshal(qp, os);

return os.toString();

}

catch(JAXBException ex)

{

return "";

}

}

public static ResponsePacket DeserializeResponse(String s)

{

try

{

JAXBContext jc = JAXBContext.newInstance("wsspsample.xom.response");

Unmarshaller um = jc.createUnmarshaller();

StreamSource source = new StreamSource(new StringReader(s));

return (ResponsePacket)um.unmarshal(source);

}

catch (JAXBException ex)

{

return new ResponsePacket();

}

}

从这里开始,我们要来创建 QueryPacket 和所需的类,设置相关的值并调用服务。

// Create a Search Query Packet Object

QueryPacket qp = new QueryPacket();

QueryType qt = new QueryType();

ContextType ct = new ContextType();

QueryTextType ctt = new QueryTextType();

ct.setQueryText(ctt);



qt.setContext(ct);

qp.setQuery(qt);

// Set search values



ctt.setValue("sharepoint");

ctt.setType("STRING"); //This is the default - not necessary

ctt.setLanguage("en-us"); //This is the default - not necessary

// Call the web service query



String sResponse = qsp.query(SerializeQuery(qp));

// Deserialize the response



ResponsePacket resp = DeserializeResponse(sResponse);

构建并运行应用程序

我们已经拥有了生成的 Web Services 代理和查询请求和响应的对象模型,已经使用它们的应用程序,现在我们只需要简单地动下手指头,即可对其进行构建、运行和测试。你需要一个配置好的 SharePoint 服务器,并在 Main.java 中设置正确的端点地址,以及能正确测试 SharePoint 服务器的登录凭据。

参考和链接

Windows SharePoint Services 3.0 Web Services Reference.

查看英文原文Getting Started With SharePoint Web Services

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论