Перейти к тексту

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

При первом входе в developerWorks для Вас будет создан профиль. Выберите информацию отображаемую в Вашем профиле — скрыть или отобразить поля можно в любой момент.

Вся введенная информация защищена.

  • Закрыть [x]

При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

Вся введенная информация защищена.

  • Закрыть [x]

Полный цикл разработки Ajax-приложений: Часть 3. Интеграция, тестирование и отладка приложения

Разделите уровни вашего приложения для создания понятного и элегантного Web-приложения

Сентил Натан, старший инженер-программист, IBM
Сентил Натан (Senthil Nathan) работает старшим инженером-программистом в IBM T.J. Watson Research Center в Hawthorne, New York. Имеет 21-летний опыт создания программного обеспечения для корпоративных приложений различных типов. В настоящее время в сферу его профессиональных интересов входят технологии SOA, Web-сервисы, Java 2 Platform, Enterprise Edition (J2EE), PHP, Web 2.0 и Ajax.

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

Больше статей из этой серии

Дата:  15.09.2008
Уровень сложности:  средний
Активность:  3217 просмотров
Комментарии:  


В первых двух частях данной серии вы настроили среду разработки, состоящую из LAMP-подобной среды выполнения и Eclipse IDE. Вы определили вымышленный сценарий работы банка для использования важных Ajax-концепций. Затем вы завершили часть сценария, создав базу данных, PHP-логику промежуточного уровня, простой XHTML для предоставления одностраничного GUI для браузера с CSS-кодом для оформления и несколько вспомогательных функций XML HTTP Request (XHR). В этой третьей и последней части вы завершите оставшуюся часть сценария путем реализации на JavaScript Ajax-логики на стороне клиента. Также вы создадите диспетчер запросов Representational State Transfer (REST) на PHP для выполнения банковских операций: депозит, дебет и стоимость портфеля ценных бумаг. Вы также разработаете (на PHP) приложение-клиент Web-сервисов SOAP (Simple Object Access Protocol) для доступа к реальному Web-сервису (бесплатному) стороннего поставщика услуг. Вы узнаете, как интегрировать различные компоненты (XHTML, CSS, JavaScript, PHP, клиент Web-сервисов и MySQL), разработанные в данной статье. Наконец, в данной статье будут рассмотрены основы развертывания, тестирования и отладки разработанного сценария с использованием LAMP-подобной среды выполнения. К концу статьи вы создадите нетривиальный пример полного сценария, демонстрирующий мощные возможности Ajax-клиента, среды выполнения Apache-PHP-MySQL и IDE, основанной на Eclipse.

Введение

Перед началом работы убедитесь в том, что артефакты сценария Bank (разработанные во второй части данной серии статей) для Bank DB, Bank Logic и Bank Portal остались нетронутыми в Eclipse IDE. К этим артефактам относились: SQL-сценарий для создания и заполнения базы данных, PHP-код для предоставления доступа к базе данных, а также XHTML, CSS и XHR для удовлетворения потребностей одностраничного приложения, работающего в браузере. Написанный для этих артефактов код предоставляет только часть функций сценария Bank, изображенного на рисунке 1. Компоненты, необходимые для соединения этих уже разработанных артефактов, пока еще отсутствуют. Если просмотреть XHTML-файл в его теперешнем состоянии, то в окне браузера отобразится беспорядочная куча различных UI-экранов. Необходимо написать соответствующую логику на стороне клиента (на JavaScript), для того чтобы интегрировать эти разные UI-экраны и создать эффект одностраничного приложения. В этот же клиентский код необходимо добавить соответствующую логику асинхронного взаимодействия XHR. Без JavaScript-кода на стороне клиента функции кассира не могут выполняться.


Рисунок 1. Сценарий работы банка
Рисунок 1. Сценарий работы банка
Подготовьтесь к последнему этапу погружения в разработку при помощи Ajax-технологий на всех трех уровнях приложения. Вы создадите, развернете и протестируете приложение, используя возможности инструментальных средств Zend Core и Eclipse IDE. Будут также исследованы MySQL, PHP, Ajax (XHTML, CSS, JavaScript, XHR), REST, JSON, XML и клиент Web-сервисов.

Можно заметить, что все HTML-формы, предоставляющие специфические функции кассира банка, конфигурируются для передачи пользовательских данных в основанный на REST сервис промежуточного уровня. Вы разработаете этот сервис как еще один PHP-модуль, принимающий запросы браузера кассира для операций депозита, дебета и текущей стоимости портфеля ценных бумаг. Этот PHP-модуль будет выступать в роли диспетчера запросов банковских операций, который анализирует специфичные операционные запросы кассира и вызывает соответствующую функцию Bank Logic для их обработки. Вы увидите, как просто создавать на PHP такие основанные на REST сервисы.

После разработки PHP-сервиса для диспетчеризации REST-запросов мы займемся основанным на технологии .NET Web-сервисом, доступным в Интернет. Это бесплатный Web-сервис, предназначенный для получения текущей цены данного символа акций. Вами будет разработан клиент Web-сервиса на промежуточном уровне PHP для удаленного доступа к этому Web-сервису из основанного на PHP диспетчера запросов банковских операций для получения курса акций. Затем диспетчер запросов банковских операций вызовет модуль Bank Logic PHP с текущим курсом акций для вычисления текущей стоимости портфеля ценных бумаг данного держателя акций. Вы изучите технические приемы доступа к Web-сервису с использованием SOAP и узнаете о двух популярных форматах обмена данными: XML и JavaScript Object Notation (JSON).

Логика клиентского приложения на JavaScript

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

  • Одностраничное приложение, работающее в браузере.
  • Управление DOM браузера.
  • Использование XHR в контексте приложения.
  • Роль JSON в обмене данными приложения.
  • Отладка Ajax-кода на стороне клиента.

Поработав в сценарии работы банка с обычным JavaScript-кодом, вы можете попрактиковаться, создавая эту же клиентскую логику с использованием интегрированной среды Ajax. В обоих случаях Aptana Web IDE, основанная на Eclipse, является идеальным вариантом для разработки клиентского кода.

Всем известно, что JavaScript предоставляет мощные функциональные возможности. В среде браузера JavaScript предоставляет метод обработки событий для перехвата действий пользователя и системных действий, таких как таймер и сетевые события. В нашем сценарии работы банка мы будем использовать обработчики событий конкретно для действий мышки (mouseover, mouseout, mouseclick и т.д.) и асинхронных обратных вызовов от сервера, используя объект XML HTTP Request (XHR).

Одностраничное приложение для работы в браузере требует загрузки относящихся к пользовательскому интерфейсу артефактов кода (XHTML, CSS и JavaScript) с сервера только один раз, когда URL приложения вводится в браузер. Это означает, что логика на стороне клиента должна иметь все необходимое для работы клиентской части сценария работы банка. Схема экрана и связанное с ней оформление передаются через XHTML и CSS-файлы. Другая клиентская логика передается через код, написанный на JavaScript. Основная часть логики заключается в разделении различных экранов приложения и отображении их в нужный момент времени на экране, в зависимости от навигации, осуществляемой пользователем. Во второй части данной серии статей рассказывалось, как использовать HTML-элементы <DIV>, <SPAN> и <TABLE> при компоновке различных экранов для создания единой XHTML-страницы для всего Web-приложения. Используя JavaScript, вы узнаете об управлении объектами DOM браузера для скрытия и показа различных пользовательских элементов управления, хранимых внутри элементов <DIV>. Кроме того, вы узнаете о стилевом оформлении различных пользовательских элементов управления при помощи динамического назначения CSS-правил. Когда бы пользователь этого приложения (обычно кассир) ни выполнил соответствующую операцию (например, депозит, дебет или обновление стоимости портфеля ценных бумаг), JavaScript-логика на стороне клиента взаимодействует с PHP-сервисом промежуточного уровня в REST-стиле. В результате этого взаимодействия браузер и PHP-сервис промежуточного уровня обмениваются данными приложения. Все это, согласно второй части данной серии статей, осуществляется при помощи объекта XHR. Клиентская JavaScript-логика использует объект XHR для передачи (получения) прикладных данных на сервер (с сервера). Вы познакомитесь с Ajax-способом приема ответов сервера в асинхронном режиме.

