Содержание


Совместное использование Ajax и Web-сервисов

Совместно использовать эти две передовые технологии легче, чем вы думали

Comments

Что такое Web-сервис?

Web-сервис является способом организации доступа к функциям приложения из Интернета. Web-сервисы работают на основе открытых протоколов, поэтому любое приложение, имеющее доступ в Web, может получить доступ к Web-сервису.

Типичное взаимодействие с Web-сервисом инициируется клиентом (удаленным приложением, использующим Web-сервис), который посылает сервису XML-сообщение. Сервис разбирает сообщение и посылает на него ответ, также в формате XML. Потребитель затем анализирует ответ и каким-либо образом использует полученную от сервиса информацию.

Часто в Web-сервисах используется разновидность языка XML, называемая SOAP. SOAP изначально расшифровывался как Simple Object Access Protocol (протокол простого доступа к объектам), однако в дальнейшем от этого по определенным причинам отказались. Этот протокол состоит из трех частей: конверта, правил определения данных и средств определения запросов на выполнение операций и ответов.

Web-сервисы описываются с помощью еще одного XML-документа, известного как WSDL (Web Services Description Language, язык описания Web-сервисов). WSDL-документ описывает операции, предоставляемые Web-сервисом, типы данных, используемые в этих операциях, протокол, используемый для взаимодействия с Web-сервисом, и местонахождение самого Web-сервиса.

Преимуществом Web-сервисов является то, что они позволяют приложениям, написанным на разных языках программирования и работающим на различных платформах, взаимодействовать друг с другом через Интернет.

Что такое Ajax?

Ajax является одной из самых передовых технологий, используемых Web-разработчиками для создания функционально насыщенных клиентских интерфейсов. Она основана на том, что приложение посылает запрос для получения новых данных, оставаясь при этом в текущем графическом представлении. В ответ на этот запрос возвращается XML-документ, который затем отображается пользователю, часто в виде подстраницы в текущем окне приложения. Говоря кратко, Ajax позволяет пользоваться динамическими серверными данными, отображая их как динамическую клиентскую информацию.

Ajax, как правило, работает через API, предоставляемый DOM-объектом XMLHttpRequest. До появления Ajax этот объект редко использовался Web-разработчиками. Сам запрос может быть как методом GET, так и POST.

На этот, как и на любой другой запрос возвращается ответ, который может сообщать об ошибке. Если в ответе нет ошибки, то текст ответа используется для обновления текущего представления.

Помните знаменитое изречение Вольтера (а именно: "Священная Римская Империя не была ни священной, ни Римской, ни империей")? Подробное исследование различных реализаций Ajax приводит к пониманию того, что Ajax – это не обязательно код JavaScript, не обязательно XML, и он не обязательно должен быть асинхронным. Если все это исключить, то от сокращения останется только союз «и» (and). Однако это сокращение хорошо звучит, поэтому в индустрии было принято решение сохранить его.

Как Ajax и Web-сервисы работают вместе

Представьте себе: клиентское приложение с богатым графическим интерфейсом, связанное с сервисом, доступным из любого уголка Интернета. Звучит здорово, правда?

Как вы видели, Ajax выполняет запрос и обычно отображает данные из ответа (или их часть) на текущей Web-странице, не обновляя ее полностью. Запрос может представлять собой как простой HTTP-запрос, так и SOAP-сообщение, предназначенное какому-либо Web-сервису. Код JavaScript процедуры Ajax может затем разобрать ответ (также в формате SOAP), извлечь необходимые данные и отобразить их пользователю.

Это действительно просто.

Бизнес-требования компании fishinhole.com

Допустим, совет директоров компании fishinhole.com хочет, чтобы вы предоставили сторонним Web-приложениям доступ к каталогу товаров компании. Они полагают, что если другие Web-сайты, в том числе форумы по спортивной рыбалке, блоги и даже конкурирующие фирмы по продаже снаряжения смогут легко получить доступ к каталогу товаров fishinhole.com, это увеличит продажи на 23.7%.

Воздержимся от размышлений, как они получили цифру 23.7%, а вместо этого сосредоточимся на том, как предоставить каталог товаров другим Web-приложениям. После недолгих размышлений мы приходим к выводу, что нам нужно создать Web-сервис. Web-сервис позволяет клиентам запрашивать каталог приманок определенного типа. В настоящее время имеется три типа приманок: Casting, Trolling и Other. Ваш Web-сервис должен возвращать список приманок указанного в запросе типа.

