Алексей Федоров, КомпьютерПресс
Для того чтобы начать создавать и использовать Web-сервисы,
нет необходимости дожидаться выхода финальной версии Microsoft .NET - такие
сервисы могут быть созданы уже сегодня. Например, чтобы создать новую модель
вашего Web-приложения, которая будет совместима с концепциями сервисоориентированного
Web, достаточно решить, какие части приложения будут реализованы в виде сервисов,
определить интерфейсы и задать спецификацию выходной информации. В этой статье
мы рассмотрим, как создать простой Web-сервис средствами Active Server Pages
(ASP), и напишем код сервера и потребителя.
По определению Web-сервис - это код, доступный по протоколу HTTP и возвращающий
информацию в формате XML. Идея создания Web-сервисов, решающих многие стандартные
задачи, очень привлекательна - в этом случае мы получаем программируемые Web-приложения,
которые могут располагаться где угодно и работать на любых платформах. Отметим,
что «каноническое» определение Web-сервиса включает поддержку протокола SOAP
для реализации возможностей вызова удаленных объектов, а также протоколов DISCO
и UDDI для реализации возможностей поиска сервисов как на одном Web-узле, так
и в Internet в целом. Сервис, который мы создадим с помощью данной статьи, не
обладает такой функциональностью; как уже было сказано выше, нашей задачей будет
тестирование концепции сервиса как такового.
Сервер
Сервис, реализованный в нашем примере, будет выполнять конвертацию из одной
валюты в другую и возвращать собственно результат конвертации, текущий курс
и текстовую строку, содержащую результат конвертации.
При вызове нашего сервиса мы указываем три параметра: Amount, From и To. Первый
параметр указывает сумму, которую необходимо перевести, второй и третий - коды
валюты. Мы используем коды валюты, определенные стандартом 4217. Данные о текущем
курсе содержатся в таблице SQL Server, которая имеет формат, показанный в таблице.
Curr |
CurrName |
USDUnit |
UnitsUSD |
USD |
United States Dollars |
1.0 |
1.0 |
ATS |
Austria Schillings |
6.5256499999999995E-2 |
15.3241 |
BEF |
Belgium Francs |
2.2259600000000001E-2 |
44.924500000000002 |
GBP |
United Kingdom Pounds |
1.42357 |
0.70245999999999997 |
EUR |
Euros |
0.897949 |
1.11365 |
FRF |
France Francs |
0.13689100000000001 |
7.3050600000000001 |
DEM |
Germany Deutsche Marks |
0.45911400000000002 |
2.1781100000000002 |
ITL |
Italy Lire |
0.000463752 |
2156.3299999999999 |
ESP |
Spain Pesetas |
5.3967800000000003E-3 |
185.29599999999999 |
CHF |
Switzerland Francs |
0.586113 |
1.7061599999999999 |
Таблица обновляется раз в день на основе данных, поступающих от одного из провайдеров
финансовой информации (еще один Web-сервис!).
Как мы отмечали выше, наш Web-cервис будет реализован средствами Active Server
Pages. Ниже мы детально рассмотрим ASP-код, реализующий данный сервис.
Поскольку сервис должен возвращать данные в формате XML, мы должны указать тип
возвращаемой информации:
Response.ContentType = "text/xml"
Далее мы обрабатываем переданные потребителем параметры (в нашем случае параметры
передаются как часть URL, но могут передаваться и внутри HTTP-запроса).
Amount = Request.QueryString("Amount")
CurrFrom = Request.QueryString ("From")
CurrTo = Request.QueryString ("To")
Мы готовы обратиться к базе данных за информацией о текущем курсе. Для этого
используем стандартные объекты ADO и простой SQL-запрос, возвращающий набор,
состоящий из двух записей:
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Provider = "SQLOLEDB"
ProvStr = "Server=jupiter;Database=WebDemo;Trusted_Connection=yes"
Conn.Open ProvStr
Set RS = Server.CreateObject("ADODB.Recordset")
Query = "SELECT * FROM Curr WHERE Curr='" & CurrFrom & _
"' OR Curr='" & CurrTo & "'"
RS.ActiveConnection = Conn
RS.Source = Query
RS.Open
DataTo = RS("USDUnit")
RS.MoveNext
DataFrom = RS("USDUnit")
DataTo = RS("USDUnit")
RS.Close
Conn.Close
Set Conn = Nothing
После этих несложных манипуляций переменная Amount содержит сумму, которую необходимо
переконвертировать, DataFrom - курс исходной валюты, а переменная DataTo - курс
результирующей валюты. Таким образом, код для получения результата будет выглядеть
так:
Result = FormatNumber(Amount * (DataFrom / DataTo), 2)
Здесь мы используем функцию FormatNumber для задания числа символов после запятой.
Итак, мы собрали всю информацию, необходимую для создания XML-документа, передаваемого
потребителю. Можно начать создавать этот документ. В нашем примере мы будем
использовать Microsoft XML DOM, хотя можно обойтись и простой конкатенацией
строк.
' Начнем создавать XML-документ
Set XMLDoc = Server.CreateObject("Microsoft.XMLDOM")
Set pi = XMLDoc.createProcessingInstruction("xml",
" version=""1.0"" encoding=""Windows-1252""")
XMLDoc.appendChild(pi)
' Главная ветвь
Set mainNode = XMLDoc.createElement("conversion")
XMLDoc.appendChild(mainNode)
Приведенный выше код создает экземпляр Microsoft XML DOM. После этого, используя
метод createProcessingInstruction, мы создаем заголовок документа и добавляем
его к нашему документу. Далее создаем главную ветвь - <conversion> и также
добавляем ее к документу. Вся информация будет храниться в дочерних ветвях данной
ветви. Чтобы добавить одну или более дочерних ветвей, мы создадим следующую
функцию:
Sub AddSubNode(Parent, Name, Value)
Set subNode = XMLDoc.createElement(Name)
Parent.appendChild(subNode)
subNode.appendChild(XMLDoc.createTextNode(Value))
End Sub
а затем воспользуемся ею для генерации дочерних ветвей нашего документа:
AddSubNode mainNode, "from", CurrFrom
AddSubNode mainNode, "to", CurrTo
AddSubNode mainNode, "amount", Amount
AddSubNode mainNode, "result", Result
AddSubNode mainNode, "usdFrom", DataFrom
AddSubNode mainNode, "usdTo", DataTo
AddSubNode mainNode, "rate", FormatNumber(DataFrom / DataTo, 4)
AddSubNode mainNode, "text", CStr(Amount) & " " & CurrFrom & _
" = " & Result & " " & CurrTo
И наконец, мы можем вернуть готовый документ потребителю:
Response.Write XMLDoc.XML
Если в качестве потребителя мы будем использовать браузер Microsoft Internet
Explorer и зададим следующий адрес (перевести 20 швейцарских франков в евро):
http://jupiter/demos/service/server.asp?Amount=20&From=CHF&To=EUR
то получим следующий XML-документ:
<?xml version="1.0"?>
<conversion>
<from>CHF</from>
<to>EUR</to>
<amount>20</amount>
<result>13.05</result>
<usdFrom>0.586113</usdFrom>
<usdTo>0.897949</usdTo>
<rate>0.6527</rate>
<text>20 CHF = 13.05 EUR</text>
</conversion>
Microsoft Internet Explorer отобразит этот документ, как показано на рис.1.