В соответствии с компонентами акронима Ajax (Asynchronous JavaScript + XML) мы охватили асинхронные и JavaScript-компоненты. Теперь самое время перейти к одному из самых важных строительных блоков Ajax-разработки - представлению данных. Хотя в акрониме Ajax XML является главным компонентом, это не единственный механизм обмена данными, доступный для Web-приложений. Поскольку XML хорошо известен в сообществе разработчиков программного обеспечения, в данной статье нет необходимости повторять то, что вы, вероятно, уже знаете. Вместо этого здесь рассматривается еще один развивающийся и популярный формат обмена данными в Web, называемый JSON. Аналогично XML, JSON тоже основан на текстовой информации и легко может читаться как человеком, так и машиной. С точки зрения читабельности машиной JSON намного легче анализировать и использовать (особенно в приложениях, выполняющихся в браузерах), поскольку он следует синтаксису и структурам данных массивов и объектов JavaScript. Использование JSON в приложениях, выполняющихся в браузерах, сводится к работе со всей структурой данных как со стандартным JavaScript-объектом. Это отличная новость для многих Web-разработчиков, поскольку полностью устраняет дополнительную работу по синтаксическому анализу. Формат JSON также получает признание в других популярных языках программирования (например, Java, PHP, Ruby, C++ и др.). В следующем разделе приводится подробная информация о том, из чего состоит JSON. Ссылки на полную информацию о формате JSON приведены в разделе "Ресурсы". Существует также несколько проектов по преобразованию существующих XML-данных в формат JSON везде, где это имеет смысл. Вы можете познакомиться с одной из таких технологий в другой статье IBM®, ссылка на которую приведена в разделе "Ресурсы". Логика на стороне клиента нашего сценария работы банка использует JSON в качестве формата обмена данными между браузером и PHP-сервисом промежуточного уровня. В последующих разделах будет рассмотрена работа с JSON на JavaScript и на PHP.

Структура JSON

JSON основан на двух структурах:

  • Совокупность пар имя/значение.
    • В различных языках программирования она реализуется одним из следующих типов:
      • Object
      • Record
      • Struct
      • Хэш-таблица
      • Ассоциативный массив
  • Упорядоченный список значений
    • В большинстве языков программирования реализуется как массив.

Это универсальные структуры данных.

  • Все современные языки программирования поддерживают их.
  • Использование формата данных (JSON), состоящего из структур, которые равнозначны таковым в языках программирования, является отличной идеей.

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

Реализация клиентской логики на JavaScript

В предыдущем разделе говорилось о том, что для нашего сценария работы банка мы выбрали формат обмена данными JSON. JSON можно напрямую использовать в браузере, применяя выражение JavaScript eval. Однако прямая обработка посредством выражения eval произвольного JSON-кода поднимает вопросы защищенности. Для предотвращения возникновения проблем, связанных с безопасностью, автор JSON Дуглас Крокфорд (Douglas Crockford), создал простую JavaScript-библиотеку, выполняющую проверку на безопасность JSON-текста перед его преобразованием в JavaScript-объект. Мы будем использовать эти библиотечные функции при обработке JSON-данных.

Прежде всего, создайте на JavaScript логику клиентского приложения:

  1. Откройте браузер и перейдите к URL http://www.json.org/json.js:
    1. В открывшемся диалоговом окне File Download нажмите кнопку Save.
    2. Сохраните файл json.js в каталоге c:\eclipse\workspace\BankTeller и закройте браузер.
  2. Если это еще не сделано, перейдите в перспективу Aptana в Eclipse: выберите Window->Open Perspective->Other->Aptana и нажмите кнопку OK.
  3. В перспективе Aptana в нижнем левом фрейме выберите закладку Project.
  4. Щелкните правой кнопкой мыши на проекте BankTeller и нажмите кнопку Refresh. Вы должны увидеть файл json.js как часть проекта BankTeller.
  5. Щелкните правой кнопкой мыши на проекте BankTeller и выберите New->JavaScript File.
    1. В поле File name введите BankTeller.js и нажмите кнопку Finish.
  6. Замените содержимое этого файла путем копирования исходного кода, приведенного в листинге 1, и сохраните файл. Можете просмотреть комментарии в этих файлах, для того чтобы понять код, или обратитесь к следующему разделу, в котором приведено общее описание логики кода.

Описание логики на стороне клиента

Логика в файле BankTeller.js реализует важные Ajax-концепции, используемые при создании одностраничного приложения, выполняющегося в браузере, при взаимодействиях с сервисом промежуточного уровня в асинхронном режиме и при использовании REST/JSON для доступа к сервису и обмена данными. Все это осуществляется, главным образом, при помощи обработчиков событий JavaScript для действий пользователя и для XHR-объектов. Для работы функций в этом файле требуются другие служебные функции из двух других JavaScript-файлов (xhr.js и json.js). Код в этих файлах начинается с определения специфичных для приложения переменных и констант. Затем следуют JavaScript-функции в произвольном порядке. Следующие десять функций имеют отношение ко взаимодействию пользователя с приложением кассира банка:

  • initOnPageLoad
  • showFooterOptions
  • changeOptionsLinkStyleForSelection
  • changeOptionsLinkStyleToDefault
  • processTellerOperation
  • hideShowAndInsertAsTopElement
  • populateDropDownListWithAccountOwnersData
  • setElementFocusAndTextAndCursorPosition
  • processFooterOperation
  • updateTellerActionResultTextArea

Следующие девять функций имеют отношение к обмену данными приложения с сервисом промежуточного уровня:

  • getAllAccountsInformation_Async
  • http_response_async_callback_for_get_all_acounts_info
  • depositAmountAction_Async
  • http_response_async_callback_for_deposit_to_account
  • debitAmountAction_Async
  • http_response_async_callback_for_debit_from_account
  • portfolioAction_Async
  • http_response_async_callback_for_get_stock_portfolio_value
  • getHostnameFromThisURL

Данный файл достаточно подробно закомментирован, что поможет вам понять внутреннюю работу Ajax-приложения. Приведенное ниже описание предлставляет общую информацию о некоторых JavaScript-функциях, используемых на стороне клиента. Более подробная информация приведена в комментариях файла BankTeller.js. Когда в браузере пользователя указывается URL этого приложения, единственная XHTML-страница для него извлекается из сервера и загружается в браузер. Во время начальной загрузки страницы выполняется функция initOnPageLoad. Как описывалось ранее, пользовательский интерфейс данного приложения содержит одну XHTML-страницу, которая поделена на различные разделы при помощи HTML-элементов <DIV>. Имеется главный элемент <DIV>, называемый "mainPage", который находится на верхнем уровне древовидной структуры DOM браузера. Все остальные элементы <DIV> являются потомками главного элемента <DIV>. В этой функции все элементы <DIV> данного приложения сохраняются в глобальных переменных. Ко всем элементам <DIV>, за исключением главной страницы и пунктов меню кассира, применяется CSS-правило для скрытия их. Поскольку все эти элементы <DIV> сохраняются в глобальных переменных для последующего использования, скрытые элементы <DIV> также удаляются из родительского элемента <DIV>, чтобы убрать вертикальную полосу прокрутки из браузера. Затем выполняется Ajax XHR-вызов для асинхронного получения информации о банковском счете.

Функция showFooterOption может по выбору показывать или скрывать сноску страницы (page footer) в разделе <DIV> приложения. Сноска страницы отображает имя кассира и еще один вариант возврата в основное меню из других экранов приложения. Для показа или скрытия сноски страницы используется встроенные CSS-стили "visible" или "hidden".

Для выбора необходимого действия кассир использует меню, отображаемое главным экраном приложения. Структура этого меню кодируется в XHTML-файле с использованием обычного HTML-текста, заключенного внутри элементов <SPAN>. Элементы <SPAN> назначаются обработчикам событий от мышки (mouseover, mouseout и onclick). Когда происходят события mouseover и mouseout, вызываются соответствующие функции обработчика событий (changeOptionsLinkStyleForSelection, changeOptionsLinkStyleToDefault). Внутри этих функций переключается стиль элементов <SPAN> при помощи правила CSS-класса с цветом фона или CSS-правила без цвета фона, что создает эффект подсветки пунктов меню.

Функция processTellerOperation - это обработчик события onclick, которое активизируется при нажатии пользователем текста menuitem в элементе <SPAN>. В эту функцию передается параметр, указывающий пункт меню, выбранный пользователем. Внутри функции выбранный пункт меню записывается в глобальную переменную для сохранения записи о текущей банковской операции, выполненной кассиром. Затем, элемент <DIV> пункта меню скрывается и показывается другой элемент <DIV>, содержащий элементы управления UI для выбранного действия кассира. В новом отображенном экране (депозит, дебет или стоимость портфеля ценных бумаг) список заполняется всеми именами владельцев счетов. Из этого списка кассир может выбрать владельца счета и выполнить требуемую банковскую операцию.

Функция hideShowAndInsertAsTopElement - это вспомогательная функция с несколькими входными параметрами, такими как скрываемый элемент, показываемый элемент, идентификатор любого конкретного элемента, устанавливаемого в фокус, необязательная позиция курсора для установки в поле ввода и параметр показа или скрытия сноски страницы. Основываясь на входных параметрах, функция показывает или скрывает соответствующие элементы. При необходимости она выполняет другие действия, указанные в других входных параметрах.

Функция populateDropDownListWithAccountOwnersData помещает имена всех владельцев счетов в окно списка. Это помогает кассиру выбрать имя конкретного клиента для выполнения требуемой операции. Данная функция также сортирует имена владельцев счета при помещении их в окно списка.

Функция updateTellerActionResultTextArea обновляет результаты действий кассира в текстовой области. Функция processFooterOperation обрабатывает операции, доступные в сноске страницы.