Также мы понимаем, что сейчас в компании нет приманок типа Other. Наш Web-сервис должен корректно обрабатывать этот случай.

Разворачиваем простой Web-сервис

Мы создадим простой Web-сервис с помощью PHP. PHP в сочетании с NuSOAP - одно из самых простых средств для быстрого создания Web-сервисов, которые мне доводилось видеть.

Сначала загрузите NuSOAP (см. Ресурсы) и поместите все его PHP-файлы в ту же директорию, где вы будете разворачивать ваш Web-сервис на PHP.

После загрузки NuSOAP можно приступать непосредственно к написанию Web-сервиса. В листинге 1 показан его код.

Листинг 1. webservice.php
<?php
require_once('nusoap.php');
$server = new soap_server;
$server->register('hello');
$server->register('retrieveByType');
function hello($name) {
    return 'Hello, ' . $name;
}

function retrieveByType($type) {
	if ($type == 'trolling') {
		$arr[0] = 'Donzai Deep Swimmer 5 1/4 inch';
		$arr[1] = 'Yosubi Squid-like 4 inch';
		$arr[2] = 'Fortunata Imperial High Action';
	} else if ($type == 'casting') {
		$arr[0] = 'Silver Spring Mirrors Size 00';
		$arr[1] = 'Gold Spring Mirrors Size 0';
		$arr[2] = 'Mini Minnow Blue';
	} else {
		$arr[0] = 'None found!';
	}

	return $arr;
}

$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

Во-первых, обратите внимание на строку require_once('nusoap.php'). Она позволяет Web-странице PHP использовать классы, определенные в nusoap.php. Вы можете спросить, зачем же тогда нужны все остальные PHP-файлы, связанные с NuSOAP. Дело в том, что nusoap.php использует в своей работе эти файлы почти так же, как наша страница использует nusoap.php.

В следующей строке создается объект soap_server. Как можно догадаться, он позволяет создать Web-сервис, использующий протокол SOAP.

В следующей строке регистрируется функция retrieveByType, которая будет доступна в качестве операции Web-сервиса. Если вы заглянете в код дальше, вы увидите, что там определяется функция retrieveByType. Почему необходим этот шаг? Потому что если функцию не зарегистрировать, она будет считаться простой PHP—функцией, доступной только на этой PHP-странице или других PHP-страницах, включающих эту. А эта строка информирует объект soap_server, что вы выставляете эту функцию в качестве операции, доступной пользователям Web-сервиса.

В следующем блоке кода непосредственно реализуется метод retrieveByType. Он представляет собой простую PHP-функцию, принимающую один параметр type, который может иметь значение trolling, casting или other. Как вы знаете, эти значения представляют собой три типа приманок, имеющихся на сайте fishinhole.com.

Метод retrieveByType возвращает массив. Этот массив представляет собой список приманок, относящихся к запрошенной категории. На данный момент имеется три различных вида приманок категории trolling и три вида приманок в категории casting. Обратите внимание, что для типа Other и любого неопознанного типа Web-сервис просто возвращает в массиве единственный элемент – строку None Found!.

Две последние строки выполняются при осуществлении доступа к Web-сервису. В первой строке проверяется, имеются ли какие-либо POST-данные. Если нет, то POST-данные приравниваются к пустой строке. Во второй строке выполняется Web-сервис, которому передаются POST-данные. В POST-данных содержится SOAP-сообщение. Мы познакомимся с этим подробнее при изучении клиента.

Сохраните эту страницу с именем webservice.php и поместите ее в ту же директорию, где установлен NuSOAP. Конечно же, эту страницу нужно поместить куда-нибудь, где система может обрабатывать файлы PHP. В наши дни большинство решений хостинга поддерживают PHP, поэтому вы без проблем сможете найти себе подходящий вариант, если у вас нет под рукой Web-сервера с модулем обработки PHP.

Теперь давайте быстро проверим работу Web-сервиса, запросив следующий URL: http://yourhost/yourdirectory/webservice.php. Конечно же, вам следует заменить yourhost и yourdirectory на имя вашей машины и директорию, в которой находится эта страница.

В ответ вы должны получить SOAP-сообщение (см. листинг 2). Если это не так, значит, ваш Web-сервис не работает как должно.

Листинг 2. SOAP-ответ
<?xml version="1.0" encoding="ISO-8859-1" ?> 
<SOAP-ENV:Envelope 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> 
<SOAP-ENV:Body> 
<SOAP-ENV:Fault> 
<faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode> 
<faultactor xsi:type="xsd:string" /> 
<faultstring xsi:type="xsd:string">method '' not defined in service</faultstring> 
<detail xsi:type="xsd:string" /> 
</SOAP-ENV:Fault> 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope>

