Лабораторная работа № 15
Язык WSDL
Краткий обзор
На данный момент WWW-консорциумом (W3C) утверждена версия WSDL 1.1. Именно ей мы и займемся в этой главе. Естественно, мы не станем разбирать официальную спецификацию языка, это заняло бы слишком много времени. Достаточно лишь на примерах познакомиться с его синтаксисом.
В данном разделе мы лишь рассмотрим схему типичного WSDL-документа. Необходимо признать, что в своей логической форме любые XML- документы, к коим, несомненно, следует отнести и WSDL-документы, достаточно сильно отличаются от HTML-документов, так знакомых любому Web-разработчику. Если HTML-документы описывали лишь отображение некоего блока информации, то XML описывает прежде всего логическую структуру. Поэтому и W SDL-документы мы будем рассматривать с точки зрения их логической структуры.
Теперь вернемся к примеру Web-сервиса, который мы разбирали в лабораторной работе № 12. Так как для разработки было использовано RAD-средство Visual Studio.2010, нам не придется заботиться о собственноручном написании WSDL-файла для этого сервиса. Он был создан автоматически.
|
|
Файл WSDL (Web Service Descriptor Language) является обычным XML- файлом и доступ к нему мы можем получить даже из браузера. Если взглянуть на рис. 12.2 в лабораторной работе № 12, то в верхней части Web-страницы будет видна ссылка Описание службы (Service Description), которая отсылает пользователя как раз к упомянутому WSDL-файлу. Код WSDL-файла, соответствующего нашему Web-сервису, приведен в листинге 15.1.
Листинг 15.1
<?xml version="l.0" encoding="utf-8"?>
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/"
xmlns="http://schernas.xmlsoap.org/wsdl/">
<types>
<s:schema attributeFormDefault="qualified" eiementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name= "MyDate">
<s:complexType>
<s:sequence>
<s:element minQccurs="1" maxOccurs="1" name="ShowTime" type="s:boolean" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="MyDateResponse">
<s:complexType>
<s:sequence>
<s:element minQccurs="1" maxOccurs="1" name="MyDateResult" nillable="true" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />
</s:schema>
</types>
<message name="MyDateSoapIn">
<part name="parameters" element="s0:MyDate" />
</message>
<message name="MyDateSoapOu t">
<part name="parameters" element="s0:MyDateResponse" />
</message>
<message name="MyDateHttpGetIn">
<part name="ShowTime" type="s:string" />
</message>
<message name="MyDateHttpGetOut" >
<part name="Body" element="s0:string" />
|
|
</message>
<message name="MyDateHttpPostln">
<part name="ShowTime" type="s:string" />
</message>
<message name="MyDateHttpPostOut”>
<part name="Body" eiement="s0:string" />
</message>
<portType name="Service1Soap">
<operation name= "MyDate" >
<input message="s0:MyDateSoapln" />
<output message="s0:MyDateSoapOut" />
</operation>
</portType>
<portType name="Service1HttpGet">
<operation name= "MyDate" >
<input message="s0:MyDateHttpGetln" />
<output message="s0:MyDateHttpGetOut" />
</operation>
</portType>
<portType name="Service1HttpPost">
<operation name= "MyDate">
<input message="s0:MyDateHttpPostln" />
<output message="s0:MyDateHttpPostOut" />
</operation>
</portType>
<binding name="Service1Soap" type="s0:Service1Soap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<operation name= "MyDate">
<soap:operation soapAction="http://tempuri.org/MyDate" style="document" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<binding name="Service1HttpGet" type="s0:Service1HttpGet">
<http:binding verb="GET" />
<operation name="MyDate" >
<http:operation location="MyDate" />
<input>
<http:urlEncoded />
</input>
<output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
<binding name="Service1HttpPost" type="s0:Service1HttpPost">
<http:binding verb="POST" />
<operation name="MyDate" >
<http:operation location="MyDate" />
<input>
<mime:content type="application/x-www-form-urlencoded" />
</input>
<output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
<service name="Service1">
<port name="Service1Soap" binding="s0:Service1Soap">
<soap:address location="http://Iocalhost/MyService/Service1.asmx"/>
</port>
<port name="Service1HttpGet" binding="s0:Service1HttpGet">
<http:address location="http://localhost/MyService/Service1.asmx"/>
</port>
<port name="Service1HttpPost" binding="s0:Service1HttpPost">
<http:address location="http://Iocalhost/MyService/Service1.asmx"/>
</port>
</service>
</definitions>
Этот файл полностью описывает функциональность созданного Web-cepвиса. и именно на него будут опираться клиентские приложения для установки связи с сервисом. Достаточно часто WSDL-файлы, описывающие структуру Web-сервисов, называют контрактами.
Теперь попробуем установить его структуру. В WSDL-файлах информация структурируется при помощи всего пяти основных элементов. Если их кратко перечислить, получится следующий список:
□ <types>. Элемент содержит определения типов данных, используемых в данном Web-сервисе.
□ <message>. Элемент содержит абстрактные представления функций Web-сервиса вместе с указанием типов входных и выходных данных.
□ <portType>. Элемент содержит ссылки на искомые функции, описанные в элементе <message> с более подробной структурой их входных и выходных данных.
□ <binding>. Элемент предназначен для связывания содержимого блока <port> с конкретными функциями Web-сервиса. В этих разделах определяются протокол и формат данных для операций, на которые указывает конкретный раздел <port>.
□ <port>. Содержат адреса функций, описанных в элементах <message>. По сути дела, порты описывают точки вхождения в Web-сервис.
□ <service>. Основной элемент, в котором перечисляются конкретные порты, указывающие на прямые URL доступа к функциям сервиса.
Таким образом, мы можем сказать, что первые три элемента — <types>, <message> и <portType> — представляют собой несколько более абстрагированный уровень описания структуры Web-сервиса, а последние два <binding> и <service> — увязывают абстрактную логику с конкретными механизмами доступа к функциональности сервиса.
Помимо этих элементов, создающих в WSDL- документе целые разделы, есть и отдельный блок, который нельзя отнести ни к какому разделу. Он выглядит следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns: mime="http: / / schemas. xmlsoap. org / wsdl /mime / "
xmlns: tm="http: //microsoft.com/wsdl/mime/textMatching/"
|
|
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:s0="http://tempuri.org/" targetNamespace="http://tempuri.org/"
xmlns="http://sсhemas.xmlsoap.org/wsdl/">
Первая строка, естественно, мгновенно узнается каждым, кто знаком с языком XML. Это стандартное объявление XML-документа. Второй тег содержит определения всех используемых в WSDL-документе пространств имен. Легко заметить, что определения большей части объявляемых пространств имен располагаются на ресурсе с доменным именем schemas.xmlschemas.org. Особое внимание здесь следует обратить на объявление пространства имен s0. так как именно оно будет чаше всего использоваться в нашем примере для объявления типов переменных.
О самих типах переменных мы будем говорить в следующем разделе, а пока что стоит отметить, что WSDL поддерживает все типы, определяемые спецификацией ХМL Schema, располагающейся но адресу http://www.w3.org/2001/XMLSchema. Чаше всего для указания типов данных стоит использовать именно это пространство имен. Его мы и объявили для идентификатора s в самом первом параметре тега <definitions>.
Если обратиться к листингу 3.1, то в нем с легкостью обнаружатся все вышеописанные структуры. Впрочем, невооруженным глазом видно, что содержимое этих элементов далеко не всегда можно признать интуитивно понятным и прозрачным. Поэтому требуется рассмотреть их тщательнее. Начнем мы с рассмотрения структуры элемента<types>.
Структура элемента <types>
Элемент <types> является основой всего WSDL-файла. Именно в этом разделе определяются все типы данных, которые будет использовать сервис. Если учесть, что хороший сервис должен обладать достаточно богатым набором функций и выполнять сложные операции, станет понятно, что описание всех его типов данных, среди которых, естественно, могут быть и достаточно объемные составные типы, может занять весомую долю всего WSDL-файла.
Рассмотрим подробнее этот блок, позаимствовав его из нашего примера. Вот как он выглядит:
<types>
<s:schema attributeFormDefault="qualified" eiementFormDefault="qualified" targetNamespace="http://tempuri.org/">
|
|
<s:element name= "MyDate">
<s:complexType>
<s:sequence>
<s:element minQccurs="1" maxOccurs="1" name="ShowTime" type="s:boolean" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="MyDateResponse">
<s:complexType>
<s:sequence>
<s:element minQccurs="1" maxOccurs="1" name="MyDateResult" nillable="true" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="string" nillable="true" type="s:string" />
</s:schema>
</types>
Легко заметить, что все содержимое блока, ограниченного тегами <types> и < /types>, создано с использованием пространства имен s, которое было объявлено в теге <definitions>. Это пространство имен, специфицированное, как мы уже знаем, в XML Schema, как раз и позволяет нам использовать типы данных, определенные в этом подмножестве языка XML.
Затем при помощи тегов <s:schema> и </s:schema> определяется тип для всего сервиса. Это можно сравнить с определением основного класса для обычного приложения. Отдельные элементы этого типа объявляются при помощи тегов <s:element>. При помощи атрибутов name объявляются наименования этих элементов. Следует также обратить внимание на параметр targetNamespace, входящий в состав объявляющего тега <s:schema>, который задает целевое пространство имен, используемое в данном блоке по умолчанию.
Элемент с наименованием MyDate, как легко догадаться, объявляет саму основную функцию нашего Web-сервиса. Внутри раздела этого объявления указывается комплексный тип данных для вложенного элемента с наименованием showTime. В объявлении элемента showTime присутствует дополнительный атрибут type, которому приписано значение "s:boolean". Естественно, подобным способом объявляется параметр, передаваемый нашей функции.
Итак, на основе анализа объявления первого элемента, мы знаем, что Web- сервис обладает функцией MyDate, которой передается параметр логического типа Boolean с наименованием ShowTime.
Следующим в блоке <types> объявляется элемент с наименованием MyDateResponse. Подобным образом обозначается элемент, отвечающий за возвращаемое значение. То есть, первый элемент содержит описание входных данных, а второй элемент описывает выходные данные. Таким образом, анализ объявления элемента MyDateResponsе показывает, что в нем располагается определение еще одного элемента с наименованием MyDateResult типа String.
Резюмируем. Блок входных данных содержит элементы, наименования которых опираются на стандартные наименования функций и параметров, указанных в исходном коде самого Web-сервиса. Наименования выходных данных создаются на основе имени функции из первого блока. То есть, для функции MyDate элемент, отвечающий за передачу результата ее работы, носит наименование MyDateResponse, а результат выполнения функции носит наименование MyDateResult.
Теперь следует перейти к рассмотрению различных типов данных, которые могут использоваться в WSDL-документах.