Теперь рассмотрим функции, относящиеся к XHR. Поскольку наше приложение является настоящим одностраничным Ajax-приложением, содержимое загружается только один раз во время начальной загрузки приложения. После этого клиентское приложение, выполняющееся в браузере, обращается к серверу только для обмена данными, специфичными для приложения. Обмен данными осуществляется при помощи объекта XHR в асинхронном режиме путем доступа к сервису промежуточного уровня в REST-стиле (Representational State Transfer). REST использует HTTP-операции, такие как PUT, GET, POST и DELETE, в зависимости от способа обращения к ресурсам удаленного сервера для обмена данными (ссылки на более подробную информацию по REST приведены в разделе "Ресурсы").

Во многих Ajax-приложениях XHR хорошо работает с механизмом доступа в REST-стиле. Как говорилось в предыдущих разделах, для кодирования данных приложения используется формат JSON. В этом приложении имеется четыре различных типа обмена данными между браузером и сервисом промежуточного уровня. Процедуры, используемые для всех четырех типов обмена данными, очень похожи. Поэтому здесь описан обмен данными только для операции депозит. Каждый обмен данными осуществляется посредством двух разных JavaScript-функций: одна - для передачи запроса в сервис промежуточного уровня, а вторая - для асинхронного получения данных ответа сервера. Когда кассир выполняет операцию депозит, он (или она) вводит сумму депозита и выбирает имя владельца счета перед нажатием кнопки Deposit. Событие onclick для этой кнопки установлено в обработчик события depositAmountAction_Async. Внутри данной функции сумма депозита считывается из поля ввода и проверяется. Затем, из ниспадающего списка выбирается имя владельца счета и из указанного полностью URL документа извлекается имя хоста. К этому времени создается JSON-объект с двумя объектными свойствами: именем владельца счета и суммой депозита. Это данные, передаваемые в сервис промежуточного уровня с использованием REST при помощи операции POST HTTP.

Для преобразования JSON-объекта в строку JSON-формата используется вспомогательная функция из файла json.js (разработанная Дугласом Крокфордом). Затем создается строка HTTP POST-запроса с двумя наборами пар ключ-значение. Первая пара ключ-значение указывает сервису промежуточного уровня, какой ресурс или команда должна быть выполнена - в данном случае это операция депозит. Вторая пара ключ-значение указывает сервису промежуточного уровня информацию о данных запроса, передаваемого из браузера - в данном случае это данные в формате JSON, содержащие имя владельца счета и сумму депозита. Затем присваивается URL сервиса промежуточного уровня. После этого создается новый XHR-объект, и, самое важное, устанавливается функция обратного вызова http_response_async_callback_for_deposit_to_account. Вызывается служебная функция sendHttpRequest из файла xhr.js с XHR-объектом, функцией обратного вызова, URL сервиса промежуточного уровня и передаваемыми данными в качестве входных параметров. Она передает запрос на обмен данными для операции депозит в сервис промежуточного уровня.

Теперь рассмотрим функцию обратного вызова. Она вызывается для каждого изменения состояния HTTP. Но интересующими нас HTTP-состояниями, проверяемыми внутри функции обратного вызова, являются HTTP_READYSTATE_LOADED и HTTP_STATUS_OK. Эти два состояния указывают, что данные ответа сервера были полностью получены, и внутренний код состояния HTTP равен 200. Когда совпадают оба эти условия, данные ответа сервера читаются во внутреннее свойство XHR-объекта под названием responseText. Строковые данные в формате JSON безопасны и преобразуются при помощи служебной функция parseJSON из json.js. Результат этого преобразования - стандартный JavaScript-объект. Внутри этого объекта проверяется состояние приложения для определения успешности выполнения операции депозита. При успешном выполнении возвращенный объект информации о счете сохраняется в глобальной переменной tellerActionResultInfo. Наконец, экран текущей операции депозит скрывается, делается видимым экран отображения результатов операции, и данные обновляются для просмотра кассиром.

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

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

Архитектурная модель Web-сервисов

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

Основой формирования обычной модели Web-сервисов является набор стандартов. К некоторым из таких важных стандартов относятся HTTP, SOAP, REST, XML, JSON и WSDL (Web Services Description Language).

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

  • Поставщик сервиса
  • Реестр сервисов
  • Сторона, запрашивающая сервис

Существуют три общих взаимодействия в архитектурной модели Web-сервисов:

  • Публикация (Publish)
  • Поиск (Find)
  • Связывание (Bind)

Рисунок 2. Роли и взаимодействия Web-сервисов
Рисунок 2. Роли и взаимодействия Web-сервисов

Поставщик сервиса - это владелец или платформа сервиса. Сторона, запрашивающая сервис (или потребитель сервиса), - это приложение, осуществляющее поиск и активизацию взаимодействия с сервисом. Роль потребителя сервиса может выполняться приложением браузера, управляемым пользователем или программой без пользовательского интерфейса (например, PHP, Java, Ruby, сервлет, EJB-компонент). Реестр сервисов представляет собой доступный для поиска каталог описаний сервисов, в котором поставщики сервисов публикуют описания своих сервисов. Потребители используют реестр для поиска сервисов и получения информации о них.

Взаимодействие Publish позволяет поставщику сервиса публиковать описание сервиса таким образом, чтобы потребитель сервиса смог его найти. Взаимодействие Find позволяет потребителю сервиса извлекать описание сервиса напрямую. Взаимодействие Bind позволяет потребителю сервиса активизировать взаимодействие с сервисом во время исполнения, используя подробную информацию о связывании, указанную в описании сервиса.

Описание сервиса - это важный аспект в модели Web-сервисов. WSDL - это стандарт, позволяющий поставщикам описывать свои сервисы в удобном формате для чтения машиной и человеком. На рисунке 3 показана структура WSDL-документа. WSDL-стандарт имеет две части: интерфейс сервиса и реализация сервиса. Интерфейс сервиса - это абстрактное или повторно используемое определение сервиса, на которое могут ссылаться различные реализации сервиса. Реализация сервиса описывает, как конкретный сервис реализуется данным поставщиком.

В интерфейсе WSDL-сервиса элементы type (тип) определяют пользовательские типы XML-данных, которые будут использоваться во взаимодействиях между потребителем и поставщиком сервиса. Элементы message (сообщение) указывают, какие типы XML-данных составляют различные части полезной нагрузки, передаваемой между потребителем и поставщиком сервиса. Элементы operation (операции) определяют, какое сообщение может появиться на входе и выходе взаимодействия Web-сервиса. PortType определяет разрешенные действия Web-сервиса. Наконец, элемент binding (связывание) определяет протокол и формат данных.

В реализации WSDL-сервиса элемент port связывает оконечную точку (сетевой адрес или URL) с элементом binding в интерфейсе сервиса. Элемент service содержит набор элементов port.


Рисунок 3. Структура WSDL
Рисунок 3. Структура WSDL

Реализация клиента Web-сервиса

Одной из банковских операций, которые выполняет кассир, является получение текущей стоимости портфеля ценных бумаг владельца данного счета. Когда кассир выбирает этот вариант на Web-странице, в PHP-сервис промежуточного уровня передается HTTP-запрос. Перед вызовом модуля Bank Logic PHP для вычисления суммарной стоимости портфеля ценных бумаг необходимо передать текущую стоимость акций в качестве параметра. Для получения этой стоимости необходимо обратиться к удаленному Web-сервису, размещенному в Интернете.

Для доступа к удаленному Web-сервису необходимо сгенерировать прокси клиента Web-сервиса, используя WSDL. В PHP это легко осуществить в нескольких строках кода. Библиотека PHP SOAP Client позволяет динамически сгенерировать клиента Web-сервиса из WSDL, предоставленного поставщиком сервиса. В данном случае мы будем использовать основанный на технологии .NET сервис курса акций, предлагаемый в Интернет бесплатно сайтом WebserviceX.net. Возможно, вы захотите потратить некоторое время на изучение WSDL-файла для удаленного сервиса курса акций, посетив WebServiceX.net (см. раздел "Ресурсы").

Выполните следующие действия для создания в PHP клиента Web-сервиса, использующего WSDL сервиса курса акций, опубликованный на WebserviceX.net:

  1. Если это еще не сделано, перейдите в перспективу Eclipse PHP: выберите Window->Open Perspective->Other->PHP и нажмите кнопку OK.
  2. В виде PHP Explorer (верхний левый фрейм) щелкните правой кнопкой мыши на проекте BankTeller и выберите New->PHP File.
    1. Введите имя файла GetStockPrice.php.
    2. Нажмите кнопку Finish.
  3. Замените содержимое этого файла, скопировав исходный код, приведенный в листинге 2, и сохраните файл. Вы можете просмотреть комментарии в этом файле для лучшего понимания кода, либо обратиться к следующему разделу, в котором приведено общее описание логики кода.

Листинг 2. Содержимое файла GetStockPrice.php
                