Создаем страницу, запрашивающую данные с Web-сервиса

Давайте начнем с кода JavaScript, который непосредственно осуществляет доступ к Web-сервису, как показано в листинге 3.

Листинг 3. JavaScript-функция invokeService()
function invokeService(type) {
 soapMessage = '<?xml version="1.0" encoding="ISO-8859-1"?>';
 soapMessage+='<SOAP-ENV:Envelope SOAP-ENV:encodingStyle=""';
 soapMessage+=' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"';
 soapMessage+=' xmlns:xsd="http://www.w3.org/2001/XMLSchema"';
 soapMessage+=' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">';
 soapMessage+=' <SOAP-ENV:Body> <ns1:retrieveByType xmlns:ns1="http://fishinhole.com">';
 soapMessage+=' <type xsi:type="xsd:string">' + type + '</type>';
 soapMessage+=' </ns1:retrieveByType> </SOAP-ENV:Body> </SOAP-ENV:Envelope>';
 
 if(window.XMLHttpRequest) {
  httpRequest=new XMLHttpRequest();
 } else if (window.ActiveXObject) { 
  httpRequest=new ActiveXObject("Microsoft.XMLHTTP"); 
 }
                  
 httpRequest.open("POST",url,true);
 if (httpRequest.overrideMimeType) { 
  httpRequest.overrideMimeType("text/xml"); 
 }
 httpRequest.onreadystatechange=populateDiv;
      
 httpRequest.setRequestHeader("Man", url + " HTTP/1.1")
 httpRequest.setRequestHeader("MessageType", "CALL");
 httpRequest.setRequestHeader("Content-Type", "text/xml");

 httpRequest.send(soapMessage);
 valTimeout=setTimeout("timeout(httpRequest);",120000);
}

Эта функция называется invokeService, она принимает один параметр: type. Наверное, можно и не говорить, что этот параметр соответствует параметру type, принимаемому операцией retrieveByType Web-сервиса. Другими словами, параметр type является строкой, значением которой может быть casting, trolling или other.

В первых строках функции конструируется SOAP-сообщение. Исчерпывающий обзор SOAP выходит далеко за рамки данной статьи. Однако определенные части этого XML-документа интуитивно понятны. Обратите внимание, что один из XML-элементов прямо соответствует имени операции (retrieveByType). Потомок этого элемента называется в соответствии с именем параметра, указанном в файле webservice.php (type). Значением же этого элемента является строковой параметр, переданный в эту JavaScript-функцию, который тоже называется type.

В нескольких следующих строках создается кросс-браузерный объект запроса. Этот объект используется для обращения к Web-сервису.

После создания объекта запроса задается функция обратного вызова, в нашем случае это функция populateDiv(). Эта функция отображает на Web-странице возвращенный список товаров.

Затем в функции задается заголовок. Особо интересно здесь то, что мы согласно спецификации SOAP задаем тип содержимого text/xml. Также обратите внимание на использование переменной url. При создании своей собственной Web-страницы вам нужно будет присвоить этой переменной значение URL-адреса, используемого вашим Web-сервисом. Он будет выглядеть примерно так: http://www.myhost/myservicedir/webservice.php.

Наконец, мы с помощью объекта запроса посылаем SOAP-сообщение и устанавливаем таймаут ожидания ответа от сервиса.

Теперь давайте рассмотрим код JavaScript для отображения списка товаров, вызываемый при получении ответа на Ajax-запрос. Этот код показан в листинге 4.

Листинг 4. JavaScript-функция populateDiv()
function populateDiv(){
 try {
      if(httpRequest.readyState==4) {
         if(httpRequest.status==200) {
            clearTimeout(valTimeout);
     	    var text = httpRequest.responseText;
	    if (window.DOMParser) {
		parser=new DOMParser();
		xmlDoc=parser.parseFromString(text,"text/xml");
	    } else {
	        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(text); 
	    } 
	
            var html = "";
	    for (i=0;i<xmlDoc.getElementsByTagName("item").length;i++) {
	     html += "<br/>" + 
             xmlDoc.getElementsByTagName("item")[i].childNodes[0].nodeValue;
	    }

	    var resultDiv=document.getElementById("resultDiv");
	    resultDiv.innerHTML = html;         		
         }
      } 
 } catch(e) { 
     alert("Error!"+e.description); 
 }      
}

