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

developerWorks Россия  >  Open source | XML  >

Полный цикл разработки Ajax-приложений, Часть 2: Реализация уровней Ajax-клиента и сервера

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

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

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

Обсудить

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


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

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


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

Сентил Натан, старший инженер-программист, IBM

21.09.2007

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

В первой части данной серии статей вы узнали о важнейших функциональных возможностях таких технологий с открытым исходным кодом, как Firefox, Zend Core и MySQL. Вы познакомились с нетривиальным банковским сценарием, использующим все три уровня Ajax-приложения. Вы также установили сервер базы данных, промежуточный сервер и основанную на Eclipse IDE, необходимые для полного цикла разработки Ajax-приложения. В данной статье будут разработаны некоторые части банковского сценария. В частности, вы создадите базу данных, используя MySQL, а также познакомитесь с несколькими инструментальными программами MySQL, работающими из командной строки и используемыми для подключения, создания, определения и заполнения базы данных специфичными для приложения данными. Затем вы разработаете PHP-модуль промежуточного уровня для хранения бизнес-логики банка, использующий ODBC для подключения к базе данных MySQL. Наконец, вы разработаете портал банка (для предоставления простого пользовательского интерфейса в браузере), который пользователи могут использовать для взаимодействия с приложением, которое вскоре будет готово для выполнения на Zend Core.

Введение

Как говорилось в первой части данной серии статей, банковский сценарий концентрируется вокруг предоставления базовых сервисов обслуживания счета, которые выполняет кассир банка. Если вы еще этого не сделали, вам следует изучить сценарий, описанный в первой части. Пользовательские данные являются важной частью данного сценария. Для целей этого упражнения все пользовательские данные будут вноситься в таблицу базы данных за один прием. Затем данные могут быть извлечены и обновлены через ODBC-драйвер MySQL, поставляемый с Zend Core. После работы с данными мы переключимся на базовую логику банка, необходимую для реализации функций кассира. Вы разработаете модуль на PHP для предоставления базовой логики банка с необходимым доступом к базе данных при помощи ODBC. Главное преимущество использования Zend Core и PHP для этой логики - использование встроенной поддержки MySQL.

Закончив работу с базой данных и PHP-модулем, вы продолжите разрабатывать простой пользовательский интерфейс для выполнения кассиром банка четырех базовых операций. Как говорилось ранее, базовая логика заключена в PHP-модуле, доступ к которому осуществляется через "тонкий" клиент. Этот основанный на Web "тонкий" клиент будет сгенерирован в Ajax-стиле: XHTML, Cascading Style Sheets (CSS), JavaScript и XMLHttpRequest (XHR). Он обеспечит простой пользовательский интерфейс для выполнения кассиром банка базовых операций. Этот пользовательский интерфейс также продемонстрирует специфичный метод взаимодействия по сети клиентской логики с серверной логикой на PHP.

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

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

База данных MySQL

Как вы узнали из первой части данной серии статей, MySQL - это база данных с открытыми исходными кодами. В нашем сценарии мы используем редакцию community server, являющуюся компактным сервером базы данных со многими полезными функциональными возможностями. Поскольку реализация банковского сценария основана на продуктах с открытыми исходными кодами, MySQL отлично подходит к PHP-серверу Zend Core. MySQL поддерживается в Zend Core. Существует несколько инструментальных программ для администрирования и программирования MySQL. В нашем сценарии для администрирования MySQL мы будем использовать только клиентскую программу командной строки. Мы создадим базу данных счетов банка, используя MySQL.

Создание и заполнение базы данных банка

В этом сценарии информация о счетах данного клиента хранится в следующем виде:

  • AccountHolderName
  • AccountNumber
  • CheckingBalance
  • StockName
  • StockQuantity
  • StockValue

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

