[转帖]WebLogic Workshop实现对.NET Web服务互操作_Tomcat, WebLogic及J2EE讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Tomcat, WebLogic及J2EE讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 4056 | 回复: 0   主题: [转帖]WebLogic Workshop实现对.NET Web服务互操作        下一篇 
white
注册用户
等级:少校
经验:1327
发帖:305
精华:0
注册:2011-7-21
状态:离线
发送短消息息给white 加好友    发送短消息息给white 发消息
发表于: IP:您无权察看 2011-8-9 15:21:25 | [全部帖] [楼主帖] 楼主

Web服务应该允许不同供应商提供的应用能够在完全不同的硬件平台上运行,可以相互找到对方,并通过一套公共的协议和数据格式实现通信,这些协议包括SOAP,UDDI和WSDL。本文将展示Miscrosoft的.NET平台上的Web服务和BEA的WebLogic平台之间的互操作是如何实现的。首先介绍的是怎样在各个平台上创建Web服务定义语言(Web Services Definition Language,WSDL)文件,接着讨论如何使用WSDL文件调用在各个平台上的Web服务。最后,我将演示每个平台所具有的强大而不标准的特性如何被其他平台使用。 

    两个简单的web服务

    在第一个例子中,我们将创建两个非常相似的Web服务,一个在.NET下创建,另一个在WebLogicshop下创建。这些Web服务都只有一个方法:getHelloMessage,该方法将返回一个问候消息框。在本例中,我们将展示如何通过其他平台分别调用这些Web服务。 

    以下是WebLogic Workshop服务的代码: 

public class WLWExample
{
      public String getHelloMessage()
{ return "Hello from WebLogic Workshop!"; }}


    以下是.NETWeb服务的代码: 

using System.ComponentModel;
using System.Web.Services;
namespace DotNetExample
{
      public class Service1 : WebService
      {
            public Service1()
      { InitializeComponent(); }
            private IContainer components = null;
      private void InitializeComponent() {}
            protected override void Dispose( bool disposing )
            { if(disposing && components != null) components.Dispose();
            base.Dispose(disposing); }
            [WebMethod] public string getHelloMessage()
      { return "Hello from Visual Studio .NET!"; } }}


    为了写出能调用这些服务的代码,我们首先必须快速地了解一下Web服务互操作的工作原理。 

    Web服务如何互操作?

    Web服务互操作的核心是Web服务定义语言(WSDL)。WSDL是一种XML语言,它允许Web服务以一种与平台无关的方式发布其公共约定。WSDL语言用于描述Web服务提供的方法,以及该方法可以产生和接收的消息。WSDL是两个不同Web服务用以向对方描述各自的Web服务的公共格式。 

    为实现上述两个Web服务的跨平台调用,首先必须为这两个Web服务生成WSDL文件。在WebLogic Workshop上和Visual Studio .NET上,这一过程稍微有些不同,但都很简单。 

    在WebLogic Workshop上创建WSDL

    1. 在项目树上,右键单击Web服务,选择“Generate WSDL from JWS”(从JWS生成WSDL)。这样就可以为Web服务创建一个WSDL。每创建一个WSDL,项目树都会将其作为Web服务的子项显示出来。 

    WebLogic Workshop使用一种特殊的命名约定为WSDL文件和CTRL文件(后面将加以讨论)命名。如果Web服务名为Service.jws,那么该服务的WSDL文件将被命名为ServiceContract.wsdl,而CTRL文件将被命名为ServiceControl.ctrl。

    在Visual Studio .NET中创建WSDL

    1. 从菜单中选择Debug/Start或者按F5,在浏览器中打开Web服务。 

    2. 右键单击IE中的“Service Description”链接,选择“Save Target AS”。输入文件名,注意该文件名的后缀应为.wsdl。 
    即使最简单的Web服务,它的WSDL文件也是非常复杂的。幸运的是,我们在使用使用Web服务时不需要知道WSDL的详细情况。感兴趣的读者,可以在http://www.w3.org/TR/wsdl上找到完整的WSDL规范。 

    在WebLogic Workshop上调用.NET服务

    WegLogic Workshop和Visual .NET都各有一套机制,通过这种机制可以使用WSDL以及调用该WSDL所指向的Web服务。在WebLogic Workshop下,必须创建一个服务控件(Service Control);在Visual .NET中,对应的是Web引用(Web Reference)。本节将讨论如何为WSDL文件创建服务控件,该服务控件可用于下层的Web服务。下一节将讨论Web引用。 

    从WSDL创建服务控件

    1. 在设计视图中,单击下拉菜单中的“Add Control”,并选择“Service Control”。 

    2. 在第一个文本框中输入控件的变量名,该变量名将用于指向源代码中的控件。 

    3. 选择组合框中的“Create a service control from a WSDL”选项,并在文本框中输入WSDL的路径。也可以通过“Browse”按钮来查找WSDL的位置。 

    4. 单击“Create”按钮。 

    当创建服务控件时,在Web服务中将会增加以下一行代码: 

