IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  Information Management | XML | SOA и Web-сервисы  >

Программирование на XML для DB2: Часть 3. Программирование на XML на стороне клиента

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить

Исходные тексты примера


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: средний

Хардип Сингх (Hardeep Singh), разработчик инструментария XML для DB2, IBM, Software Group

15.05.2009

Изучив эту статью, вы научитесь расширять XML-модель для создания многофункциональных клиентов, использующих XML-данные, передаваемые с вашего сервера приложений. Вы также узнаете, как использовать динамический HTML (DHTML) для представления XML, XPath для навигации по XML-документам и объектную модель документа (document object model, DOM) для модификации и сериализации XML при возврате на сервер приложений.

Введение

Большая популярность Web 2.0 в значительной степени обусловлена гибкостью современного поколения браузеров. Эти браузеры используют Ajax для общения с серверами, обмениваясь с ними XML-данными, а затем средствами DHTML перемещаются по структуре XML-документа и представляют его пользователю. Такие возможности браузера позволяют использовать его в качестве "толстого" клиента в Web-приложениях.

Из этих основных технологий родился ряд свежих технологий и начинаний, отвечающих на растущую популярность Web 2.0. Для упрощения использования XML были созданы новые вспомогательные библиотеки, такие как Dojo и Sarissa; также была расширена поддержка масштабируемой векторной графики (Scalable Vector Graphics - SVG). Встраиваемые виджеты, такие как карты Google и Yahoo, методы сбора (синдикации) и объединения данных, например, каналы RSS и Atom, и новая парадигма разработки с использованием mashup-данных – все эти разработки направлены на то, чтобы удовлетворить растущие требования культуры Web 2.0.

Как показано на рисунке 1, связующим элементом всех этих технологий является XML. Применение XML в фидах (каналах) позволяет публиковать и принимать сложные структуры данных через Интернет. Программные интерфейсы приложений (API) DOM в DHTML и XPath, поддерживаемые в Sarissa, позволяют эффективно перемещаться по XML-документу для чтения и записи на стороне клиента.


Рисунок 1. Архитектура, ориентированная на интернет
Архитектура, ориентированная на интернет

Замечание: В мире Web 2.0, где источники данных рассматриваются как каналы и сервисы, драйверы баз данных оснащаются поддержкой вызовов REST, FEED и SOAP. После того как будут решены вопросы с безопасностью, вы получите прямой доступ к процедурам базы данных через вызовы SOAP или REST не только с сервера приложений, но и с Web-клиента, без ненужных преобразований. В следующей статье автор создаст пример SOAP-драйвера для DB2®.



В начало


Использование XML-модели на стороне клиента

Так как многие технологии, связанные с XML, являются общими для сервера приложений и для браузера, модель данных XML из первой статьи можно распространить на сторону клиента. Из данной статьи вы узнаете, как расширить XML-модель для создания функционально насыщенных клиентов с помощью XML-данных, получаемых с сервера приложений. Вы также узнаете, как использовать DHTML для отображения XML, XPath - для навигации по XML, и DOM, чтобы модифицировать и сериализовать XML для отправки данных на сервер приложений.

Мы создадим DOM-оболочку для клиента так же, как создавали ее для сервера приложений. Эта оболочка не только изолирует JavaScript-визуализацию и код бизнес-логики от интерфейсов DOM API, но и на уровне сервера приложений делает код очень похожим на код Java™. Для этого мы будем использовать библиотеку с открытым кодом Sarissa, которая предоставляет API-интерфейсы XPath для JavaScript-кода, выполняющегося в браузере. Код оболочки можно загрузить в конце данной статьи (см. раздел Загрузки).

<script type="text/javascript" src="sarissa/sarissa.js"></script>
<script language="javascript" type="text/javascript" src="xmlparse.js"></script>



В начало


Сценарий

В следующих разделах мы развиваем пример страхового приложения из предыдущих статей данной серии (см. Ресурсы). Web-клиент обеспечивает следующую функциональность:

1. Позволяет пользователям просматривать и изменять имя и фамилию в своем профиле.

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

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

Возможность просмотра и изменения своего имени пользователем

Извлекаем информацию пользователя с сервера приложений и представляем ее клиенту для внесения изменений.

Код клиента на JavaScript

Класс profilediv используется для публикации HTML-строки, созданной из XML-данных.