Рис.1.
Полный код, реализующий наш Web-сервис, приведен в листинге 1.
ЛИСТИНГ 1.
<%
Response.ContentType = "text/xml"
'--------------------------------------
' Web Service Provider
'
' Parameters:
'
' Amount = Amount to convert
' From = Source Currency
' To = Target Currency
'--------------------------------------
Sub AddSubNode(Parent, Name, Value)
Set subNode = XMLDoc.createElement(Name)
Parent.appendChild(subNode)
subNode.appendChild(XMLDoc.createTextNode(Value))
End Sub
Amount = Request.QueryString("Amount")
CurrFrom = Request.QueryString ("From")
CurrTo = Request.QueryString ("To")
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Provider = "SQLOLEDB"
ProvStr = "Server=jupiter;Database=WebDemo;Trusted_Connection=yes"
Conn.Open ProvStr
Set RS = Server.CreateObject("ADODB.Recordset")
Query = "SELECT * FROM Curr WHERE Curr='" & CurrFrom & _
"' OR Curr='" & CurrTo & "'"
RS.ActiveConnection = Conn
RS.Source = Query
RS.Open
DataTo = RS("USDUnit")
RS.MoveNext
DataFrom = RS("USDUnit")
RS.Close
Conn.Close
Set Conn = Nothing
Result = FormatNumber(Amount * (DataFrom / DataTo), 2)
' Начнем создавать XML-документ
Set XMLDoc = Server.CreateObject("Microsoft.XMLDOM")
Set pi = XMLDoc.createProcessingInstruction("xml",
" version=""1.0"" encoding=""Windows-1252""")
XMLDoc.appendChild(pi)
' Главная ветвь
Set mainNode = XMLDoc.createElement("conversion")
XMLDoc.appendChild(mainNode)
AddSubNode mainNode, "from", CurrFrom
AddSubNode mainNode, "to", CurrTo
AddSubNode mainNode, "amount", Amount
AddSubNode mainNode, "result", Result
AddSubNode mainNode, "usdFrom", DataFrom
AddSubNode mainNode, "usdTo", DataTo
AddSubNode mainNode, "rate", FormatNumber(DataFrom / DataTo, 4)
AddSubNode mainNode, "text", CStr(Amount) & " " & CurrFrom & _
" = " & Result & " " & CurrTo
Response.Write XMLDoc.XML
Set mainNode = Nothing
Set XMLDoc = Nothing
%>
После того как мы реализовали наш Web-сервис, мы должны написать код для потребителя
этого сервиса. Рассмотрим этот вопрос в следующем разделе.
Потребитель
Как мы определили в начале этой статьи, потребитель Web-сервиса должен посылать
сервису HTTP-запрос и получать результат в виде XML-документа. После этого потребитель
должен обработать полученный XML-документ и извлечь из него необходимые данные.
Для посылки HTTP-запроса мы будем использовать методы, реализованные в объекте
ServerXMLHTTP, который является частью Microsoft XML DOM (см. врезку), а для
обработки XML-документа - методы объекта DOMDocument.
Начнем с того, что создадим экземпляры двух упомянутых выше объектов:
Set HTTPReq = Server.CreateObject("MSXML2.ServerXMLHTTP")
Set XMLDoc = Server.CreateObject("MSXML2.DOMDocument")
Далее мы генерируем HTTP-запрос - этот процесс состоит из вызова двух методов
объекта ServerXMLHTTP - Open для задания метода передачи информации и адреса
и Send для непосредственной отсылки запроса.
HTTPReq.Open "POST", "http://jupiter/demos/service/server.asp" & _
"?Amount=200&From=FRF&To=USD", False
HTTPReq.Send
Возвращаемый нашим сервисом XML-документ может быть получен либо как значение
свойства ResponseXML, либо - как значение свойства ResponseText. И в том и в
другом случае мы загружаем этот документ в экземпляр объекта DOMDocument.
XMLDoc.LoadXML HTTPReq.ResponseText
Объект произведет необходимую обработку XML-документа, после чего мы сможем
извлечь из него данные:
Set Node = XMLDoc.selectSingleNode("/conversion/text")
Response.Write Node.Text
Отметим, что в вышеприведенном фрагменте мы извлекаем текстовую строку, которая
для нашего примера будет выглядеть так:
20 CHF = 13.05 EUR
Помимо этого при обращении к ветви result мы можем получить только результат
конвертации, а при обращении к ветви rate - текущий курс.
Полный код, реализующий потребителя нашего Web-сервиса, приведен в листинге
2.
ЛИСТИНГ 2
<%
'------------------------------
' Currency Service Consumer
'------------------------------
Set HTTPReq = Server.CreateObject("MSXML2.ServerXMLHTTP")
Set XMLDoc = Server.CreateObject("MSXML2.DOMDocument")
HTTPReq.Open "POST", "http://jupiter/demos/service/server.asp" & _
"?Amount=200&From=FRF&To=USD", False
HTTPReq.Send
XMLDoc.LoadXML HTTPReq.ResponseText
Set Node = XMLDoc.selectSingleNode("/conversion/text")
Response.Write Node.Text
Set Node = Nothing
Set HTTPReq = Nothing
Set XMLDoc = Nothing
%>
Завершая обсуждение реализации потребителя Web-сервиса, отметим, что можно передавать
параметры и как часть HTTP-запроса (а не как часть URL). Для этого необходимо
изменить код генерации HTTP-запроса на следующий:
HTTPReq.Open "POST", "http://jupiter/demos/service/curr2.asp", False
HTTPReq.SetRequestHeader "Amount", "20"
HTTPReq.SetRequestHeader "From", "FRF"
HTTPReq.SetRequestHeader "To", "USD"
HTTPReq.Send
Поскольку в этом случае параметры передаются как часть HTTP-запроса, необходимо
также изменить код обработки параметров в сервере:
Amount = Request.ServerVariables("HTTP_Amount")
CurrFrom = Request("HTTP_From")
CurrTo = Request("HTTP_To")
Какой из вариантов передачи параметров использовать в том или ином случае -
передавать параметры через URL либо внутри HTTP-запроса - решать вам: приведенное
выше решение поддерживает оба способа.
Заключение
В данной статье мы рассмотрели возможности создания Web-сервиса и потребителя
данного сервиса, чтобы уже сегодня можно было начать предварительное тестирование
новой архитектурной модели Web, которая появится в ближайшие годы.
|