public String callDotNet(){ return dotNetExample.getHelloMessage(); }


    完成这些步骤之后,就应该可以得到这样的一个WebLogic Workshop Web服务: 

public class WLWClient{ private DotNetExampleControl dotNetExample;
public String callDotNet() { return dotNetExample.getHelloMessage(); }}


    如果.NET Web服务正在运行,你应该就可以运行上述Web服务了,并且可以通过callDotNet方法跨平台调用.NET Web服务。CallDotNet方法将返回一个响应消息,该消息包含了.NET的问候消息: 

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Body> <getHelloMessageResponse xmlns="http://tempuri.org/"> <getHelloMessageResult> Hello from VisualStudio.NET! </getHelloMessageResult> </getHelloMessageResponse> </soap:Body></soap:Envelope>


    从.NET调用WebLogic Workshop服务

    前面我们在WebLogic Workshop平台上调用了一个.NET平台上的Web服务,接下来将介绍在.NET平台上调用WebLogic Workshop平台上的Web服务。在WebLogic Workshop上,我们通过服务控件来调用外部的另一个Web服务;在.NET上,我们将采用Web引用。

    从WSDL创建Web引用

    1. 打开“Project”菜单,选择“Add Web Reference”。 

    2. 在弹出的对话框中,你可以浏览各种Web服务。请在地址文本框中输入WSDL文件的路径,该WSDL文件是你为WebLogic Workshop Web服务创建的。 

    3. 选择“Add Reference”按钮。 

    这样就为你的项目添加了一个指向WebLogic Workshop Web服务的Web引用。在默认情况下,该引用命名为WebReference1。通过Solution Explorer,你可以看到这个新创建的引用已经被添加到项目里面了,在引用的下方,你可以找到该引用所出自的WSDL。 

    在C#中,你可以像使用其他任何对象一样来使用Web引用。首先,必须将Web引用导入到源文件中。你可以在C#文件中添加下面这行代码: 

 using DotNetClient.WebReference1;


    将引用导入到源文件之后,就可以创建该Web引用的一个新的实例,并通过这个实例调用WebLogic Workshop上的Web服务。下面的代码演示了一个用C#描述的完成这些工作的Web服务: 

using System.ComponentModel;
using System.Web.Services;
using DotNetExample.WebReference1;
namespace DotNetClient
{ public class Service1 : WebService
      { public Service1()
      { InitializeComponent(); }
            private IContainer components = null;
            private void InitializeComponent()
      {}
            protected override void Dispose( bool disposing )
            { if(disposing && components != null) components.Dispose();
            base.Dispose(disposing); }
            private WLWExample wlwExample = new WLWExample();
      [WebMethod] public DataSet callWLW() { wlwExample.getHelloMessage(); } }}


    如果调用了callWLW方法,就可以收到来自WebLogic Workshop Web服务的问候消息。 