<div class="profilediv" id="profilediv"></div>


Когда пользователь регистрируется на сайте, он вводит идентификатор покупателя (cid). Когда пользователь выбирает в клиентском приложении Update profile (обновить профиль), этот идентификатор передается функции getCustomerInfo.Клиент посылает HTTP-запрос серверу с помощью интерфейса XMLHttpRequest API, предоставленного библиотекой Sarissa. В запросе также определена функция обратного вызова. Эта функция, customerInfoCallback, запускается, когда приходит ответ от сервера. В листинге 1 показано, как извлечь информацию покупателя:


Листинг 1. Клиент запрашивает информацию покупателя
<script>
function getCustomerInfo(cid)
{
var xmlhttpObj= new XMLHttpRequest();
var addr=hosturl+"?cmd= getuserprofile&msg="+cid;
var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('GET', addr, true);
xmlhttpObj.onreadystatechange = function() { customerInfoCallback(xmlhttpObj); };
 xmlhttpObj.send("");
 }

Java-код сервера приложений

В листинге 2 показано, что происходит на сервере приложений, когда он получает клиентский HTTP-запрос. Сначала сервер проверяет, был ли отправлен HTTP-запрос как POST или GET, а потом на основании полученной информации возвращает команду и значения данных с параметрами HTTP-вызова.


Листинг 2. Сервер приложений возвращает информацию покупателя
				
public void service( HttpServletRequest _req, HttpServletResponse _res)
throws ServletException, IOException
{

String cmd, msgtext, returnvalue;

if(_req.getMethod().equalsIgnoreCase("POST"))
{
String message = getPostBody(_req.getReader());
 XMLParse msgxml=new XMLParse(message);
 cmd= msgxml.getValue("//request/@cmd");
msgtext= msgxml.toString("/request/*");
}
else
{
cmd= _req.getParameter("cmd");
msgtext= _req.getParameter("msg");
}

Поскольку команда должна получить пользовательский профиль, сервер приложений извлекает информацию пользователя из базы данных и возвращает ее клиенту. В листинге показаны только те SQL-предложения, которые необходимы для получения информации; предполагается, что читатель самостоятельно может применить программные интерфейсы Java Database Connectivity (JDBC) для подключения к базе данных и получения результата запроса.

Так как пользовательская информация хранится в базе данных в виде XML-документа, вам не придется изменять формат документа, чтобы вернуть его клиенту. Убедитесь, что тип возвращаемых данных в HTTP-заголовке ответа указан как XML.


Листинг 3. Ответ сервера приложений
				
				
	if(cmd.equalsIgnoreCase("getuserprofile"))
{
//returnvalue= select CUSTXML from customer_table where customerid =msgtext
}
_res.setContentType("text/xml");
_res.getWriter().write(returnvalue);
 _res.setHeader("Cache-Control", "no-cache");

JavaScript-код клиента

Когда клиент получает ответ от сервера приложений, запускается функция, определенная в событии callback.

В листинге 4 показан запрос пользовательской информации - userinfo. Обратите внимание, что userinfo объявлена как глобальная переменная, потому что когда вы посылаете обновления, сделанные пользователем в имени или фамилии, эта переменная изменяется.


Листинг 4. Запрос переменной userinfo
				
				
var userinfo=null;
function customerInfoCallback (xmlhttp)
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{

Так как ответ от севера приходит в формате XML, вы напрямую передаете его в конструктор своей DOM-оболочки.

userinfo= new xmlparse(xmlhttp.responseXML, false);

Затем с помощью XPath вы находите имя и фамилию.

var firstname = userinfo.getValue("/Customer/@firstname",null);
var lastname = userinfo.getValue("/Customer/@lastname",null);

В листинге 5 показано, как с помощью DHTML создать графический пользовательский интерфейс (GUI), позволяющий изменять имя пользователя, и как вносить эти изменения в div- тег profilediv, который вы объявили в своей HTML-странице.


Листинг 5. Код DHTML для создания графического интерфейса
				var htmlstr="<table class='inputtable'><tr>";
htmlstr+='<td>firstname:</td><td><input id="fname" value="'+firstname+'"/></td>';
htmlstr+='<td>lastname:</td><td><input id="lname" value="'+lastname+'"/></td>';
htmlstr+='<tr><td/><td><input type="button" value="save"
onClick="javascript:updateCustomer()"/></td>';
htmlstr+='</tr></table>';
document.getElementById("profilediv").innerHTML=htmlstr;
}
}