<?php
/*
============================================================
Проект: Полный цикл разработки Ajax-приложений

Назначение: Это пример сценария, используемого
 в статье на IBM developerWorks.

Дата последней модификации: 17 мая 2007.

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

Данный модуль демонстрирует, насколько легко использовать
удаленный Web-сервис (выполняющийся на платформе .NET),
динамически применяя PHP путем указания удаленного
WSDL-файла для этого Web-сервиса.

Для выполнения этого используется библиотека PHP SOAP Client. 
============================================================
*/
   // Получить необходимый модуль Bank Logic PHP.
   require_once("BankLogic.php");
   
   /*
   ============================================================
   Функция: getStockPortfolioValue

   Дата последней модификации: 17 мая 2007.
   
   Эта функция принимает имя владельца счета в качестве входного параметра.
   В данном сценарии все владельцы счетов имеют одну акцию 
   в своем портфеле ценных бумаг. Код получает тикерный символ 
   акции, хранящийся у данного владельца счета.
   Затем он использует библиотеку PHP SOAP client для удаленной 
   активизации основанного на .NET Web-сервиса курса акций и 
   получает ответ в XML-формате, возвращаемый этим сервисом. Код 
   анализирует подробный ответ об акции и извлекает текущую 
   стоимость этой акции. Затем вызывается еще одна функция
   внутри модуля Bank Logic PHP для обновления базы данных
   с новым значением стоимости портфеля ценных бумаг.
   ============================================================ 
   */   
   function getStockPortfolioValue($accountHolderName) {
      // Из модуля Bank Logic получить информацию о 
      // всех счетах, хранящихся в базе данных.
      // [Если кто-то хочет оптимизировать это, можно написать
      // новую функцию для возврата информации о счете 
      // владельца данного счета вместо получения
      // информации о всех счетах.]
      $finalResult = getAllAccountInformation();
      
      // Проверить, что из DB прочитана информация о всех счетах.
      if ($finalResult["ResultCode"] != 0) {
         // Какая-то ошибка. Возвратить управление.
         return($finalResult);
      } // Конец if ($finalResult["ResultCode"] != 0)
      
      // Получить информацию о счете пользователя, с которым мы сейчас работаем.
      $accountInfoArray = $finalResult["AccountInfo"];
      $tickerSymbol = null;
      
      // Выполнить цикл по информации всех доступных счетов и отфильтровать
      // информацию о счете для имени владельца данного счета, переданного 
      // в качестве параметра в функцию, в которой мы находимся.
      foreach ($accountInfoArray as $accountInfo) {
         // Это счет интересующего нас субъекта?  
         if (strcasecmp($accountInfo["AccountHolderName"], $accountHolderName) == 0) {
            // Получить тикерный символ единственной акции,
             имеющейся в его портфеле ценных бумаг.
            $tickerSymbol = $accountInfo["StockName"];
            // Символ получен. Пропустить последующий цикл.
            break;
         } // Конец if (strcasecmp($accountInfo["AccountHolderName"] ...
      } // Конец foreach ($accountInfoArray as $accountInfo)
      
      // Если произошла ошибка при получении тикерного символа, вернуть управление.
      if ($tickerSymbol == null) {
         $finalResult["ResultCode"] = 1;
         $finalResult["ResultMsg"] = 
            "Unable to get ticker symbol from the account of $accountHolderName.";
         return($finalResult);                  
      } // Конец if ($tickerSymbol == null)
      
      // Это WSDL, опубликованный поставщиком сервиса.
      $wsdl = "http://www.webservicex.net/stockquote.asmx?WSDL"; 
      // Вся магия заключена в следующих четырех строках, выполняющих
      // сложную функцию удаленно по Интернету.
      // Это действительно здорово. Почему другие исполняющие системы промежуточного 
      // уровня не могут следовать простоте PHP при выполнении подобных вещей.
      // Создать экземпляр библиотеки PHP SOAP client, непосредственно указав  
      // удаленный WSDL URL.
      $proxy = new SoapClient($wsdl, array("trace"=>1,"exceptions"=>0));
      // Установить необходимый входной параметр для удаленного сервиса.
      // В нашем случае это просто тикерный символ. 
      $param['symbol'] = $tickerSymbol;  
      // Выполнить удаленную логику. Это так просто.
      $result = $proxy->GetQuote($param); 
      // У нас имеется строка ответа в XML-формате.
      $quoteResult = $result->GetQuoteResult;
      
      // Преобразовать строку из XML-формата в DOM-объект.
      // PHP также выполняет обработку XML очень элегантно и просто.
      $xml = simplexml_load_string($quoteResult);
      $stockPrice = 0.0;
      
      // XML-ответ о курсе акции излишне подробен.
      // Он содержит информацию о различных аспектах данной акции.
      // Мы интересуемся только текущей рыночной стоимостью акции.
      // Эта информация доступна в виде: 
      // <Stock>...<Last>56.34</Last>...</Stock>
      // Все, что мы должны сделать, - извлечь значение XML-элемента <Last>
      // Посмотрите сами, как легко это сделать на PHP.
      if (property_exists($xml, "Stock") == true) {
         // У нас есть элемент <Stock> в ответе Web-сервиса.
         $stockInfo = $xml->Stock;
         
         // Теперь проверить, содержит ли элемент <Stock> потомка с названием <Last>.
         if (property_exists($stockInfo, "Last")) {
            // Просто извлечь последнюю рыночную стоимость этой акции.
            $stockPrice = $stockInfo->Last;
         } else {
            $finalResult["ResultCode"] = 1;
            $finalResult["ResultMsg"] = 
               "Unable to get current stock price of " .
               "$accountHolderName's stock $tickerSymbol.";
            return($finalResult);            
         } // Конец if (property_exists($stockInfo, "Last"))
      } else {
         $finalResult["ResultCode"] = 1;
         $finalResult["ResultMsg"] = 
            "Unable to get current stock price of " .
            "$accountHolderName's stock $tickerSymbol.";
         return($finalResult);         
      } // Конец if (property_exists($xml, "Stock") == true)
   
      // Теперь, когда есть текущая стоимость акции, вычисляем 
      // стоимость портфеля ценных бумаг и обновляем ее в DB.
      // Возвратить результат.
      $finalResult = portfolioValue($accountHolderName, $stockPrice);
      return($finalResult);
   } // Конец function getStockPortfolioValue   
?>
		

Логика PHP-клиента Web-сервиса

Процедура, которой вы следовали в предыдущем разделе для создания клиента Web-сервиса, является всего лишь одним из простейших подходов, возможных при использовании библиотеки PHP SOAP client. Логика в GetStockPrice.php создает клиента Web-сервиса для сервиса курса акций, размещенного по URL http://www.webserviceX.net. Библиотека PHP SOAP client непосредственно указывает на WSDL URL, опубликованный провайдером сервиса, и динамически создает для сервиса прокси в оперативной памяти (in-memory proxy), используя информацию описания сервиса, содержащуюся в WSDL. Затем прокси-код выполняет удаленный вызов, как будто бы функция курса акций доступна локально на вашей машине. В данном случае клиентский прокси использует протокол доступа SOAP для взаимодействия с удаленным сервисом курса акций, посылая ему тикерный символ (ticker symbol) акции в качестве входного параметра и, таким образом, получая XML-документ в качестве выходных данных от сервиса курса акций.

Логика в GetStockPrice.php является простой, поскольку содержит только одну функцию: getStockPortfolioValue. Этот PHP-модуль требует наличия модуля BankLogic.php для использования функций доступа к базе данных, имеющихся в нем. Функция getStockPortfolioValue принимает параметр - имя владельца счета, для которого необходимо вычислить и обновить стоимость портфеля ценных бумаг. Она получает информацию обо всех счетах, хранящуюся в базе данных, и отфильтровывает ту, которая принадлежит владельцу данного счета. Вместо извлечения информации обо всех счетах вы можете модифицировать код, чтобы получать информацию только для конкретного владельца акций (это упражнение, которое вы, возможно, захотите выполнить позже). Из отфильтрованной информации о счете извлекается тикерный символ, принадлежащий портфелю ценных бумаг. Затем создается экземпляр объекта PHP SoapClient путем передачи WSDL URL курса акций в качестве параметра в конструктор класса. Тикерный символ акции добавляется в качестве входного параметра для Web-сервиса. Затем вызывается метод GetQuote прокси, который выполняет SOAP-вызов удаленного Web-сервиса. При успешном выполнении Web-сервис получает ответ в виде строки в XML-формате. PHP предоставляет один из простейших способов преобразования этой строки в XML-формате в структуру объектов XML DOM. В этом XML-дереве элемент <Last> хранит текущую рыночную стоимость данной акции. Извлекается значение <Last>. Наконец, вызывается функция под названием portfolioValue в PHP-модуле Bank Logic с именем владельца счета и текущей стоимостью акций в качестве параметров. Эта функция вычисляет новое значение стоимости портфеля ценных бумаг, используя текущий курс акций, обновляет базу данных и возвращает ассоциативный массив, содержащий предыдущее и текущее значения стоимости портфеля ценных бумаг. Этот ассоциативный массив возвращается также программе, вызвавшей функцию getStockPortfolio.