Для создания базы данных и заполнения таблицы специфическими для приложения данными выполните следующие действия:

  1. Если среда Eclipse еще не запущена, запустите ее (c:\eclipse\eclipse.exe).
  2. Перейдите в перспективу PHP в Eclipse:
    1. Выберите Window->Open Perspective->Other->PHP и нажмите кнопку OK.
  3. В Eclipse выберите File->New->Project.
  4. Выберите General->Project и нажмите кнопку Next.
  5. Введите BankDB в поле project name.
  6. Нажмите кнопку Finish.
  7. Щелкните правой кнопкой мыши на проекте BankDB и выберите New->Other.
  8. Выберите General-> File и нажмите кнопку Next.
  9. В поле File name введите BankDB.sql и нажмите кнопку Finish.
  10. Введите или скопируйте содержимое исходного кода для BankDB.sql, приведенное в листинге 1.
  11. Сохраните и закройте файл.
  12. Для запуска клиента командной строки MySQL выберите Windows Start Menu->All Programs->MySQL->MySQL Server->MySQL Command Line Client.
  13. В окне командной строки MySQL введите пароль webtech и нажмите клавишу Enter.
  14. В приглашении mysql> введите source c:\eclipse\workspace\BankDB\BankDB.sql и нажмите клавишу Enter.
  15. Проверьте корректность выполнения предыдущей команды, убедившись в существовании базы данных BankDB. Вы можете сделать это, выполнив следующие команды:
    1. show databases;
    2. use bankdb;
    3. show tables;
    4. describe account;
  16. Чтобы закрыть клиент командной строки, введите exit.

Листинг 1. Содержимое файла BankDB.sql
                
			
-- Этот файл является частью статьи "Полный цикл Ajax-разработки" на 
-- IBM developerWorks. Этот файл содержит простой сценарий для
-- создания базы данных и заполнения его данными.
-- 
-- Дата последней модификации: 10 мая 2007
-- 
-- Для выполнения в MySQL приведенных ниже выражений проделайте следующее:
-- 1) Запустите клиент командной строки MySQL.
-- 2) Введите пароль администратора MySQL.
-- 3) Введите следующую строку, заменяя <YOUR_SQL_FILE_DIR> именем 
--    каталога, в котором хранится файл.
--    source <YOUR_SQL_FILE_DIR>\bankdb.sql

--
-- Структура таблицы 'BankDB'
--

DROP DATABASE BankDB;

CREATE DATABASE BankDB;

USE BankDB;

CREATE TABLE account (
   AccountHolderName VARCHAR(20) NOT NULL, 
   AccountNumber INTEGER NOT NULL,
   CheckingBalance DOUBLE NOT NULL,
   StockName VARCHAR(6),
   StockQuantity INTEGER,
   StockValue DOUBLE,
   PRIMARY KEY(AccountHolderName, AccountNumber)
);

--
-- Заполнение данными таблицы 'account'
--

insert into ACCOUNT values ('Frodo', 435245, 2344.45, 'GOOG', 100, 3453.32);
insert into ACCOUNT values ('Sam', 928462, 7583.32, 'CSCO', 200, 5323.43);
insert into ACCOUNT values ('Pippin', 234233, 3444.62, 'INTC', 300, 4213.76);
insert into ACCOUNT values ('Merry', 642445, 1005.32, 'MSFT', 250, 1353.32);
insert into ACCOUNT values ('Aragorn', 972321, 6424.24, 'HPQ', 525, 12043.94);
insert into ACCOUNT values ('Gandalf', 432134, 5392.23, 'IBM', 400, 10043.78);
insert into ACCOUNT values ('Legolas', 590134, 4313.82, 'DELL', 325, 5926.62);
		

Использование PHP для доступа к базе данных MySQL

Одной из популярных функциональных возможностей PHP является его простая классическая поддержка доступа к данным, хранящимся в базах данных разных производителей, в том числе MySQL. Он предоставляет эффективный и простой метод интегрирования бизнес-логики с базой данных. За последние несколько лет PHP-сообщество сделало несколько улучшений, например, PHP Data Objects (PDO), который предоставляет уровень абстракции и реализует общие функции API, независимые от используемого сервера базы данных. PHP-функции API базы данных реализованы также для процедурного и объектно-ориентированного стилей. В нашем сценарии мы будем использовать API базы данных, предназначенный для MySQL. PHP предлагает два способа доступа к MySQL:

  • MySQL
  • MySQL Improved

Обычное расширение для MySQL не поддерживает всю функциональность MySQL 4.1.0. К неподдерживаемым функциональным возможностям относятся хранимые процедуры, триггеры и виды (view). Расширение MySQL Improved (mysqli) является самым новым усовершенствованным способом доступа к этим функциям. Расширение для mysqli доступно в PHP 5.0 или старших версий. Однако mysqli не разрешен по умолчанию - вы должны сделать это при помощи программы администрирования Zend Core. В данном упражнении mysqli уже был разрешен в первой части данной серии статей при установке и настройке Zend Core.

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

Строительные блоки функций PHP MySQLi