Сделав эти изменения, нажмите кнопку Save (Сохранить), чтобы запустить функцию updateCustomer. Объектная модель userinfo, содержащая пользовательскую информацию, обновляется, когда пользователь вносит изменения. Чтобы добраться до узлов, которые надо изменить, мы снова используем XPath.


Листинг 6. Использование XPath для обновления пользовательской информации
				
				
	function updateCustomer()
{
var fname=document.getElementById("fname").value;
 var lname=document.getElementById("lname").value;
 userinfo.setValue("/Customer/@firstname",null,fname);
 userinfo.setValue("/Customer/@lastname",null,lname);

Создается новый запрос, и обновленная модель DOM сериализуется и присоединяется к запросу. В листинге 7 показана строка запроса, которая передается серверу (при помощи POST).

Обратите внимание, что сообщение имеет формат XML, поэтому тип контента запроса в заголовке HTTP установлен на XML.


Листинг 7. Строка запроса, отправленная на сервер
				
var msg='<request cmd=" updateuserprofile">'+userinfo.toString("/")+'</request>';
var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('POST', hostname, true);
xmlhttpObj.onreadystatechange = function() { profileUpdated(xmlhttpObj); };
xmlhttpObj.setRequestHeader('content-type', 'text/xml');
xmlhttpObj.send(msg);
}

Java-код сервера приложений

Входные пользовательские XML-данные, полученные от запроса, обрабатываются с помощью DOM-оболочки.

Поскольку customerid является атрибутом в изначальном пользовательском профиле, который был передан клиенту, нет необходимости предусматривать в запросе дополнительный параметр для идентификатора (ID) пользователя.

В листинге 8 показано, как извлечь customerid из документа XML и построить на его основе SQL-команду для обновления базы данных. Данные пользовательского профиля из HTTP-запроса передаются в качестве параметра в SQL-предложение обновления; никакие дополнительные изменения не требуются.


Листинг 8. Создание SQL-команды обновления базы данных
				
				
else if(cmd.equalsIgnoreCase("updateuserprofile"))
{
XMLParse custxml=new XMLParse(msgtext);
String cid= custxml.getValue("/Customer/@customerid");
//update customer_table set custxml=? where customerid=cid
//stmt.setString(1,msgtext);
}

Обратите внимание на сходство кода приложения, используемого для навигации по XML-документу, на стороне клиента и на стороне сервера. Интересно также, что сервер приложений в обоих HTTP-запросах действует просто как посредник между клиентом и базой данных, не воздействуя при этом на данные.

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

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

JavaScript-код клиента

Ссылка URL для соответствующего Web-сервиса, предоставляемого страховой компанией, также выбирается из списка. Так как Ajax запрещает переадресацию URL, вам надо запустить Web-сервис с сервера приложений. Вы передаете URL в запросе серверу приложений для вычисления стоимости страховки для каждого купленного товара. Этот процесс показан в листинге 9:


Листинг 9. Клиент выбирает URL
				function itemsPurchased(url,cid)
{
var msg='<request cmd="getPurchaseInfoWithInsurance"><data customerid="cid">
<![CDATA['+ url+']]></data></request>';

var xmlhttpObj= new XMLHttpRequest();
xmlhttpObj.open('POST', hostname, true);
xmlhttpObj.onreadystatechange = function() { temsPurchasedCallback (xmlhttpObj); };
xmlhttpObj.setRequestHeader('content-type', 'text/xml');
xmlhttpObj.send(msg);
}
}

Замечание: поскольку URL может содержать специальные символы, мы вставляем его в сегмент CDATA, чтобы не получить некорректный XML-документ.

Java-код сервера приложений

Сообщение запроса обрабатывается с помощью DOM-оболочки, и из него извлекается URL страховой компании. В листинге 10 показано, как приложение использует эту ссылку для создания вызова к Web-сервису страховой компании, чтобы получить XML-документ, содержащий сумму страховки.


Листинг 10. Сервер приложений получает сумму страховки
				
				
				