<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/"> Hello from WebLogic Workshop!</string>


    从.NET调用会话Web服务 

    在WebLogic Workshop上使用会话(conversation)比较简单,而且是透明的。但是,如果要在.NET上调用会话Web服务,就必须做一些额外的工作,确保会话功能的一致性。 

    当Web服务的一个客户端调用会话方法时,WebLogic Workshop通过会话键(Conversation key)来决定要调用的会话方法是哪一个。会话键是嵌入在送往Web服务的SOAP消息的头部的。对于start方法,头部的格式如下: 

<StartHeader>
<conversationID>convID</conversationID>
<callbackLocation>callback</callbackLocation>
</StartHeader>


    会话ID和调用返回点(Callback location)都是可选的。如果你没有提供会话ID,WebLogic Workshop将自动生成一个会话ID。调用返回点用于指定WebLogic Workshop将调用返回的消息发往的地点。 

    对于continue方法,会话头部的格式如下: 

<ContinueHeader>
<conversationID>convID</conversationID>
</ContinueHeader>


    调用continue方法时,必须指定会话ID,因为你需要通过某种途径告诉WebLogic Workshop当你调用continue方法时你要加入哪一个会话。调用返回点并不是必不可少的,因为在对start方法的调用中已经指定了。 

    向.NET Web服务的客户端添加SOAP头部相当简单。会话Web服务所对应的WSDL文件已经指明了start头部和continue头部的结构,因此.NET现在就可以知道这些头部的格式了。当.NET创建一个Web引用时,对应于WSDL中指明的每个SOAP头部,.NET就为该Web引用添加一个相应的域: 

// A web reference to a conversational web service.private WLWExample wlwExample;
[WebMethod] public void callStartMethod()
{ wlwExample.StartHeaderValue = new WebReference1.StartHeader();
      wlwExample.StartHeaderValue.conversationID = “convID”;
      wlwExample.StartHeaderValue.callbackLocation = “callbackLoc”;
wlwExample.startMethod();}


    在本例中假设Web引用名为WebReference1,所指向的Web服务名为WLWExample,这与上一个例子一样。WLWExample有一个名为startMethod的方法,该方法用于开始一个对话。对于例中的字符串“convID”和“callbackLoc”,应该用实际需要的会话ID和调用返回点替换。 

    你可以用极其相似的代码(将StartHeaderValue替换为ContinueHeaderValue)来调用后面的方法。

在WebLogic Workshop上使用.NET数据集

    数据集(DataSet)是一种Microsoft活动数据对象(Microsoft Active Data object),用于实现一种常见的对数据的相关包装器(relational wrapper)。数据集将数据装在一套表中,这些表的结构跟SQL语言中表的结构很相似,这些表都有一些特定的列,按特定的次序排列,每列对应于一种特定类型。数据集对象为装载和操作数据提供了极大的便利。然而,考虑到本文的目的,我们对此不再赘述,而是将注意力放到数据集的串行化机制上来。 

    创建一个简单的数据集

    一开始,我们要创建一个简单的用于描述一个电话本的数据集,并填上一些简单的示范数据。接着从一个Web服务中返回这个数据集,注意数据集是如何串行化到XML中的。 

