Для того чтобы начать создавать и использовать 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.
ЛИСТИНГ 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, которая появится в ближайшие годы. |