else if(cmd.equalsIgnoreCase("getPurchaseInfoWithInsurance"))
{
XMLParse dataxml=new XMLParse(msgtext);
String url= dataxml.toString("/data/text()");
String insurancestr=callWebServiceUsingHTTPClient(url);

Замечание: XML-документ с суммой страховки приведен в части 2, в разделе "Пример посложнее".

Содержимое тега customer ID также извлекается из сообщения и используется для получения из базы данных информации о купленном пользователем товаре.

String cid= dataxml.getValue("/data/@customerid");

Оставшуюся бизнес-логику для создания списка купленных товаров можно реализовать двумя способами:

  1. Вызвать в базе данных хранимую процедуру, приведенную во второй части в листинге 6.
    // returnvalue = call customerItemsWithInsurance (cid, insurancestr);
    

  2. Закодировать логику в сервере приложений, используя код из первой статьи. С помощью customerXML из листинга 6 первой статьи вы обойдете в цикле все товары, посчитаете размер страховки и добавите ее к информации о товаре.

    Замените строки с 9 по 11 следующим кодом:



    Листинг 11. Заменяем строки с 9 по 11
    						 
    
    XMLParse insurancexml=new XMLParse(insurancestr);
    customerXML.find("/Customer/Items/item",true);
    String currency= insurancexml.getValue("//rate/@currency");
    
    for(int i=0; customerXML.currentFind.getLength()>i;i++)
    {
    price = customerXML.getValue("@price",i));
    if(price>500) rate= insurancexml.getValue("//rate[@price=""]/@rate"));
    else If(price>100) rate= insurancexml.getValue("//rate[@price="500"]/@rate"));
    else rate= insurancexml.getValue("//rate[@price="100"]/@rate"));
    String iteminsurance="<insurance currency="+currency+ ">"+price*rate+"</insurance>"
    customerXML. appendElement(customerXML.createNode (iteminsurance),
    customerXML.getNode (null,i), false )
    }
    // returnvalue = customerXML.toString();
    

Если вы сравните приведенный выше код с запросом в customerItemsWithInsurance хранимой процедуры из второй статьи, то заметите множество совпадений, особенно там, где используется XPath. Этот факт еще раз подчеркивает выгоду использования XML-модели и простоту встраивания бизнес-логики в базу данных.

Также обратите внимание на эффективность выражений XPath при поиске и навигации в иерархической модели данных XML. Воспроизведение такого поиска в объектной модели данных с помощью Java-кода потребовало бы немалых усилий. Использование XPath упрощает этот процесс и позволяет сделать все необходимое в одной строке кода.

JavaScript-код клиента

Ответ сервера запускает функцию itemsPurchasedCallback, в которой возвращенные XML-данные обрабатываются DOM-оболочкой. В листинге 12 показано, как это сделать:


Листинг 12. XML обрабатывается DOM-оболочкой
				function itemsPurchasedCallback (xmlhttp)
{

if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
var itemInfo= new xmlparse(xmlhttp.responseXML, false);

Сначала извлекаем из возвращенного XML имя пользователя:


Листинг 13. Извлекаем имя пользователя
				

var firstname = userinfo.getValue("/Customer/@firstname",null);
var lastname = userinfo.getValue("/Customer/@lastname",null);

var htmlstr="<table class='inputtable'>"
htmlstr+='<tr><td>firstname:<td colspan=5>'+firstname
htmlstr+='<tr><td>lastname:<td colspan=5>'+lastname

Затем проходим по всем товарам в документе и извлекаем нужную информацию, чтобы создать строку HTML, с помощью которой мы представим пользователю эту информацию.


Листинг 14. Извлекаем HTML для отображения информации
				itemInfo.find("//item",null,true);
htmlstr+='<tr><td>itemID<td>description<td>date<td>price<td>insurance';
for(var j=0;itemInfo.currentFind.length>j ;j++)
 {
 var id= itemInfo.getValue("@ID",j);
var description= itemInfo.getValue("@description",j);
var purchaseDate= itemInfo.getValue("@purchaseDate",j);
var price= itemInfo.getValue("@price",j);
var insurance= itemInfo.getValue("insurance/text()",j);
var currency= itemInfo.getValue("insurance/@currency",j);
htmlstr+='<tr><td>'+id+'<td>'+description+'<td>' +purchaseDate+
'<td>' +currency+price++'<td>' +insurance;
}
document.getElementById("profilediv").innerHTML=htmlstr;
}