Как уже упоминалось, существует обширный массив функций mysqli, доступных в PHP. В данном разделе рассматриваются только те функции, которые используются при реализации сценария. В частности, рассматриваются такие функции базы данных как подключение, чтение, запись и отключение от базы данных. Всю дополнительную информацию вы найдете в официальной документации по PHP, ссылка на которую приведена в разделе "Ресурсы".

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

$link = mysqli_connect("hostname", "user", "password", "dbname");

Эта функция делает попытку подключиться к указанной базе данных, расположенной на указанном хосте, с соответствующими полномочиями. Имеются также дополнительные параметры, которые принимает данная функция (см. документацию по PHP). При успешном подключении к базе данных функция возвращает объект connection, который необходим в последующих операция чтения и записи в базу данных. Если подключение выполнить не удалось, эта функция возвращает значение false. Если вы не хотите встраивать пароль к базе данных непосредственно в ваш код в текстовом виде, можно использовать функциональность MySQL password digest.

Дополняющей функцией к операции подключения к базе данных является функция закрытия базы данных:

$result = mysqli_close($link);

Эта функция пытается закрыть предварительно открытое подключение к базе данных. Она принимает в качестве параметра объект connection и возвращает значение true, если операция выполнилась успешно, и значение false в противном случае.

Рассмотрев функции управления подключением, давайте рассмотрим функции чтения и записи данных. Ниже приведен список полезных функций для операций чтения/записи:

  • (1) $result = mysqli_query($link, $queryStr);
  • (2) $numberOfRows = mysqli_num_rows($result);
  • (3) $row = mysqli_fetch_assoc($result);
  • (4) $row = mysqli_fetch_object($result);

Функция (1) выполняет SQL-запрос к базе данных. В качестве входных параметров она принимает объект connection и строку корректного SQL-запроса. Функция выполняет запрос и возвращает true при успешном выполнении и false в противном случае. Однако для SQL-запроса SELECT эта функция возвращает объект result.

Функция (2) получает количество строк в наборе, возвращаемом из SQL-запроса. В качестве параметра она принимает объект result.

Функция (3) получает строку результата в виде ассоциативного массива PHP. Этот массив содержит имена столбцов базы данных как ключи и значения полей базы данных как значения массива. Например, если запрос к базе данных возвратил значение столбца "capital", к результату можно обратиться так:

$stateCapital = $row['capital'];

Функция (4) получает строку результата в виде PHP-объекта. Этот объект содержит имена столбцов базы данных как свойства объекта и значения полей базы данных как значения свойства объекта. Например, если запрос к базе данных возвратил значение столбца "park", к результату можно обратиться путем разыменования значения объекта:

$nationalPark = $row->park;

Функции 3 и 4 предоставляют очень простой способ отобразить значения базы данных в программные переменные. Как упоминалось ранее, PHP также предлагает несколько других способов отображения значений базы данных.

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

  • $returnCode = mysqli_errno($link);
  • $errorMsg = mysqli_error($link);

Функция mysqli_errno возвращает код ошибки самого последнего выполненного вызова функции. Она принимает в качестве параметра объект connection и возвращает код для выполненной функции. Код 0 указывает на отсутствие ошибок. Функция mysqli_error возвращает строковое описание последней ошибки. Обе эти функции важны для выполнения полного цикла запроса к базе данных.

Реализация бизнес-логики банка в PHP-модуле

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

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

Можно заметить, как просто выполняются операции с базой данных на PHP. В листинге 2 пароль объявляется в текстовом виде. Этот пароль используется только в тестовой базе данных, создаваемой в данной статье. В дальнейшем вы можете улучшить код, используя (вместо обычного текста) пароль в виде дайджеста (digest).

Логика PHP-модуля BankLogic

PHP-файл, приведенный в листинге 2, содержит бизнес-логику для базовых операций кассира банка. В частности, к этим операциям относятся получение информации обо всех счетах, имеющихся в базе данных, выполнение транзакций для операций депозита и дебета, вычисление стоимости портфеля ценных бумаг для данного клиента. Все эти функции принимают некоторые входные параметры и возвращают ассоциативный массив, содержащий соответствующую информацию о счете. Основная часть логики работы этих функций состоит в подключении к базе данных BankDB MySQL и выполнении операций чтения или обновления. В начале листинга 2 определяются три PHP-переменные с глобальной областью видимости. Эти переменные хранят объект подключения к базе данных ($link), объект результатов SQL-запроса ($dbResult) и окончательный результат ($finalResult), возвращаемый процедуре, вызвавшей этот PHP-модуль. Этот PHP-модуль имеет две функции для подключения и отключения от базы данных MySQL. После подключения создается объект connection и сохраняется в переменной $link, которая доступна во всем этом PHP-файле, поскольку имеет глобальную область видимости. Аналогично, при выполнении операций чтения или обновления DB результаты SQL-запроса сохраняются в переменной $dbResult, которая тоже является глобальной. При необходимости закрытия подключения к базе данных используется другая вспомогательная функция (close_connection_to_db). Перед закрытием подключения к базе данных эта функция освобождает память, занимаемую переменной $dbResult.