Результатом работы удаленного сервиса курса акций является XML-документ с объемной информацией о запрошенном тикерном символе акции. Просмотрите листинг 3, в котором приведен пример выходной информации сервиса курса акций для тикерного символа акции IBM. Выходные данные в XML-формате содержат очень много информации, в том числе дату и время цены запрошенной акции, цены открытия и закрытия, процентное изменение цены, верхнее и нижнее отклонение цены за операционный день, объем торгов, годовой диапазон цен, чистую прибыль на акцию и отношение цены к прибыли (P/E ratio) акции. Среди всей этой информации нас интересует последняя цена закрытия для данного тикерного символа акций, которая доступна в XML-элементе <Last>. Весь остальной код в методе getStockPrice занимается разбором всех XML-результатов от Web-сервиса при помощи DOM-анализатора.


Листинг 3. Пример XML-ответа от удаленного Web-сервиса курса акций
                
<?xml version="1.0" encoding="utf-8" ?> 
<string xmlns="http://www.webserviceX.NET/">
   <StockQuotes>
      <Stock>
         <Symbol>IBM</Symbol>
         <Last>101.17</Last>
         <Date>4/27/2007</Date>
         <Time>4:01pm</Time>
         <Change>+0.27</Change>
         <Open>100.30</Open>
         <High>101.17</High>
         <Low>100.06</Low>
         <Volume>6141359<Volume>
         <MktCap>152.3B</MktCap>
         <PreviousClose>100.90</PreviousClose>
         <PercentageChange>+0.27%</PercentageChange>
         <AnnRange>72.73 - 101.17</AnnRange>
         <Earns>6.262</Earns>
         <P-E>16.11</P-E>
         <Name>INTL BUSINESS MAC</Name>
      </Stock>
   </StockQuotes>
</string> 
		

Диспетчер REST-запросов операций банка на PHP

Мы почти закончили реализацию требуемых артефактов. Этот последний раздел, посвященный диспетчеру REST-запросов, объединяет код всех трех уровней. PHP опять упрощает получение вызовов REST-сервиса (HTTP POST в данном случае), диспетчеризацию их в соответствующие служебные функции и возврат результатов обратно в клиентские программы, работающие в браузерах. Обмен данными между клиентами и этим PHP-модулем выполняется с использованием формата JSON и требует наличия JSON-анализатора в PHP. Мы будем использовать JSON-анализатор с открытым исходным кодом, доступный на PEAR.net. В данном разделе предоставляется подробная информация по реализации и описание PHP-модуля диспетчера REST-запросов.

Выполните следующие действия для реализации PHP-модуля диспетчера REST-запросов:

  1. Если это еще не сделано, переключитесь в перспективу Eclipse PHP: выберите Window->Open Perspective->Other->PHP и нажмите кнопку OK.
  2. В виде PHP Explorer (верхний левый фрейм) щелкните правой кнопкой мыши на проекте BankTeller и выберите New->PHP File:
    1. Введите имя файла JSON.php.
    2. Нажмите кнопку Finish.
  3. Откройте браузер и перейдите по URL http://mike.teczno.com/JSON/JSON.phps:
    1. Скопируйте все содержимое, отображаемое в вашем браузере, в буфер обмена (clipboard) и закройте браузер.
    2. Замените все содержимое файла JSON.php в вашем Eclipse-редакторе, скопировав содержимое из буфера обмена.
    3. Выберите File->Save.
    4. Закройте файл.
  4. В виде PHP Explorer (верхний левый фрейм) щелкните правой кнопкой мыши на проекте BankTeller и выберите New->PHP File:
    1. Введите имя файла BankActions_REST_Service.php.
    2. Нажмите кнопку Finish.
  5. Замените содержимое этого файла, введя или скопировав исходный код, приведенный в листинге 4, и сохраните файл, нажав File->Save.

Компактная логика кода в BankActions_REST_Service.php выполняет диспетчеризацию запросов клиентского приложения, выполняющегося в браузере (операции кассира банка). Этот PHP-модуль зависит от трех других PHP-модулей. Два из них являются частями данного проекта (BankLogic.php и GetStockPrice.php), а третий - это внешний JSON-анализатор с открытым исходным кодом, написанный на PHP. Мы уже описали все функции, доступные в двух PHP-модулях. Библиотека JSON.php является очень простой в использовании. Она, насколько это возможно, приближает использование JSON к среде программирования PHP. JSON.php предоставляет JSON-анализатор со следующими функциями:

  • decode() преобразовывает JSON-данные в PHP-объект.
  • encode() преобразовывает ассоциативный массив PHP в структуру данных JSON.

Когда бы ни осуществляла клиентская программа, выполняющаяся в браузере, REST-обращения (HTTP POST) к сервису промежуточного уровня сценария работы банка, код в BankActions_REST_Service.php сначала собирает входные данные сервиса, переданные клиентской программой. Эти входные данные доступны в виде пар ключ-значение в суперглобальном ассоциативном массиве $_REQUEST PHP-сервера. Входные данные, передаваемые клиентской программой, содержат две пары ключ-значение. Одна из них содержит команду кассира банка, которую нужно выполнить. Это, обычно, депозит, дебет или получение/обновление стоимости портфеля ценных бумаг. Другой элемент данных содержит специфичные для приложения данные, необходимые для выполнения команды кассира. Эти данные кодируются с использованием JSON. После синтаксического анализа команды кассира банка и входных данных сервиса логика программы использует JSON-анализатор для преобразования текста, представленного в JSON-формате, в PHP-объект. После того, как это будет сделано, выражение switch передает управление соответствующей функции кассира банка в другие включенные PHP-модули. Во время вызова этих функций им передаются необходимые параметры, извлеченные из JSON-текста. При возврате из функций кассира банка они предоставляют окончательные результаты (успех или неудача) в ассоциативном массиве PHP. Эти окончательные результаты преобразовываются в JSON-текст и возвращаются клиентской программе в браузер.

Вот вы и завершили реализацию и описание всех нужных артефактов кода на всех трех уровнях для полного сценария работы банка. Поздравляем!


Листинг 4. Содержимое файла BankActions_REST_Service.php
                
<?php
/*
============================================================
Проект: Полный цикл разработки Ajax-приложений

Назначение: Это пример сценария, используемого в статье
 на IBM developerWorks.

Дата последней модификации: 17 мая 2007.

Этот модуль является обработчиком REST-запросов сервиса для 
серверной части сценария работы банка. Он получает 
REST-запросы (HTTP POST) от одностраничных клиентских 
приложений, выполняющихся в браузере. Он направляет различные 
запросы различным функциям логики.
Он также передает и принимает специфичные для приложения данные
в заранее согласованным JSON-формате. 
============================================================
*/
   // Получить другие необходимые PHP-модули.
   // JSON.php - это JSON-анализатор с открытым исходным кодом на PHP.
   // Его можно получить с http://mike.teczno.com/JSON/JSON.phps 
   require_once("JSON.php");
   // Модуль Bank Logic имеет три основных серверных функции кассира банка.
   require_once("BankLogic.php");
   // GetStockPrice - это прокси-клиент Web-сервиса для удаленного Web-сервиса.
   require_once("GetStockPrice.php");
   
   // Определить все используемые константы.
   define ("BANK_TELLER_COMMAND_KEY", "Bank_Teller_Command");
   define ("BANK_TELLER_POST_DATA_KEY", "Post_Data");
   define ("GET_ALL_ACCOUNTS_INFO", "Get_All_Accounts_Info");
   define ("DEPOSIT_TO_ACCOUNT", "Deposit_To_Account");
   define ("DEBIT_FROM_ACCOUNT", "Debit_From_Account");
   define ("GET_STOCK_PORTFOLIO_VALUE", "Get_Stock_Portfolio_Value");
   
   // Данные XHTML-формы из клиентской Ajax-программы кассира банка 
   // доступны в одной из суперглобальных переменных PHP 
   // т.е. в ассоциативном массиве $_REQUEST.
   // Каждый REST-запрос от клиентского приложения будет иметь две пары
   // ключ-значение. Первая - это команда кассира банка, указывающая, что нужно
   // выполнить: депозит, дебет, стоимость портфеля ценных бумаг и т.д.
   // Вторая пара ключ-значение является специфичными для приложения данными,
   // передаваемыми в виде строки в JSON-формате. 
   $bankTellerCommand = $_REQUEST[BANK_TELLER_COMMAND_KEY];
   $bankTellerPostData = $_REQUEST[BANK_TELLER_POST_DATA_KEY];
   
   // Использовать JSON в PHP настолько просто, насколько это вообще возможно.
   // Создать экземпляр JSON-анализатора (доступный через JSON.php)
   $json = new Services_JSON();
   // В одном выражении преобразовать текст, представленный в JSON-формате
   // в эквивалентную структуру PHP-классов. Да, именно так.
   $bankTellerInput = $json->decode($bankTellerPostData);
   $responseToBeSent = "";
   $bankActionResult = null;
   
   // Ветвление для команды кассира, выполненной в клиентском приложении.
   switch($bankTellerCommand) {
      case GET_ALL_ACCOUNTS_INFO:
         // Получить информацию о всех счетах, хранящихся в базе данных.
         $bankActionResult = getAllAccountInformation();
         break;
         
      case DEPOSIT_TO_ACCOUNT:
         // Выполнить транзакцию депозита счета.
         // Передать имя владельца счета и сумму депозита, переданную 
         // клиентским приложением из браузера. Третий параметр 1 указывает DEPOSIT.
         // Эта функция доступна в BankLogic.php
         $bankActionResult = 
            accountTransaction(
               $bankTellerInput->accountHolderName,
               $bankTellerInput->amount, 1);
         break;
         
      case DEBIT_FROM_ACCOUNT:
         // Выполнить транзакцию дебета счета.
         // Передать имя владельца счета и сумму дебета, переданную 
         // клиентским приложением из браузера. Третий параметр 2 указывает DEBIT.
         // Эта функция доступна в BankLogic.php       
         $bankActionResult = 
            accountTransaction(
               $bankTellerInput->accountHolderName,
               $bankTellerInput->amount, 2);         
         break;
         
      case GET_STOCK_PORTFOLIO_VALUE:
         // Выполнить транзакцию "Обновление стоимости портфеля ценных бумаг".
         // Это потребует выхода в Интернет и вызова удаленного Web-сервиса.
         // Данная функция доступна в GetStockPrice.php
         $bankActionResult = 
            getStockPortfolioValue($bankTellerInput->accountHolderName);
         break;
         
      default:
         // Некорректная команда.
         $bankActionResult["ResultCode"] = 1;
         $bankActionResult["ResultMsg"] = "Invalid Teller Command";
   } // Конец switch($bankTellerCommand)
   
   // Мы сделали все, что запрашивала клиентская программа.
   // Возвратим окончательные результаты в тексте, представленном в JSON-формате.
   // Преобразование структуры данных ассоциативного массива PHP в JSON-текст
   // занимает одну строку кода на PHP.
   $responseToBeSent = $json->encode($bankActionResult);
   // Установить HTTP-заголовок так, чтобы он указывал, что мы передаем данные
   // в JSON-формате.
   // В настоящее время разрабатывается проект (май 2007) для определения 
   // нового типа содержимого text/json.
   header("Content-Type: text/plain");      
   // Это все. Возвратить ответ в JSON-формате обратно 
   // в браузер.
   echo($responseToBeSent);