Обратите внимание на сходство между JavaScript-кодом на стороне клиента, который использует XPath для поиска и обхода всех товаров, с приведенным выше Java-кодом сервера приложений.



В начало


Объектная модель данных

Даже если бы вы использовали стандартный подход объектной модели данных, вам все равно надо было бы сериализовать уровень объектов данных вашего приложения в формат, который будет понятен клиенту. Так как объекты сложные, то по существу у вас есть два варианта:

1. На уровне приложения создать страницу клиента и заполнить данные в соответствующих разделах Web-страницы (подход ASP/JSP). Затем предоставить несколько программных интерфейсов, чтобы принимать изменения, внесенные пользователем в данные. Недостатки такого подхода:

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

2. Создать структуру данных, которую можно послать клиенту как строку. Наиболее приемлемым форматом для представления таким образом сериализованной структуры данных является XML. Недостатки такого подхода:

  • вам придется написать дополнительный код, чтобы реализовать сериализацию;
  • если обновленные данные приходят от клиента в виде XML, надо будет написать дополнительный код для сервера приложений, чтобы перевести измененный XML обратно в объекты данных приложения.

Возникает очевидный вопрос: если вам приходится обращаться к модели данных XML для общения с клиентом, то почему бы не использовать его на самом уровне приложения?

Вам все равно придется обрабатывать информацию, которую вы получите в результате работы Web-сервиса, который вычисляет размер страховки. Так как эта информация получена в формате XML, вам сначала надо будет преобразовать ее в свою объектную модель. Если ваши данные хранились в базе данных как XML, то вы можете передать этот XML хранимой процедуре customerItemsWithInsurance. Недостаток этого подхода такой: если вы храните данные в формате XML и используете объектную модель в приложении, возникают сложности, связанные с преобразованиями и установлением соответствия.

Если бы данные хранились в базе данных в реляционной схеме, ваши запросы к базе данных были бы сложнее. Кроме того, вам бы пришлось написать дополнительный код на промежуточном уровне, чтобы установить соответствие между реляционными данными и объектной моделью данных или моделью данных XML.



В начало


Заключение

В Web-ориентированной архитектуре на различных уровнях приложения возникает необходимость сериализации данных. Наиболее приемлемым способом передачи данных между Web-клиентом и сервером приложений является XML. На каждом уровне данные можно запрашивать, изменять и обновлять. Если данные при этом остаются в формате XML, то для управления данными можно использовать такие XML-технологии, как XPath, DOM и XQuery. В этом заключается суть XML-модели данных для программирования, которая может быть весьма эффективной в сложных задачах интеграции бизнес-данных.




В начало


Загрузка

ОписаниеИмяРазмерМетод загрузки
Классы-оболочки DOM и XPath для javascriptxmlparse.zip9 КБHTTP
Информация о методах загрузки


Ресурсы

Научиться

Получить продукты и технологии
  • DB2 Viper 2 Open Beta

  • Загрузите бесплатную ознакомительную версию DB2 Enterprise 9.

  • Теперь вы можете пользоваться DB2 бесплатно. Загрузите DB2 Express-C - бесплатную версию DB2 Express Edition для сообщества разработчиков, которая предоставляет те же основные возможности, что и DB2 Express Edtion, и дает надежную основу для построения и развертывания приложений.


Обсудить


Об авторе

Хардип Сингх (Hardeep Singh) – член группы встроенной поддержки XML в DB2 и архитектор инструментария для XML DB2 (DB2 XQuery Builder). Он также отвечает за стратегию переноса XML-приложений для следующей версии универсальной базы данных DB2. Его опыт работы в промышленности насчитывает 21 год. .




Выскажите мнение об этой странице


Пожалуйста, найдите минутку и заполните форму, чтобы повысить уровень сервиса.



 


 


 


Поделиться этой статьей:

забобрить забобрить memori сохранить в memori




В начало


IBM обладает всеми авторскими правами касательно информации, расположенной на developerWorks. Использование информации приведенной на этом ресурсе без явного письменного разрешения от IBM или первоначального автора запрещены. Если Вы желаете использовать информацию с developerWorks, пожалуйста воспользуйтесь регистрационной формой для того, чтобы связаться с нами запрос на использование материалов developerWorks Россия.
    IBM в России Конфиденциальность Контакты