Частью данного файла являются три базовые функции:

  • Функция getAllAccountInformation вызывается для извлечения данных обо всех счетах, имеющихся в базе данных. В коде выполняется ODBC-подключение к базе данных MySQL при помощи MySQLi extension API и извлекается информация обо всех счетах, хранящаяся в таблице account. После успешной операции чтения выполняется итерация по множеству результатов и выбирается информация о конкретном счете. Информация обо всех счетах записывается в ассоциативный PHP-массив, и этот массив возвращается программе, вызвавшей функцию.
  • Функция accountTransaction вызывается для выполнения операции депозита или дебета. В качестве входных параметров передаются имя владельца счета, сумма транзакции и тип транзакции для указания операции депозита или дебета. Выполняется ODBC-подключение к базе данных, и данные о текущем счете указанного владельца счета извлекаются из базы данных и записываются в ассоциативный массив. Это - состояние счета до транзакции. Затем выполняется необходимая транзакция (депозит или дебет). База данных обновляется с новым балансом. Это состояние счета после транзакции тоже записывается в другой ассоциативный массив. Оба состояния счета (до и после транзакции) записываются в обычный массив и возвращаются как окончательный результат программе, вызвавшей данную функцию. Также обратите внимание на то, что код выполняет транзакцию только в том случае, если указано корректное значение суммы транзакции.
  • Метод portfoliovalue вызывается для вычисления значения стоимости портфеля ценных бумаг для данного владельца счета. В качестве входных параметров передаются имя владельца счета и текущая рыночная стоимость ценных бумаг, которыми владеет данный клиент. Этот метод принимает состояние до транзакции и сохраняет его в ассоциативном массиве. Затем вычисляется новое значение стоимости портфеля ценных бумаг и обновляется соответствующее поле в базе данных Bank. В другой ассоциативный массив записывается также состояние счета после транзакции. Оба состояния счета (до и после транзакции) записываются в обычный массив и возвращаются как окончательный результат программе, вызвавшей данную функцию.

В исходном файле имеются комментарии, помогающие понять логику кода.

Одностраничный пользовательский интерфейс в стиле Ajax

Для пользовательского интерфейса кассира банка вы разработаете одностраничное приложение, работающее в браузере. Обратите внимание на то, что одностраничное приложение отличается от традиционного Web-приложения "Нажми и жди". В Web-приложениях "Нажми и жди" каждая страница извлекается с сервера путем загрузки всего содержимого каждый раз при переходе пользователя на новую страницу. Напротив, модель, используемая для выполняющихся в браузере одностраничных приложений, является полной противоположностью такого подхода. В ней все содержимое для представления (XHTML, CSS и JavaScript), необходимое приложению, извлекается с сервера только один раз. Такая одноразовая загрузка выполняется обычно в начале работы приложения, когда пользователь указывает в браузере URL приложения. Все необходимые приложению элементы пользовательского интерфейса определяются в XHTML-файле. Вся информация по оформлению (стили) для различных частей пользовательского интерфейса кодируется в CSS-файле. Для скрытия и показа нужных частей пользовательского интерфейса применяются специальные технические приемы Document Object Model (DOM), которые симулируют многостраничное поведение без извлечения страниц с сервера. JavaScript-код приложения, выполняющийся в браузере, может справиться с основной частью логики приложения. Используемая для проектирования приложения Ajax-технология делает приложение очень чувствительным к действиям пользователя. Она также снимает с сервера значительную часть нагрузки обычного генерирования страниц. В Ajax-приложениях взаимодействия браузер-сервер сводятся только к обмену специфическим для приложения данными, что оптимизирует ресурсы сервера при работе с большим количеством пользователей и приложений.

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