?>
		

Интеграция компонентов сценария работы банка

На данный момент вы завершили разработку Ajax-клиента, PHP-сервиса промежуточного уровня и компонентов базы данных MySQL, необходимых для сценария работы банка. Они перечислены ниже:

  • BankDB (База данных банка, основанная на MySQL).
  • BankLogic (Базовая логика для функций кассира банка внутри PHP-модуля).
  • BankPortal (Web-клиент кассира банка, использующий технологии Ajax).
  • BankActions (REST-сервис действий кассира банка на PHP).
  • Клиент Web-сервиса котировки акций (SOAP-прокси, использующий PHP SOAP Client).

Эти компоненты выполняют в нашем сценарии работы банка специфическую задачу. Как было показано в этой серии статей, каждый компонент зависит от некоторого другого компонента, создавая завершенную картину сценария работы банка. В типичных трехуровневых Web-приложениях используемые интегрированные среды (такие как .NET) требуют подробного конфигурирования зависимостей для интеграции различных прикладных компонентов. Выбранные для реализации данного сценария технологии отличаются отсутствием такого сложного конфигурирования. Обо всех необходимых зависимостях мы уже позаботились при реализации этих компонентов. Не требуется специфичной для приложения интеграции во время исполнения при использовании Ajax (XHTML, CSS, JavaScript, REST, JSON), PHP или MySQL, что устраняет значительные накладные расходы и уменьшает сложность полного цикла разработки приложения.

Развертывание компонентов сценария работы банка

Теперь, после завершения разработки и интеграции компонентов сценария работы банка, пора приступить к их развертыванию на PHP-сервере Zend Core. Напомним, что Zend Core работает поверх Web-сервера Apache.

  1. Активизируйте перспективу Eclipse PHP: выберите Window->Open Perspective->Other->PHP и нажмите кнопку OK.
  2. Выберите вариант Window->Web Browser->Internal Web Browser.
  3. В виде PHP Explorer (верхний левый фрейм) щелкните правой кнопкой мыши на проекте BankTeller и выберите Run As->Run:
    1. В левом фрейме диалогового окна Run разверните вариант "PHP Web Page", нажав знак + рядом с ним.
    2. Убедитесь в том, что запись New_configuration присутствует в "PHP Web Page".
    3. Если записи New_Configuration нет, щелкните правой кнопкой мыши на PHP Web Page и выберите New для ее создания.
    4. Выберите запись New_Configuration.
    5. В правой панели этого же диалогового окна вы увидите различные конфигурационные параметры для New_Configuation. Убедитесь, что поле Server field установлено в Default PHP Web Server.
    6. В поле File/Project нажмите кнопку Browse, выберите BankTeller и нажмите кнопку OK.
    7. Убедитесь, что отмечен флажок Publish files to Server.
    8. В поле Publish To: добавьте текст BankTeller, так чтобы этот конфигурационный параметр выглядел следующим образом: C:\Program Files\Zend\Apache2\htdocs\BankTeller.
    9. Отметьте флажок Auto Generate.
    10. Нажмите кнопку Run.

Эти действия приведут к развертыванию файлов в Zend Core и к запуску внутреннего браузера Eclipse. Сейчас вы можете закрыть внутренний браузер.

Если вы увидели, что главное меню приложения Bank Teller появилось на экране Eclipse Browser, все прошло хорошо. Если нет, вы должны убедиться в том, что случайно не пропустили какие-либо действия. Это все, что нужно для развертывания и запуска полного Ajax-приложения.

Тестирование компонентов сценария работы банка

Наконец настал момент вкусить плоды всей работы, выполненной в данной серии статей! Сценарий работы банка находится в состоянии тестирования. Выполните следующие действия для тестирования операций кассира банка, испытав код (на всех трех уровнях), который вы разработали и развернули:

  1. В инструментальной панели Eclipse нажмите пиктограмму внутреннего Web-браузера Eclipse (похожа на глобус).
  2. Дождитесь запуска внутреннего браузера Eclipse.
  3. В поле URL address браузера введите http://localhost/BankTeller в качестве URL для приложения сценария работы банка, выполняющегося на локальной машине, и нажмите Enter.
  4. При этом отобразится главный экран приложения сценария работы банка, как показано на рисунке 4. Как объяснялось выше, - это единственная Web-страница приложения. Вы можете следить за URL при тестировании приложения. Это единственный URL, который вы увидите во всем приложении. Имеется несколько разделов или экранов для данного приложения, которые являются частями одной страницы. На данный момент все остальные элементы управления пользовательского интерфейса для этих экранов скрыты, и видим только главный экран. Суть этой Ajax-функциональности состоит в том, что для данного приложения больше не будет обновлений страницы, загружаемых с сервера во время сессии браузера.
  5. Вы можете подвигать курсор мыши над пунктами меню. Пункты меню подсвечиваются. Это простая возможность Ajax, реализованная всего лишь путем изменения стиля CSS-класса элемента <SPAN>, содержащего текст меню, для событий mouseover и mouseout.
  6. Выберите первый пункт меню "Deposit to an account", что приведет к появлению экрана deposit Ajax-способом (при получении страницы не требуется помощь сервера). Вы должны увидеть окно списка со всеми владельцами счетов. Эти данные были получены из сервера промежуточного уровня в фоновом режиме с использованием асинхронной возможности Ajax XHR. Вы можете также заметить сноску страницы, отображающую вымышленное имя кассира банка и ссылку перехода обратно в главное меню.
    1. Выберите владельца счета Merry и введите сумму депозита 125.00, как показано на рисунке 5.
    2. Нажмите кнопку Deposit. Вы должны увидеть страницу с подробной информацией о транзакции, как показано на рисунке 6.
    3. Нажмите ссылку Back to main menu в сноске страницы.
  7. Выберите второй пункт меню Debit from an account. При этом мгновенно, без ожидания, откроется экран debit.
    • Выберите владельца счета, введите сумму дебета и нажмите кнопку Debit.
    • Проверьте результаты, возвращенные с сервера.
    • Нажмите ссылку Back to main menu в сноске страницы.
  8. Выберите третий пункт меню Current portfolio value. При этом немедленно откроется экран portfolio value:
    • В окне списка выберите владельца счета Gandalf, как показано на рисунке 7.
    • Нажмите кнопку Get Stock Portfolio Value. Вы должны получить экран с обновленным значением стоимости портфеля ценных бумаг, как показано на рисунке 8. Это действие кассира банка передало REST-запрос PHP-сервису промежуточного уровня, который, в свою очередь, создал динамического клиента Web-сервисов для удаленного сервиса котировки акций и вызвал этот сервис. Новая цена акции была обновлена в базе данных, и новое значение стоимости портфеля ценных бумаг было вычислено и возвращено в браузер.
    • Нажмите ссылку Back to main menu в сноске страницы.
  9. Закройте внутренний Web-браузер Eclipse.

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


Рисунок 4. Главный экран Bank Teller
Рисунок 4. Главный экран Bank Teller

Рисунок 5. Экран результатов операции депозит
Рисунок 5. Экран результатов операции депозит

Рисунок 6. Экран результатов операции дебет
Рисунок 6. Экран результатов операции дебет