[WebMethod] public DataSet getDataSet()
{ // Create a new data set and add a table to it.
      DataSet dataSet = new DataSet("MyDataSet");
      DataTable table = dataSet.Tables.Add("PhoneBook");
      // Create the columns of the table.
      DataColumn primaryKeyCol = table.Columns.Add("ID", typeof(int));
      table.Columns.Add("Name", typeof(string));
      table.Columns.Add("Telephone", typeof(string));
      // Set the ID field as the primary key.
table.PrimaryKey = new DataColumn[] { primaryKeyCol };
      // Create some bogus data.
table.LoadDataRow(new object[] {1, "Fred", "555.2145"}, true);
table.LoadDataRow(new object[] {2, "Bob", "555.6246"}, true);
table.LoadDataRow(new object[] {3, "Howard", "555.1125"}, true);
table.LoadDataRow(new object[] {4, "Stanley", "555.0932"}, true);
// Return the data set to the caller. return dataSet;}


    这个数据集的规划很简单��数据集中只有一个名为“PhoneBook”的表,该表包含了三列。一列为ID,该列将作为关键字;一列为Name,还有一列为Telephone。在数据集中我们已经添加了一些简单的数据。当调用上述方法时,将返回以下XML: 

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
<xs:schema id="MyDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="MyDataSet" msdata:IsDataSet="true">
<xs:complexType> <xs:choice maxOccurs="unbounded">
<xs:element name="PhoneBook"> <xs:complexType>
<xs:sequence> <xs:element name="ID" type="xs:int" />
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="Telephone" type="xs:string" minOccurs="0" />
</xs:sequence> </xs:complexType> </xs:element> </xs:choice>
</xs:complexType> <xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//PhoneBook" /> <xs:field xpath="ID" />
</xs:unique> </xs:element> </xs:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <MyDataSet xmlns="">
<PhoneBook diffgr:id="PhoneBook1" msdata:rowOrder="0">
<ID>1</ID> <Name>Fred</Name> <Telephone>555.2145</Telephone>
</PhoneBook>> <PhoneBook diffgr:id="PhoneBook2" msdata:rowOrder="1">
<ID>21</ID> <Name>Bob</Name> <Telephone>555.6246</Telephone>
</PhoneBook> <PhoneBook diffgr:id="PhoneBook3" msdata:rowOrder="2">
<ID>3</ID> <Name>Howard</Name>
<Telephone>555.1125</Telephone> </PhoneBook>
<PhoneBook diffgr:id="PhoneBook4" msdata:rowOrder="3">
<ID>4</ID> <Name>Stanley</Name>
<Telephone>555.0932</Telephone> </PhoneBook>
</MyDataSet> </diffgr:diffgram></DataSet>


    这个数据集的XML编码分为两部分。一部分是规划,描述了XML编码的结构;另一部分是数据集的实体。本文将略去规划部分,假定规划是已知的,这里仅仅着重考虑数据编码本身。在一些更复杂的应用中,通过规划来做一些其他的事情通常是很有用的。 

    通过灵活地反复使用以下格式的元素,就可以将创建好的表中的数据编码成非常简单的格式: 

<PhoneBook> <ID></ID> <Name></Name> <Telephone></Telephone></PhoneBook>


    如果我们已经知道了XML的形式,就可以编写一个能获取并使用这些数据的WebLogic Workshop Web服务。 

    用XML映像(XML Map)提取数据

    通过WebLogic Workshop的XML映射技术,我们可以提取这些数据,并将其存入到用于表示电话本实体的Java对象中。下面的代码将完成这项工作: 

public static class PhoneBookEntry{ public int id; public String name; public String phoneNumber;}


    为了对引入的XML进行解码,我们将用到一个XML映像。以下XML映像可以作为服务控件的返回映像,这个服务控件是用于调用可返回数据集的.NET Web 服务的。 

public PhoneBookEntry[] getDataSet();


    该映像需添加到.NET Web服务对应的CTRL文件中的getDataSet方法中。这个映像看起来可能有些复杂,但这的的确确就是要演化为.NET Web服务返回的用于获取电话本条目部分的XML。接着用一个xm:multiple属性将每个电话本条目的数据绑定到由映像-增强(map-enhanced)getDataSet返回的一个数组的元素上。 

    你可能已经注意到,这个映像建议的XML形式与之前我展示过的那个映像略有出入。不幸的是,WebLogic Workshop收到的SOAP消息看上去与.NET的Web界面所显示的XML形式有所不同。你可以通过在WebLogic Workshop上的Web服务中调用.NET的Web服务方法来找到WebLogic Workshop所收到的消息,并使用测试视图查看.NET返回的XML形式。 

    结论

    互操作性在Web服务中非常重要,而通过WebLogic Workshop可以非常容易地实现对其他Web服务的互操作。在本文中我们讨论了为实现对.NET的互操作需要做那些工作,实际上,这些原理同样适用于其他任何可以产生有效WSDL的Web服务产品。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论