Одним из приемов, используемых для скрытия и показа различных частей приложения, является применение HTML-тегов <DIV>, <SPAN> и <TABLE>. Простой обзор этих тегов приведен на рисунке 1. Тег <DIV> позволяет разделить HTML-документ на несколько отдельных секций. Помещение элементов управления конкретного экрана внутри тега <DIV> является первым шагом в разделении приложения на многие экраны. После этого при помощи JavaScript будет легко управлять видимостью экрана или элемента <DIV> на конкретном этапе работы приложения. Еще одним удобным тегом в данном упражнении является тег <SPAN>, который помогает применить стили к текстовым фрагментам приложения. В сценарии работы банка этот тег используется для создания меню. Также используется тег <TABLE> для управления схемой документа.


Рисунок 1. Теги <SPAN>, <DIV>, <TABLE>
>Рисунок 1. Теги <SPAN>, <DIV>, <TABLE>

Еще одним обычным способом добавления функциональности в выполняющиеся в браузере приложения является стилевое оформление на уровне отдельных элементов пользовательского интерфейса. Для управления внешним видом приложений, выполняющихся в браузере, широко используется CSS. CSS - это отдельный код со своим собственным синтаксисом. CSS легко настроить, поскольку для этого не нужны никакие подключаемые модули - все делается в текстовом файле путем определения правил. CSS-правило состоит из селектора (selector) и блока объявлений (declaration block). Селекторы начинают каждое правило, используя фигурную скобку. Блок объявлений окружен фигурными скобками и состоит из объявлений. Объявления - это пары свойство/значение, разделенные точкой с запятой. В листинге 3 приведен простой пример CSS-правила. Существуют разные типы селекторов CSS, что показано на рисунке 2.

Объяснение всех возможностей CSS-селекторов потребовало бы написания отдельной статьи. Можете потратить некоторое время на ознакомление с другой относящейся к CSS информацией для полного понимания внутренней работы CSS. Для этого отлично подойдет сайт "CSS Zen garden", ссылка на который приведена в разделе "Ресурсы".

Листинг 3. Простое CSS-правило
                
body {
   color: maroon;
   font-size: medium;
   text-align: center; 
   background:green; 
}
		


Рисунок 2. Типы CSS-селекторов
Рисунок 2. Типы CSS-селекторов

Некоторые интегрированные среды Ajax предоставляют абстракцию библиотек исходного кода для операций ввода/вывод, сетевых операций, графики, данных и т.д. Основанная на Eclipse программа Aptana обеспечивает отличную интеграцию многих подобных Ajax-сред в одной IDE. Однако рассмотрение этих интегрированных Ajax-сред выходит за рамки данной статьи. Ajax-код для сценария работы банка реализуется при помощи обычного JavaScript, главным образом для того, чтобы упростить работу и дать вам возможность поработать с кодом в приложении напрямую, а не через библиотеки. После завершения работы с данной серией статей вы можете ознакомиться с такими интегрированными Ajax-средами как Dojo, Rico, Script.aculo.us и Prototype.

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

HTTP-взаимодействие в Ajax

В предыдущем разделе были рассмотрены технологии XHTML, CSS и DOM, являющиеся частью Ajax. Кроме них основным для Ajax-приложений является способ выполнения HTTP-взаимодействий (с сервером промежуточного уровня). Ajax обеспечивает новый способ взаимодействия выполняющихся в браузере приложений с серверами в асинхронном стиле. Он значительно отличается от классических Web-приложений в том, что пользователи не ожидают ответа и не видят песочных часов при нажатии кнопки Submit в HTML-форме. Такое асинхронное HTTP-взаимодействие поддерживается объектом XHR, который является объектом браузера, позволяющим JavaScript-коду в браузере выполнять асинхронные HTTP-запросы к серверу. Он позволяет выполнять HTTP-запросы, принимать ответы и обновлять части страницы полностью в фоновом режиме, что приводит к отсутствию видимых для пользователя прерываний работы приложения. Ajax сохраняет чувствительность пользовательского интерфейса во время работы с сервером. В настоящее время ведутся работы в W3C по стандартизации XHR (см. раздел "Ресурсы"). На рисунке 3 показаны различные методы и свойства объекта XHR.


Рисунок 3. Методы и свойства объекта XML HTTP Request (XHR)
Рисунок 3. Методы и свойства объекта XML HTTP Request (XHR)