Рисунок 7. Экран операции стоимости портфеля ценных бумаг
Рисунок 7. Экран операции стоимости портфеля ценных бумаг

Рисунок 8. Экран результатов операции стоимости портфеля ценных бумаг
Рисунок 8. Экран результатов операции стоимости портфеля ценных бумаг

Варианты отладки

В любой среде разработки программного обеспечения средства отладки являются решающими компонентами, влияющими на скорость и качество выполнения проекта. В многоуровневых Web-приложениях, таких как наш сценарий работы банка, отладчики являются важнейшей частью набора инструментальных средств разработчика. Желательная функциональность (способность отлаживать все уровни Web-приложения внутри одной IDE) пока еще не доступна. Однако новые проекты с открытыми исходными кодами, основанные на Eclipse (например, PHP Development Tool (PDT) и Aptana Web IDE), являются очень перспективными. Поскольку оба проекта подключаются к одной и той же платформе Eclipse, мы можем ожидать, что они вскоре предоставят возможность сквозной отладки, позволяя разработчикам устанавливать одну точку останова в JavaScript-функции, а вторую - в PHP-функции. Это даст возможность отлаживать одну полную транзакцию и в браузере, и на сервере Zend Core.

Как отдельные системы PDT и Aptana имеют отличные отладочные возможности для PHP и JavaScript соответственно. Aptana хорошо интегрируется с популярными браузерами (например, Firefox, Internet Explorer, Safari и Opera) для отладки JavaScript-кода. Аналогично, Firebug (подключаемый модуль Firefox) обеспечивает превосходные отладочные возможности для JavaScript. Однако на момент написания данной статьи эти отладочные инструментальные средства были еще не готовы к совместной работе для обеспечения возможности сквозной отладки, начиная с кода, выполняющегося в браузере, и вплоть до серверного кода.

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

  1. Выполнение отладки PHP-кода на сервере Zend Core, используя отладчик PDT.
  2. Выполнение отладки JavaScript-кода на стороне клиента в браузере Firefox, используя отладчик Firebug.

Отладка PHP-кода на стороне сервера

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

  1. Активизируйте перспективу Eclipse PHP: выберите Window->Open Perspective->Other->PHP и нажмите кнопку OK.
  2. Выберите меню Window->Web Browser->Internal Web Browser.
  3. На момент написания данной статьи PDT и Zend-отладчик будут работать вместе только в том случае, если начальная страница приложения является PHP-файлом. По этой причине вы должны переименовать файл index.html в index.php. Это просто меняет расширение файла и абсолютно не влияет на поведение приложения:
    1. В виде PHP project explorer ниже проекта BankTeller щелкните правой кнопкой мыши на файле index.html и выберите Refactor->Rename.
    2. Измените имя файла на index.php.
  4. В виде Eclipse PHP project explorer щелкните правой кнопкой мыши на проекте BankTeller и выберите Debug As->Debug:
    1. В левой панели отобразившегося диалогового окна Debug выберите PHP Web Page->New_configuration. При этом отобразится правая панель с кнопкой Debug в нижней части диалогового окна.
    2. Нажмите кнопку Debug.
    3. Если отобразится запрос на открытие перспективы PHP Debug, нажмите Yes. Перспектива PHP Debug отобразится с открытым файлом index.php и внутренним браузером Eclipse. Отладчик остановится в начале файла index.php (который содержит только HTML-сценарий и не содержит какого-либо PHP-кода).
    4. Быстро нажмите пиктограмму Resume (зеленая стрелка с желтой полоской), доступную в виде Debug (верхняя левая часть экрана). Если вы затратите на это более 60 секунд, внутренний браузер завершится по таймауту, и вы должны будете начать отладку с самого начала.
    5. Во время начальной загрузки страницы мы используем Ajax XHR для получения всей информации с сервера. Когда этот XHR-запрос доходит до сервера Zend Core, отладчик останавливается на первой строке PHP-файла диспетчера REST-запросов. (Отладчик настроен на остановку на первой строке выполняемого PHP-файла. Это дополнение ко всем точкам останова, которые мы можем установить).
    6. Теперь вы можете использовать отладочные возможности, такие как пошаговое выполнение функции (step into) или проход всей функции за один шаг (step over), используя пиктограммы, расположенные в верхней части вида Debug.
    7. Во время использования возможностей step into и step over вы можете также контролировать значения переменных вашего приложения в PHP-коде. Это можно делать в виде Variables, доступном в перспективе Debug.
    8. Чтобы обойти таймаут внутреннего браузера, выполняйте отладку быстро, укладываясь в 60 секунд, а затем нажмите пиктограмму Resume (зеленая стрелка с желтой полоской), доступную в виде Debug.
  5. Давайте проверим возможность останова в конкретной точке PHP-кода вместо останова на первой строке всякий раз при выполнении PHP-кода:
    1. Перейдите в перспективу PHP.
    2. В проекте BankTeller откройте файл BankActions_REST_Service.php.
    3. В этом файле найдите PHP-выражение $json = new Services_JSON().
    4. Выполните двойной щелчок левой кнопкой мыши на номере строки этого выражения (в самой левой части редактора). Для этого выражения вставится пиктограмма точки останова.
    5. Перейдите в конец этого файла и установите еще одну точку останова в последней строке: echo($responseToBeSent).
    6. Перейдите в перспективу Eclipse PHP Debug.
    7. Если внутренний браузер Eclipse откроется в этот раз, закройте его.
    8. В панели меню Eclipse выберите пункт Run->Debug. При этом откроется диалоговое окно Debug.
    9. В левой панели этого диалогового окна перейдите в закладку Advanced.
    10. В разделе Breakpoint отметьте флажок Override project/workspace Break at First Line. Оставьте флажок Break at First Line не отмеченным.
    11. Нажмите кнопку Debug. При этом запустится внутренний браузер, и выполнится переход прямо на первую точку останова, установленную на JSON-выражении. Останов выполнится здесь потому, что XHR-запрос для получения информации обо всех счетах активизируется во время начальной загрузки страницы.
    12. Вы можете нажать пиктограмму Resume в виде Debug. Программа выполнится и остановится на второй точке останова в конце файла. Вы можете повторно нажать пиктограмму Resume, чтобы продолжить выполнение.
    13. Теперь можно перейти во внутренний браузер и выполнить любые операции кассира банка.
  6. В перспективе PHP Debug выберите вид Breakpoints.
    1. Щелкните правой кнопкой мыши на любой из точек останова и выберите Remove All.
    2. Если отобразится запрос на подтверждение, нажмите кнопку Yes.

Примечание: На момент написания данной статьи вы должны знать о следующей незначительной проблеме PDT-отладки. Во время сеанса PHP-отладки вы можете увидеть в виде Debug сразу после завершения отладки PHP-сценария одно или несколько сообщений, аналогичных следующему: <terminated> New_configuration [PHP Web Page]. Не удаляйте их до тех пор, пока не завершите отладку всего приложения. Если вы удалите эти сообщения, отладку следующей функции приложения нельзя будет выполнить в этом же сеансе отладки, и вам придется начать новый сеанс. Эта проблема и проблема таймаута внутреннего браузера, вероятно, будут исправлены ко времени перехода PDT от состояния предвыпускной версии (release candidate) (RC3) к официальной версии.

Отладка JavaScript-кода на стороне клиента