Первые строки функции должны быть знакомы всем, кто когда-нибудь использовал Ajax. Напомним, что эта функция вызывается каждый раз при изменении состояния объекта запроса. Особый интерес для нас представляет ситуация, когда запрос возвращает корректный ответ (код 200).

При возвращении корректного ответа мы сбрасываем таймаут и считываем текст ответа. Напомним, что текст ответа представляет собой SOAP-сообщение, т.е. имеет формат XML. Это означает, что нам нужно средствами языка JavaScript извлечь из этого XML нужную информацию.

Переходим к следующим нескольким строкам. Здесь мы создаем кросс-браузерный объект XML-документа, который можно проанализировать средствами JavaScript. Так как SOAP-ответ является XML-документом, то его содержимое можно разобрать так же, как любой другой XML-документ.

Далее мы генерируем HTML-разметку. Мы начинаем с пустой HTML-строки. Затем мы разбираем SOAP-ответ на элементы item. Помните, что Web-сервис возвращает массив, поэтому, возможно, мы получим более одного элемента item. Цикл for фактически говорит "для каждого элемента item выполнить следующее".

Рассмотрим, в чем заключается это "следующее". JavaScript-код считывает первого потомка элемента item. В нашем случае имеется только один элемент-потомок, являющийся обычной строкой. Далее мы извлекаем значение этого потомка, которое является наименованием товара. Из эстетических соображений перед каждым наименованием я помещаю тег <br/>. Таким образом, каждый элемент списка отображается на отдельной строке. Наконец, вся строка соединяется с существующей разметкой HTML, и по окончании цикла for мы имеем заполненный список.

Разметка HTML готова, теперь поместим ее на страницу. В нашем случае содержимое элемента div с именем resultDiv перезаписывается только что созданной разметкой HTML. В результате мы видим, как при выборе новой категории в выпадающем списке на экране отображается список имеющихся товаров.

Давайте рассмотрим HTML разметку Web-страницы клиента, показанную в листинге 5.

Листинг 5. HTML-страница клиента
<body>    
   <div style="position:relative;left:0px;background-color:blue;margin:0px;">   
   <h2 align="center"><font color="#ffffff">FishinHole.com Web Service</font></h2></div>
   <table align="center" cellpadding="6px" cellspacing="6px" width="400" border="0">
      <tr>
         <td width="80" valign="center"><font color="black">
          Lure Type:</font></td>
         <td>
	  <select name="lureType" id="lureType" onchange="changeTypes()">
	   <option value="">-SELECT-</option>
	   <option value="trolling">Trolling</option>
	   <option value="casting">Casting</option>
	   <option value="other">Other</option>
	  </select>
         </td>
	 <td width="150"> </td>
         <tr>
          <td colspan="3">
            <div id="resultDiv"></div>
          </td>
       </tr> 
    </table>    
</body>

Здесь нет ничего особенно сложного. У нас есть простой выпадающий список с тремя типами приманок: trolling, casting и other. Я использую атрибут onchange, чтобы при выборе пользователем нового типа приманки автоматически выполнялся JavaScript-код, осуществляющий Ajax-запрос

Также обратите внимание на div-элемент resultDiv. Именно здесь отображается список товаров.

Тестирование

Поместите данную HTML-страницу на любую платформу, интерпретирующую HTML и JavaScript-код. Если вы работаете в операционной системе Microsoft ® Windows®, просто сохраните ее на жестком диске.

Затем откройте эту Web-страницу. В середине экрана вы увидите выпадающий список. Сначала в нем выбран элемент -SELECT- . Теперь выберите в нем значение Trolling. Подождите несколько секунд, и на экране появится список из трех товаров. Поздравляем, тест успешно пройден!

Если у вас возникли проблемы, убедитесь, что вы правильно установили значение переменной url. Также JavaScript-код может сообщить о возникновении исключительной ситуации и вывести ее описание во всплывающем окне. Оно подскажет вам, что пошло не так.

Заключение

Web-сервисы являются мощным средством предоставления доступа к функциональности пользователям через Интернет. Ajax позволяет реализовать функционально насыщенные графические интерфейсы Web-приложений, способные изменять отображаемые данные без перезагрузки страницы. Эти два инструмента можно использовать совместно для создания полнофункциональных Web-приложений, эмулирующих распределенные объектные приложения и наделенных профессиональным графическим интерфейсом.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, SOA и web-сервисы
ArticleID=569746
ArticleTitle=Совместное использование Ajax и Web-сервисов
publish-date=11032010