Ниже приведено общее описание последовательности операций для XHR:

  1. Создать экземпляр объекта XMLHttpRequest.
  2. Использовать объект XMLHttpRequest для выполнения вызова к серверу, определяя функцию обратного вызова, выполняющуюся автоматически при получении ответа от сервера.
  3. Обработать ответ сервера в функции обратного вызова.
  4. При необходимости перейти к шагу 2 для выполнения следующего взаимодействия с сервером в асинхронном режиме.

Я рассмотрю конкретные детали использования XHR в данном сценарии позже.

Строительные блоки Ajax-приложения, выполняющегося в браузере

Наше приложение состоит из следующих артефактов:

  • XHTML-файл
  • CSS-файл
  • XHR JavaScript-файл
  • Бизнес-логика на JavaScript на стороне клиента
  • Необходимые вспомогательные JavaScript-файлы

XHTML-файл - это основной файл, который пользователи указывают в браузерах для начала работы приложения. Этот файл главным образом содержит все элементы пользовательского интерфейса, созданные (в основном) при помощи обычных HTML-тегов, таких как <DIV>, <SPAN>, <TABLE> и <FORM>. Данный файл также использует несколько других браузерных технологий для добавления стилей, взаимодействий и поддержки формата данных.

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

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

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

Кроме того, одним из строительных блоков данного приложения является также программа с открытым исходным кодом для обработки JSON-данных (JavaScript Object Notation). Более подробная информация об этом приведена в третьей части данной серии статей.

Реализация портала Bank как Ajax-приложения

Для нашего сценария работы банка требуется простой пользовательский интерфейс, который используют кассиры банка для выполнения основных операций, реализованных нами в PHP-модуле ранее. На момент написания данной статьи простой способ создания основанных на XHTML, CSS и JavaScript приложений, выполняющихся в браузере, предоставляет Aptana Web IDE. Aptana - это бесплатный подключаемый модуль, который интегрируется в среду Eclipse вместе с программой PDT. Он все еще находится в стадии разработки, но доступная в настоящее время промежуточная версия полностью отвечает требованиям нашего сценария. Мы будем реализовывать Ajax-функции в данном сценарии при помощи "чистого" JavaScript, хотя Aptana обеспечивает возможность интеграции с несколькими другими Ajax-библиотеками с открытыми исходными кодами.

Выполните следующие действия для создания одностраничного Ajax-приложения, выполняющегося в браузере:

  1. В Eclipse перейдите в перспективу Aptana: выберите Window->Open Perspective->Other->Aptana и нажмите кнопку OK.
  2. В перспективе Aptana в нижнем левом фрейме выберите закладку Project.
  3. Щелкните правой кнопкой мыши на проекте BankTeller и выберите New->HTML file:
    1. В поле File name введите index.html и нажмите кнопку Finish.
  4. Замените содержимое файла index.html, введя или скопировав исходный код из листинга 4, и выберите File->Save.
  5. Щелкните правой кнопкой мыши на проекте BankTeller и выберите New->CSS file:
    1. В поле File name введите BankTeller.css и нажмите кнопку Finish.
  6. Замените содержимое файла BankTeller.css, введя или скопировав исходный код из листинга 5, и выберите File->Save.
  7. Щелкните правой кнопкой мыши на проекте BankTeller и выберите New->JavaScript file:
    1. В поле File name введите xhr.js и нажмите кнопку Finish.
  8. Замените содержимое этого файла, введя или скопировав исходный код из листинга 6, и выберите File->Save.
  9. Просмотрите комментарии в этих файлах для освоения кода или обратитесь к следующему разделу, в котором приведено общее описание логики программы.

Итак, две третьих части работы с артефактами одностраничного Ajax-приложения сделано! Вы выполните оставшуюся работу в третьей части данной серии статей.

Логика выполняющегося в браузере приложения Bank

Вы создали XHTML- и CSS-артефакты вместе со вспомогательным файлом, работающим с XHR. XHTML-файл (index.html) является точкой входа в приложение. Это единственный файл, который пользователь приложения кассира банка будет видеть в адресной строке браузера. Все остальные артефакты передаются с сервера в сессию браузера вместе с файлом index.html. Если вы посмотрите в раздел <HEAD> файла index.html, то увидите следующие HTML-теги:

<script language="JavaScript" type="text/javascript" src="xyz.js"></script>

Тег script определяет один или несколько сценариев, которые могут активизироваться элементами внутри документа. В данном частном случае он загружает JavaScript-код из внешнего файла. Вот как загружается JavaScript-код приложения из трех различных JavaScript-файлов:

<link rel="stylesheet" type="text/css" href="xyz.css" media="all" />