Выполните следующие действия для отладки JavaScript-логики на стороне клиента, используя отладчик Firebug, который вы установили в первой части данной серии статей. Приведенные ниже инструкции предполагают, что вы развернули приложение сценария работы банка и выполнили обычное тестирование, как описывалось в двух предыдущих разделах.

  1. Запустите браузер Firefox на вашей машине.
  2. Введите URL http://localhost/BankTeller.
  3. Дождитесь появления на экране браузера главного меню приложения Bank teller.
  4. В панели меню Firefox выберите Tools->Firebug->Open Firebug. При этом откроется окно Firebug в нижней части окна браузера Firefox.
  5. Перейдите в закладку HTML в окне Firebug:
    1. Разверните раздел <body> в HTML.
    2. В отображенном HTML-тексте проведите курсором мышки по <div id="mainPage". При этом выделятся части экрана приложения, содержащиеся внутри элемента mainPage <DIV>.
    3. Проведите курсором мышки по тексту <h1 title=... и увидите, что теперь выделился заголовок приложения.
    4. Проверьте это же для элементов tellerOptions и pageFooter <DIV>.
    5. Вы можете заметить, что на этом экране pageFooter скрыт; но Firebug способен показать вам его.
  6. Перейдите в закладку CSS окна Firebug. Вы можете увидеть весь CSS-файл этого приложения.
  7. Перейдите в закладку Script в окне Firebug. Вы можете увидеть все JavaScript-файлы этого приложения.
    1. В верхней части окна Firebug нажмите маленькую стрелку вниз, отображаемую возле имени JavaScript-файла. Вы можете выбрать любой из перечисленных здесь JavaScript-файлов и просмотреть код.
  8. Перейдите в закладку DOM окна Firebug. Отобразится вся DOM-структура приложения кассира банка, выполняющегося в браузере.
  9. Перейдите в закладку Net окна Firebug:
    1. Это позволяет вам следить за всей сетевой активностью в приложении.
    2. Вы можете по отдельности выбрать HTML, CSS, JavaScript, Images и просматривать HTTP Headers, Post-данные и Response-данные.
    3. Также отобразится красивое графическое окно времени извлечения выбранного типа содержимого.
    4. В верхней части окна Firebug нажмите XHR. При этом отобразится XHR-активность, имевшая место в приложении кассира банка. На данный момент был только один обмен данными, выполненный с использованием XHR. Показывается REST-ресурс, к которому обращались на сервере.
    5. Разверните запись BankActions_REST_Service.php.
    6. Перейдите в закладки Post и Response для просмотра данных JSON-запроса и ответа, обмен которыми был осуществлен с сервисом промежуточного уровня.
  10. Выполнив такую большую подготовку к работе в Firebug, давайте попытаемся отладить некоторый JavaScript-код:
    1. Перейдите в закладку Script в окне Firebug.
    2. Используя маленькую стрелку вниз в верхней части окна Firebug, выберите BankTeller.js.
    3. Перейдите в конец содержимого файла BankTeller.js, где была определена последняя функция.
    4. В этой последней функции щелкните на номере исходной строки var textResult = teller_request.responseText;.
    5. Для этой строки установится точка останова. (Еще один щелчок кнопки мыши снимет точку останова. В данном случае оставьте точку останова для этой строки активной.)
    6. Перейдите к предыдущей функции portfolioAction_Async().
    7. Установите точку останова на первом выражении этой функции.
    8. В меню приложения Bank Teller (в верхней половине окна браузера) выберите вариант 3 для текущей стоимости портфеля ценных бумаг. Немедленно отобразится экран portfolio value.
    9. Выберите владельца счета и нажмите кнопку Get Stock Portfolio Value. Выполнение JavaScript прерывается на точке останова внутри функции portfolioAction_Async().
    10. В нижней части окна Firebug вы можете увидеть пиктограммы: continue (продолжение), step over (перешагивание), step into (вход) и step out (выход).
    11. Нажмите пиктограмму step over (или клавишу F10). Приложение выполнится до следующей строки.
    12. Вы можете пройти несколько строк, а также просмотреть значения переменных в правой стороне окна Firebug.
    13. Вы можете пройти еще несколько строк и увидеть, как создается JSON-объект, а затем преобразовывается в строку в JSON-формате.
    14. Нажмите пиктограмму Continue (или клавишу F8).
    15. Это завершит выполнение текущей функции - посылается запрос на сервер промежуточного уровня для получения стоимости портфеля ценных бумаг.
    16. Если ваша машина подключена к Интернет, PHP-сервис промежуточного уровня активизирует удаленный Web-сервис курса акций и возвратит результат обратно на сервер. Это вызовет остановку JavaScript-кода на второй точке останова, установленной на функции обратного вызова XHR.
    17. Нажимайте клавишу F10 (step over) последовательно для всех выражений этой функции. Обратите внимание на прием JSON-ответа с сервера и на то, как он разбирается при помощи parseJSON (с разрешения Дугласа Крокфорда). До конца этой функции вы также увидите, как мы скрываем один экран приложения (get portfolio) и показываем другой (teller operation results) без единого обновления страницы с сервера промежуточного уровня.
    18. Нажмите ссылку Back to main menu в сноске страницы приложения кассира банка.
    19. Закройте окно Firebug.
  11. Закройте браузер Firefox.

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

Краткое резюме

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

Основные моменты

  • Ожидали ли вы обновления страницы в данном Ajax-приложении? Скорее всего, нет, и никогда не будете.
  • Быстрота реакции была достигнута за счет локализации всей клиентской логики в одном приложении, выполняющемся в браузере.
  • При нажатии кнопок Deposit, Debit и Get Stock Portfolio Value данное приложение взаимодействует с PHP-сервером промежуточного уровня для обмена очень маленьким объемом данных (это значительно повышает эффективность использования сети).
  • При использовании данного приложения кажется, что ходишь по разным страницам. На самом деле этот эффект был достигнут просто путем скрытия и показа различных элементов DIV, которые помещены на одну HTML-страницу.
  • Разработка Web-приложений в Ajax-стиле делает возможным перенос в браузер шаблонов полнофункционального взаимодействия с пользователем. Результат состоит в улучшенном восприятии приложения пользователями и клиентами.
  • Такой способ проектирования Web-приложений уменьшает также нагрузку на сервер промежуточного уровня, поскольку сервер больше не занимается не обязательными обновлениями HTML-страницы. Вместо этого он осуществляет только обмен необходимым данными.
  • Во время работы с данным приложением вы замечали изменение URL браузера? Он не менялся никогда и был установлен в одно значение для всего приложения. Вот что делает это приложение одностраничным. Представляемое содержимое (HTML, CSS и JavaScript) загружается с Web-сервера только один раз в самом начале работы.

Заключение

Центр Ajax-ресурсов на developerWorks
Посетите Ajax Resource Center - универсальное хранилище информации по программной модели Ajax со статьями и учебными руководствами, дискуссионными форумами, блогами, wiki, событиями и новостями. Если что-то происходит, здесь об этом обязательно упоминается.

Вы только что завершили погружение в разработку Ajax-приложения, проходящее через все три уровня (клиент, промежуточный уровень и сервер данных). Вы применили несколько технологий с открытыми исходными кодами в качестве программного обеспечения промежуточного уровня для создания и развертывания этого приложения. Во время этого процесса вы использовали некоторые из основных функциональных возможностей Zend Core и некоторые инструментальные средства Eclipse IDE. Вы проникли в суть концепций MySQL, PHP, Ajax (XHTML, CSS, JavaScript, XHR), REST, JSON, XML и клиента Web-сервисов. В Eclipse IDE вы приобрели опыт работы в перспективах PHP и Aptana. Вы также научились развертывать и тестировать на стороне сервера Zend Core/Apache. Артефакты кода для JavaScript-логики на стороне клиента, PHP Web services Client, PHP-диспетчер REST-запросов и WSDL-файл котировки акций, использованные в данной части серии статей, включены в загружаемый файл, поставляемый с этой статьей (см. раздел "Загрузка").

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

Подводя итог, скажем, что данная серия статей продемонстрировала мощь Zend Core и среды разработки Eclipse (PDT и Aptana). Обе системы - это вероятный выбор для небольших и средних фирм, которые ищут набор программ промежуточного уровня с открытыми исходными кодами, или оценивают путь миграции с платформы .NET на системы с открытыми исходными кодами. Эти исполняющие системы и основанные на Eclipse инструментальные средства обеспечивают также естественное расширение необходимых для работы коммерческих предложений продуктов и сервисов от нескольких производителей. Наконец, большая заслуга разработчиков Zend и Aptana состоит в том, что они принесли простоту в новую стадию Web-разработки посредством своих продуктов с открытыми исходными кодами Zend Core, Eclipse PDT и Aptana Web IDE.



Загрузка

ИмяРазмерМетод загрузки
wa-aj-end2end3.zip28KBHTTP

Информация о методах загрузки


Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Об авторе

Сентил Натан (Senthil Nathan) работает старшим инженером-программистом в IBM T.J. Watson Research Center в Hawthorne, New York. Имеет 21-летний опыт создания программного обеспечения для корпоративных приложений различных типов. В настоящее время в сферу его профессиональных интересов входят технологии SOA, Web-сервисы, Java 2 Platform, Enterprise Edition (J2EE), PHP, Web 2.0 и Ajax.

Помощь по сообщениям о нарушениях

Сообщение о нарушениях

Спасибо. Эта запись была помечена для модератора.


Помощь по сообщениям о нарушениях

Сообщение о нарушениях

Сообщение о нарушении не было отправлено. Попробуйте, пожалуйста, позже.


developerWorks: вход


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


При первом входе в developerWorks для Вас будет создан профиль. Выберите информацию отображаемую в Вашем профиле — скрыть или отобразить поля можно в любой момент.

Выберите ваше отображаемое имя

При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

(Должно содержать от 3 до 31 символа.)


Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Оценить эту статью

Комментарии

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, XML
ArticleID=338094
ArticleTitle=Полный цикл разработки Ajax-приложений: Часть 3. Интеграция, тестирование и отладка приложения
publish-date=09152008
author1-email=sen@us.ibm.com
author1-email-cc=

Теги

Help
Используйте форму поиска, чтобы найти любой контент с данным тегом в My developerWorks. Используйте ползунок, чтобы отразить больше или меньше тегов.

КнопкаПопулярные теги отображает самые распространенные теги для данной области контента (например: Java, Linux, WebSphere).

Кнопка Мои теги отображает Ваши теги для данной области контента (например: Java, Linux, WebSphere).

Используйте форму поиска, чтобы найти любой контент с данным тегом в My developerWorks. Кнопка Популярные теги отображает самые распространенные теги для данной области контента (например: Java, Linux, WebSphere). Кнопка Мои теги отображает Ваши теги для данной области контента (например: Java, Linux, WebSphere).