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。
服务 | 管理用途 |
(_vti_adm/Admin.asmx) | 创建删除站点的管理方法,获取被部署的SharePoint的语言
|
通知 (Alerts.asmx) | 用于操作SharePoint通知列表项的方法
|
验证 (Authentication.asmx) | 客户端代理为使用窗体验证的站点提供用户验证的方法
|
复制 (Copy.asmx) | 在站点之间或内部复制文件的方法
|
文档工作区 (Dws.asmx) | 管理文档工作区站点和数据的方法
|
窗体 (Forms.asmx) | 当工作于某个列表内容时,返回用在这个用户界面中的窗体信息的方法
|
图像 (Imaging.asmx) | 创建和管理图片库的方法
|
获取列表数据 (DspSts.asmx) | 完成对站点和SharePoint中的列表的查询
|
列表 (Lists.asmx) | 对列表和列表数据进行操作的方法
|
会议 (Meetings.asmx) | 创建和管理会议工作区站点
|
人员 (People.asmx) | 解析和查找安全主体
|
权限 (Permissions.asmx) | 处理站点或列表权限的方法
|
目录管理 (sharepointemailws.asmx) | 管理活动目录e-mail分发组和他们的成员信息的方法
|
站点数据 (SiteData.asmx) | 从站点或列表中返回元数据或列表数据的方法
|
站点 (Sites.asmx) | 返回关于站点集和站点模板的信息的方法
|
搜索 (spsearch.asmx) | 使用搜索服务进行搜索的方法
|
用户和用户组 (usergroup.asmx) | 操作用户角色定义和用户组的方法
|
版本 (Versions.asmx) | 操作文件版本的方法
|
视图 (Views.asmx) | 操作列表视图的方法
|
Web 部件页 (WebPartPages.asmx) | 操作Web 部件页的方法
|
Web应用程序 (Webs.asmx) | 操作站点和子站点的方法 |
MOSS搜索 (Search.asmx) | 通过MOSS(Microsoft Office SharePoint Server)搜索服务进行搜索的方法,它们也包含获取被管理搜索属性的方法
|
现在,我们已经对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中消费SharePoint Web Services是相当简单而直接的,你只需简单地添加Web引用,并使用生成的代理。不过,我们将多做一步来用XSD生成一组表示查询和应答的类,其能序列化出发送和返回的XML。
Visual Studio包含了一个名为XSD.exe的工具,其能被用于根据XSD生成.NET类型。不过这是一个命令行工具,但我喜欢把他添加为Visual Studio的一个菜单选项,以便能在IDE中执行它。如果你已经完成了这个步骤,或者你已经有一些添加插件这样的经验,你就可以跳过这步。
属性 | 值 |
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中生成.NET类型。现在我们已经有了XSD,我们将创建一个Windows Forms项目,并从下载的XSD中生成.NET类型。在打开Microsft.Search.Query.xsd之后,到工具菜单中选择我们上一步创建的XSD菜单项,以生成Microsoft_Search_Query.cs文件。
我们现在可以通过在“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来消费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从我的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