Тег link объединяет CSS-правила, определенные во внешнем файле. Это выражение подключает указанный CSS-файл к HTML-документу, влияя таким образом на стиль всего Web-приложения.

Все артефакты, связанные с отображаемым содержимым приложения кассира банка, загружаются один раз во время начала работы приложения. Это означает, что необходимо разделить отдельные экраны, которые будут частью приложения, таким образом, чтобы их можно было отображать пользователю при необходимости. Это легко делается путем включения всех элементов пользовательского интерфейса для экрана внутрь отдельного элемента <DIV>. Все приложение полностью находится внутри элемента <DIV> под названием mainPage. В данном приложении имеется шесть других разделов, каждый из которых помещен в свой собственный элемент <DIV>. В свою очередь, все эти шесть <DIV>-разделов заключены в элемент <DIV> mainPage. Организуя эти различные UI-разделы подобным образом, мы облегчаем управление ими посредством управления объектами DOM, что будет рассмотрено в третьей части данной серии статей.

Во время загрузки приложения обработчик событий (initOnPageLoad) устанавливается в элементе <body>. Этот обработчик событий вызывается в самом начале, так чтобы можно было установить содержимое начального экрана для отображения пользователю. Аналогично тегу <DIV>, теги <SPAN> тоже приносят пользу, устанавливая меню подобную структуру в начальном экране просто путем использования обычного текста, заключенного в тег <SPAN>. Обратите внимание на то, что элементы <SPAN> имеют три различных обработчика событий, связанных с мышкой. Эти обработчики событий просто используют правила CSS-стиля для выделения (и снятия выделения) элементов меню. При нажатии на один из элементов меню, соответствующий обработчик события onclick делает соответствующий экран видимым в окне браузера. Все происходит без обращения к серверу, а лишь путем локального управления объектами DOM браузера. Еще одним интересным элементом пользовательского интерфейса является раздел сноски, которая прикрепляется к нижней части каждого экрана. В каждый момент времени схема экрана содержит <DIV>-элементы mainPage и pageFooter. Какой-либо из остальных разделов (депозит, дебет, портфель ценных бумаг и результаты операции кассира банка) помещается между этими двумя элементами <DIV> - еще один гибкий принцип Ajax-проектирования.

CSS-файл (BankTeller.css) содержит CSS-правила, которые применяются к элементам пользовательского интерфейса данного приложения. В этих CSS-правилах продемонстрировано несколько функциональных возможностей CSS. В данном приложении широко используются HTML-селекторы, ID-селекторы и class-селекторы.

Например, в самом начале CSS-файла HTML-селектор body переопределяет шрифт и цвет фона всей страницы приложения. В конце CSS-файла используется portfolioActionButton, который является ID-селектором. Он указывает, что все HTML-теги, определенные в HTML-файле (index.html) с этой строкой ID, будут иметь стиль, определенный CSS-правилом #portfolioActionButton. Аналогично, вы можете увидеть использование селектора классов в CSS-правиле .tellerOptionsLink, которое применяется ко всем HTML-тегам, присвоенным классу tellerOptionsLink. Также обратите внимание на использование групповых селекторов, в которых сгруппированы два или более селекторов для объявлений одного стиля. Примеры групповых селекторов имеются во многих местах файла BankTeller.css. В нижней части CSS-файла можно увидеть, что все три кнопки операции сгруппированы вместе (#depositAmountActionButton, #debitAmountActionButton и #portfolioActionButton) для получения одинаковых свойств стиля кнопки. Демонстрируется также еще одна продвинутая функциональная возможность CSS, называемая дочерним селектором (descendant selector). Дочерний селектор позволяет оформлять стилем отдельные дочерние элементы в зависимости от их родительского селектора. Пример показан в CSS-файле для стилевого оформления всех столбцов таблицы (например, <td> в <table>) путем назначения специфичного отступа в ячейках (cell padding). Найдите table.depositAmountButtonTable td и вы увидите применение дочерних селекторов. CSS-синтаксис HTML, ID и class-селекторов можно увидеть на рисунке 2.

XHR-файл (xhr.js) содержит две функции. Одна создает объект XHR, который можно использовать для обмена (передачи и приема) информацией с сервером промежуточного уровня. Функция createRequest подготавливает объект XHR. На момент написания данной статьи XMLHttpRequest по-разному поддерживался в различных браузерах. В частности, два самых популярных браузера (Internet Explorer (IE) и Mozilla Firefox) поддерживают XHR по-своему.

XHR по-разному реализован в различных версиях IE. Данная функция пытается создать объект XHR, используя специфичную для браузера технику. В браузерах, отличных от IE, объект XHR может быть создан просто путем инициализации встроенного класса XMLHttpRequest. В IE версии 6.0 и выше это делается при помощи ActiveXObject и XMLHTTP в Msxml2. Во всех остальных версиях IE это делается при помощи ActiveXObject и другого экземпляра объекта XMLHTTP. Microsoft работает над реализацией XHR-поддержки, аналогичной имеющейся в других браузерах. Пока этого не произошло, логика, применяемая в данной функции, необходима. Другая функция (sendHttpRequest) используется для передачи любых произвольных данных в сервис промежуточного уровня. Она взаимодействует с сервисом промежуточного уровня, используя механизм доступа в стиле REST при помощи запроса POST HTTP. Эта функция принимает следующие четыре параметра:

  • Объект XHR.
  • Функция обратного вызова (null, если функция обратного вызова не нужна).
  • URL, по которому нужно передать данные.
  • Данные (специфичные для приложения данные, которые нужно передать в сервис промежуточного уровня).

Метод sendHttpRequest передает данные в сервис промежуточного уровня, используя объект XHR. Если указана функция обратного вызова, он устанавливает свойство onreadystatechange объекта XHR в эту функцию. Затем он открывает HTTP-соединение с сервисом промежуточного уровня. В этот сервис передаются все необходимые HTTP-заголовки и данные. Если указана функция обратного вызова, метод send объекта XHR возвращает управление немедленно, не ожидая ответа сервера. В данном случае ответ сервера обрабатывается функцией обратного вызова после приема ответа браузером. Подробная информация об этом будет приведена в третьей части(EN) данной серии статей. Если функция обратного вызова не предоставляется, функция send блокирует работу и ждет получения ответа от сервера, или генерирует HTTP-ошибки.

Код выполняющегося в браузере одностраничного приложения, приведенный в листинге 4, генерирует простой интерфейс для браузера, используемый кассирами банка при выполнении банковских операций, таких как депозит, дебет и вычисление стоимости портфеля ценных бумаг. Как часть данного одностраничного Web-приложения код предоставляет три формы. Каждая из этих трех форм реализует ниспадающий HTML-список, заполняемый именами владельцев счетов. Затем реализуется редактируемое поле для ввода суммы депозита или дебета. Три кнопки позволяют кассиру банка выполнить требуемую банковскую операцию. Три кнопки в этом приложении спроектированы для доступа к REST-сервису промежуточного уровня, который вы разработаете в третьей части(EN) данной серии статей. До тех пор пока вы не разработаете PHP-модуль, функции кассира банка не будут функционировать. Также в третьей части (EN)вы разработаете JavaScript-файл (BankTeller.js).

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

Заключение

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

  • JavaScript-модуль (содержащий логику, выполняющуюся на стороне клиента, и логику асинхронного взаимодействия) для выполнения обмена данными с сервером.
  • PHP-модуль, содержащий код SOAP-клиента удаленного Web-сервиса котировок акций.
  • PHP-модуль, выступающий в роли REST-сервиса для вызовов бизнес-логики в других PHP-модулях, которые являются частью данного сценария.
  • Интеграция всех артефактов всего сценария.
  • Реализация и тестирование всего Ajax-PHP-сценария.
  • Отладка завершенного сценария с использованием отладчиков на стороне клиента и на стороне сервера.

Информация, приведенная в первой и второй частях данной серии статей, познакомила вас с богатыми возможностями технологий с открытыми исходными кодами, имеющимися для всех трех уровней, а также помогла понять работу отдельных инструментальных средств Eclipse для Ajax-PHP-разработки. Артефакты кода для создания DB на SQL, серверной логики приложения на PHP и Bank Portal (XHTML, CSS и XHR) находятся в загружаемом файле, прилагающемся к данной статье. Следите за выходом третьей и последней части данной серии статей. А пока углубитесь в изучение базовых концепций Ajax и PHP (а также технологий разработки), уже примененных в сценарии работы банка.




В начало


Загрузка

ИмяРазмерМетод загрузки
wa-aj-end2end2.zip14KBHTTP
Информация о методах загрузки


Ресурсы

Научиться

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

Обсудить


Об авторе

Сентил Натан (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.




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


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



 


 


 


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

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




В начало


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