Создание Web-приложений с помощью C++Builder 5
Автор: Наталия Елманова
Источник: www.compress.ru
Простейшее Web-приложение
Создание форм и обработка пользовательского ввода
Применение баз данных в Web-приложениях
Интерактивные формы для редактирования данных
Заключение
Данная статья посвящена одной из неплохо зарекомендовавших себя технологий
создания динамических интерактивных Web-сайтов - разработке CGI- и ISAPI-приложений.
Будучи далеко не единственной технологией создания таких Web-сайтов, она тем
не менее остается довольно популярной. В данной статье мы рассмотрим примеры
создания CGI- и ISAPI-приложений, выполняемых под управлением Microsoft Internet
Information Services, с помощью C++Builder 5. О других способах создания динамических
Web-сайтов, например разработке ASP-приложений, вы можете прочитать в статье
Сергея Трепалина <Создание серверных компонентов для ASP-приложений> на этом
же CD-ROM.
Web-приложения (называемые также скриптами)
представляют собой исполняемые файлы или
библиотеки, выполняемые под управлением Web-сервера.
Их назначение - в ответ на запросы
пользователя динамически генерировать HTML-страницы,
которые будут интерпретироваться Web-браузером.
Применение Интернета в широком смысле
означает доступ к ресурсам, содержащимся в
Сети. Любой ресурс Интернета однозначно
идентифицируется с помощью адреса URL (Uniform
Resource Locators), который можно ввести в
соответствующем поле браузера либо выбрать,
щелкнув мышью на гипертекстовой ссылке Web-страницы
или другого документа. Примерами Интернет-ресурсов
являются HTML-страницы, документы различных
форматов, Java-аплеты, элементы управления
ActiveX и другие файлы. Результат выполнения
какого-либо приложения, управляемого Web-сервером,
также является ресурсом Интернета, и если
настройки уровня безопасности браузера
позволяют использовать этот ресурс, он
также будет интерпретирован браузером.
Отметим, что приложения, выполняемые под
управлением Web-серверов и являющиеся
источником подобных ресурсов, способны
обрабатывать параметры, содержащиеся в
запросе пользователя, и результат их работы
может зависеть от этих параметров.
Создать Web-приложение, динамически
генерирующее подобные ресурсы (обычно HTML-документы),
можно с помощью практически любого
средства разработки - лишь бы оно
позволяло создавать приложения для той
операционной системы, в которой работает Web-сервер.
Однако если вы хотите снизить трудозатраты,
связанные с созданием таких приложений, то
имеет смысл обратить внимание на средства
разработки, позволяющие их минимизировать.
С этой точки зрения довольно удачным
выбором являются Borland Delphi 5 и Borland C++Builder 5 (редакции
Enterprise и Professional), а также Delphi 4 и C++Builder 4 Enterprise,
так как эти средства разработки содержат
неплохие визуальные инструменты и
компоненты для создания подобных
приложений.
Рассматриваемые в настоящей статье примеры или их аналоги, если это особо не
оговорено, можно создавать с помощью любого из перечисленных выше средств разработки.
Сами примеры созданы с помощью C++Builder 5 Enterprise, но, думаю, пользователям
Delphi не составит особого труда перенести их код на Object Pascal.
Изучение разработки Web-приложений мы
начнем с создания простейшего примера.
Простейшее Web-приложение
Для создания простейшего Web-приложения из главного меню среды разработки C++Builder
выберем пункт File | New и в репозитарии объектов выберем пиктограмму Web Server
Application (рис. 1).
Рис. 1. Выбор пиктограммы Web Server Application из репозитария объектов
Далее нужно выбрать тип приложения (исполняемый файл CGI или Win-CGI либо динамически
загружаемая библиотека ISAPI/NSAPI DLL, представляющая собой функциональное
расширение для Microsoft Internet Information Services или Netscape FastTrack).
CGI-скрипт (CGI-Common Gateway Interface), будучи исполняемым файлом, запускается
в отдельном процессе, в то время как ISAPI/NSAPI DLL (динамически загружаемая
библиотека - выполняется в адресном пространстве Web-сервера. Поэтому ISAPI/NSAPI
DLL требуют меньше ресурсов, чем CGI-скрипты. К тому же такие библиотеки после
загрузки остаются в памяти сервера, что уменьшает время их отклика на последующие
обращения к ним. Однако это мешает их отладке: после внесения в библиотеку каких-либо
изменений необходим перезапуск Web-сервера. В связи с этим при разработке Web-приложений
нередко сначала создается CGI-скрипт, который затем отлаживается, после чего
на основе имеющихся модулей создается ISAPI/NSAPI DLL. Так мы и поступим: выберем
опцию CGI Stand-alone executable и создадим Win32-консольное приложение для
генерации HTML-документов. В результате получим объект TWebModule, напоминающий
обычный модуль данных (рис. 2).
Рис. 2. Объект TWebModule
Рассмотрим, как работает Web-приложение.
Если Web-сервер получает от браузера запрос,
соответствующий спецификации CGI, он
инициирует запуск CGI-приложения для его
выполнения. Если запрос корректен, CGI-приложение
обрабатывает его и генерирует HTML-документ,
который отсылается Web-сервером обратно в
браузер. Для обмена данными между браузером
и сервером используется протокол HTTP (HyperText
Transfer Protocol).
Когда Web-приложение получает HTTP-запрос, оно создает объект TWebRequest
для представления запроса и объект TWebResponce для представления отклика,
отправляемого в браузер пользователя. Затем оба объекта передаются объекту TWebModule
(рис. 3).
Рис. 3. Структура Web-приложения
Объект TWebModule содержит набор объектов TWebActionItems,
хранящих информацию о том, как обрабатывать
различные пользовательские запросы.
Опознав запрос, он выбирает нужный из них и
выполняет соответствующий обработчик
события OnAction, обрабатывающий запрос и
динамически генерирующий ответ, который
передается Web-сервером в браузер
пользователя.
Для того чтобы приложение было работоспособным, создадим хотя бы один объект
TWebActionItem, реализующий отклик на пользовательский запрос. С этой
целью из контекстного меню объекта TWebModule надо выбрать пункт Action
Editor и нажать кнопку Add в появившейся форме. Далее можно установить
свойства PathInfo и Default объекта WebActionItem1. Первое
свойство является частью URL (Uniform Resource Locator) - полного описания
доступа к ресурсу (рис. 4).
Рис. 4. Структура URL
Свойство Default указывает, выполняется ли данный отклик, если параметр
PathInfo в пользовательском запросе остался пустым (рис.5).
Рис. 5. Action Editor
Теперь создадим обработчик события OnAction компонента TWebActionItem:
void __fastcall TWebModule1::WebModule1WebActionItem1Action(
TObject *Sender, TWebRequest *Request, TWebResponse *Response,
bool &Handled)
{
AnsiString cont = AnsiString("<HTML><BODY><H3>Hello!</H3>");
cont = cont + AnsiString("<BR>");
cont = cont + AnsiString("<H2>Now is ") + TimeToStr(Time()) +
AnsiString(" </H2>");
cont = cont + AnsiString("</BODY></HTML>");
Response->Content = cont;
}
В этом обработчике события генерируется содержащая текущее время HTML-страница
примерно следующего вида (рис. 6):
Рис. 6. Динамически генерируемая HTML-страница
Сделаем одно небольшое, но важное замечание. Перед компиляцией такого приложения
в С++Builder в опциях проекта следует отключить опцию Use dynamic RTL
на странице Linker. Кроме того, стоит отключить и опцию Build with
runtime packages на странице Packages либо поместить все эти библиотеки
в тот же каталог, что и само приложение (рис. 7).
Рис. 7. Диалоговая панель Project Options
Дело в том, что запустить такое приложение
из командной строки можно без проблем, при
этом оно обращается к RTL и <пакетам>,
находящимся за пределами каталогов Web-сервера.
Однако запустить его с помощью Web-сервера
скорее всего не удастся - все эти файлы
окажутся недоступны. В этом случае вместо
ожидаемого результата выполнения
приложения будет получено сообщение об
ошибке примерно следующего вида:
CGI Error
The specified CGI application misbehaved by not returning a
complete set of HTTP headers. The headers it did return are: ...
Отметим, что при создании ISAPI DLL с
использованием Delphi 4 или C++Builder 4 в такой
библиотеке не должно быть <пакетов> - она
обязательно должна состоять из одного
файла.
После компиляции приложения можно
сохранить полученный исполняемый файл в
каталоге, предназначенном для Web-приложений
(в случае MS Internet Information Services по умолчанию это
каталог C:\Inetpub\scripts). Затем можно обратиться
к приложению через Web-браузер, указав URL-приложения.
Обратите внимание: внешнему пользователю,
обращающемуся к созданному приложению
через браузер, не видна (и не должна быть
видна) структура каталогов компьютера,
содержащего Web-сервер, - вместо этого ему
следует вводить их псевдонимы. Такой подход
к использованию каталогов Web-сервера
необходим для обеспечения безопасности -
внешний пользователь ничего не должен
знать о файлах и каталогах компьютера,
содержащего Web-сервер, кроме того что ему
положено.
Запустив приложение, можно нажать кнопку Reload и убедиться, что текст
в браузере меняется. Это значит, что страница генерируется динамически (рис. 8).
Рис. 8. Динамически генерируемая HTML-страница
Из этого CGI-скрипта мы можем создать ISAPI DLL. Для этого следует создать
новое Web-приложение в виде ISAPI DLL, удалить из него объект TWebModule,
а вместо него добавить другой объект TWebModule из предыдущего проекта.
Создание форм и обработка пользовательского ввода
Отметим, что объект TWebModule существенно
облегчает создание CGI-приложений, связанных
с обработкой пользовательского ввода (например,
в HTML-формах), заключающегося в изменении или
добавлении данных. Типичными примерами
таких приложений являются анкеты, которые в
изобилии встречаются на многих Web-серверах.
Дополним наше приложение такой анкетой.
Для отображения в браузере формы ввода данных пользователем создадим еще один
компонент TWebActionItem (рис. 9):
Рис. 9. Добавление объекта TWebActionItem для создания HTML-формы
Установим свойство Default вновь созданного объекта TWebAction
равным True. Теперь добавим в WebModule1 компонент TPageProducer,
назначение которого - генерировать HTML-документ на основе заранее заданного
шаблона (рис. 10).
Рис. 10. Добавление в WebModule1 компонента TPageProducer
Для создания шаблона документа можно воспользоваться любым HTML-редактором,
поддерживающим создание форм, например Microsoft FrontPage (рис. 11).
Рис. 11. Создание шаблона HTML-формы с помощью Microsoft FrontPage
Исходный текст формы, представленной на рис. 11, имеет вид:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>Untitled Normal Page</title></head>
<body bgcolor="#FFFFFF">
<p> </p>
<form method="GET">
<p>What is Your name?<font size="4">
<input type="text" size="20" name="T1"></font></p>
<p>What is Your e-mail?<font size="4">
<input type="text" size="20" name="T2"></font></p>
<p><font size="4"><input type="submit" name="B1"
value="Submit"><input type="reset" name="B2"
value="Reset"></font></p>
</form>
</body>
</html>
Созданный документ можно сохранить в виде
файла (и указать его имя в качестве свойства
HTMLFile компонента TPageProducer). Можно
также скопировать HTML-текст в буфер обмена и
поместить его в редактор свойства HTMLDoc
этого компонента.
Теперь создадим обработчик события OnAction
сгенерированного нами компонента TWebActionItem2:
void __fastcall TWebModule1::WebModule1WebActionItem2Action(
TObject *Sender, TWebRequest *Request, TWebResponse *Response,
bool &Handled)
{
Response->Content=PageProducer1->Content();
}
Отметим, что в Delphi 5 и C++Builder 5 компонент TWebAction
имеет свойство Producer, позволяющее
непосредственно указать, какую именно HTML-страницу
нужно генерировать при обращении. Это во
многих случаях избавляет от необходимости
создавать обработчик события OnAction
данного компонента.
Сохранив проект, можно снова обратиться к нему с помощью браузера, указав значение
PathInfo в URL (рис. 12):
Рис. 12. Тестирование HTML-формы в браузере
Теперь осталось обработать пользовательский ввод, например, динамически сгенерировав
страницу с введенными пользователем значениями. С этой целью добавим еще один
компонент - TPageProducer (рис. 13):
Рис. 13. Добавление компонента PageProducer2 для генерации
страницы,
содержащей результаты обработки пользовательского ввода
В качестве значения свойства HTMLDoc
вновь созданного компонента PageProducer2
введем следующий текст:
<html>
<head>
<title>Thank You!</title>
</head>
<body >
<p>Dear <#T1>!</p>
<p>Thank you for completing this form. We have included your
e-mail address <#T2> in our mailing list. You will receive a
lot of spam from us!</p>
</body>
</html>
Данный текст представляет собой шаблон
документа. Он содержит специальные тэги,
заменяемые в процессе формирования HTML-страницы
строками, которые, в свою очередь, могут
быть введены пользователем в созданную
выше форму. В нашем случае это тэги <#T1> и
<#T2>. Они представляют собой имена полей
ввода в созданной ранее форме, в чем можно
убедиться, просмотрев HTML-текст формы.
Для замены специальных тэгов следует
создать обработчик события OnHTMLTag
компонента PageProducer2:
void __fastcall TWebModule1::PageProducer2HTMLTag(
TObject *Sender, TTag Tag, const AnsiString TagString,
TStrings *TagParams, AnsiString &ReplaceText)
{
ReplaceText = Request->QueryFields->Values[TagString] +
Request->ContentFields->Values[TagString];
}
Здесь Request - объект TWebRequest,
сгенерированный приложением в результате
пользовательского запроса. В свойстве QueryFields
(объект TStrings) этого объекта содержатся
имена параметров и значения, введенные
пользователем, в виде Name=Value (реально они
содержатся в переменной окружения QUERY_STRING,
созданной Web-сервером, в виде Name1=Value1&Name2=Value2&:).
Параметр TagString - строка, содержащаяся в
тэге, подлежащем замене. Cвойство Values
объекта TStrings используется, если строки,
содержащиеся в этом объекте, представимы в
виде Name=Value (что и происходит в данном случае).
Отметим, что если в тэге <form>,
содержащемся в тексте формы, вместо метода
GET указан метод POST, то вместо свойства QueryFields
следует использовать свойство ContentField.
Теперь создадим еще один компонент TWebAction
(со значением свойства PathInfo, равным /test3)
для отображения страницы, сгенерированной
с помощью PageProducer2, и добавим еще один
обработчик события OnAction:
void __fastcall TWebModule1::WebModule1WebActionItem3Action(
TObject *Sender, TWebRequest *Request, TWebResponse *Response,
bool &Handled)
{
Response->Content=PageProducer2->Content();
}
Возникает вопрос: каким образом можно
инициировать генерацию этой страницы после
нажатия пользователем кнопки Submit в форме
ввода? С этой целью следует описать реакцию
на ее нажатие в HTML-тексте формы, то есть
отредактировать свойство HTMLDoc
компонента PageProducer1:
<form method="POST"
action="http://mywebserver/scripts/formproc.exe/t3">
В параметре action указывается URL ресурса,
предоставляемого при нажатии кнопки Submit. В
данном случае это наше приложение со
значением PathInfo, равным /test3 (естественно,
имя Web-сервера, так же как и другие части URL,
может быть другим).
Теперь можно снова скомпилировать и сохранить приложение. Обратившись к нему
с помощью браузера и заполнив форму, нажмем на кнопку Submit. В результате получим
страницу, сгенерированную динамически на основе введенных в форму данных (рис. 14):
Рис. 14. Результат обработки пользовательского ввода
Из этого CGI-скрипта, как и в предыдущем случае, можно создать ISAPI DLL.
Применение баз данных в Web-приложениях
Мы можем создать код, позволяющий добавлять записи в какую-нибудь таблицу,
в созданный ранее обработчик события WebModule1WebActionItem3Action (и
таким образом действительно получить простейший список рассылки). Для этого
необходимо добавить некоторые из компонентов доступа к данным в WebModule1
и установить соответствующие свойства (рис. 15):
Рис. 15. Объект TWebModule с компонентами доступа к данным
Перепишем созданный ранее обработчик
события WebModule1WebActionItem3Action:
void __fastcall TWebModule1::WebModule1WebActionItem3Action(
TObject *Sender, TWebRequest *Request,
TWebResponse *Response, bool &Handled)
{
AnsiString CustName=Request->QueryFields->Values["T1"] +
Request->ContentFields->Values["T1"];
AnsiString CustEmail=Request->QueryFields->Values["T2"] +
Request->ContentFields->Values["T2"];
Table1->Open();
Table1->Append();
Table1->FieldByName("Name")->Value=CustName;
Table1->FieldByName("E-mail")->Value=CustEmail;
Table1->Post();
Table1->Close();
Response->Content=PageProducer2->Content();
}
Теперь наше приложение сохраняет
пользовательский ввод в таблице базы
данных. Чтобы убедиться в этом, можно
скомпилировать, а затем протестировать
приложение.
Мы рассмотрели простейший пример
использования баз данных в Web-приложениях.
Но, как правило, требуется публикация
данных в Интернете и представление их в
браузере. Для этой цели используются
компоненты TDataSetTableProducer и TQueryTableProducer,
получающие данные либо из компонентов TDataSet,
либо c помощью запроса к базе данных и
представляющие их в виде HTML-документа в
табличном виде.
Для создания приложений, осуществляющих публикацию данных в Интернете, можно
воспользоваться <мастером> DB Web Application Wizard со страницы Business
репозитария объектов (рис. 16).
Рис. 16. Выбор DB Web Application Wizard из репозитария объектов
DB Web Application Wizard представляет собой последовательность диалоговых
панелей, в которых следует выбирать базу данных, таблицу и публикуемые поля
(рис. 17).
Рис. 17. Выбор полей таблицы или запроса, отображаемых в браузере
После заполнения всех форм мы получим компонент TWebModule, в который
входят компоненты TTable (или TQuery), TSession
и TDataSetPageProducer. Этого достаточно для создания простейшего приложения
для публикации данных. Выглядеть оно будет примерно так, как показано на рис. 18.
Рис. 18. Простейшее Web-приложение, публикующее данные в Интернете
Таблица, выбранная для этого примера (biolife.db
из базы данных BCDEMOS), содержит графические
поля. Рассмотрим варианты отображения их в
таблице.
Один из способов решения этой проблемы -
создание в таблице вычисляемого поля,
содержащего соответствующий HTML-тэг со
ссылкой на графический файл, полученный на
основе изображения, извлеченного из
соответствующей записи. Именно так мы и
поступим. Кроме того, необходимо учитывать,
что несколько человек могут обратиться к
одной и той же таблице с разными запросами
одновременно, поэтому конкретный
пользователь не должен видеть в своем
браузере изображения, которые ему не
предназначены. Этого можно достичь,
например, присвоив файлам с изображениями
уникальные имена. Обработчик события OnCalcField
для компонента Table1, реализующий этот
прием, может выглядеть, например, так:
void __fastcall TWebModule1::Table1CalcFields(
TDataSet *DataSet)
{
TDateTime DT = Now();
Word hour,min,sec,msec;
DecodeTime(DT,hour,min,sec,msec);
//Создадим уникальный ID, основанный на текущем значении времени
UserID=IntToStr(hour)+IntToStr(min)+IntToStr(sec)+IntToStr(msec);
//Создадим уникальное имя для файла с изображением
int i=random(1000000000);
AnsiString FileName=UserID+"_"+IntToStr(i)+".JPG";
//Save an image to a file
TJPEGImage *JPG= new TJPEGImage;
TPicture *P = new TPicture();
P->Assign(Table1->FieldByName("Graphic"));
JPG->Assign(P->Graphic);
JPG->SaveToFile(FileName);
Table1Picture->Value="<IMG SRC='"+FileName+"'>";
&P->Free;
&JPG->Free;
}
Необходимо также сослаться на
соответствующий h-файл:
#include <vcl\jpeg.hpp>
Видимо, приведенный выше код нуждается в
некоторых комментариях. При написании
предполагалось, что вероятность извлечения
какого-либо изображения двумя
пользователями одновременно в течение
одной и той же миллисекунды ничтожно мала. В
этом случае можно сгенерировать имена
файлов извлекаемых изображений, комбинируя
величину, основанную на значении времени с
точностью до миллисекунды, со случайным
числом, которое уникально для каждой записи
в данном сеансе работы пользователя, но, к
сожалению, не уникально для нескольких
пользователей одновременно.
Может возникнуть вопрос: почему файл с
графическим изображением не удаляется в
обработчике события OnCalcFields? Дело в том, что
изображение может быть загружено в браузер
намного позже, чем приложение завершит свою
работу (особенно если пользователь имеет
доступ в Интернет по обычной телефонной
линии с помощью модемного соединения). Это
означает, что файлы с изображениями после
окончания работы приложения должны
храниться на жестком диске Web-сервера.
Поэтому удаляться они должны другим
приложением либо просто другим экземпляром
того же самого приложения, запущенным позже.
Пример кода, реализующего удаление
ненужных файлов с графическими
изображениями в предположении, что для
загрузки всех изображений в браузер
конкретного пользователя достаточно
десяти минут, приведен ниже:
void __fastcall TWebModule1::WebModuleCreate(TObject *Sender)
{
//Delete old *.JPG files
TSearchRec sr;
if (FindFirst("*.JPG", faAnyFile, sr) == 0)
{
do
{
if (Double(Now())-Double(FileDateToDateTime(sr.Time))>0.00694)
//10 минут - это примерно 0.00694 часть дня
DeleteFile(sr.Name);
} while (FindNext(sr) == 0);
FindClose(sr);
}
//инициализируем генератор случайных чисел
Randomize();
}
В обработчике события OnCrerate нашего
объекта TWebModule удаляем все изображения,
хранящиеся в каталоге Web-приложения более
десяти минут, и инициализируем генератор
случайных чисел.
Отметим, что каталог, в котором размещены
файлы с графическими изображениями, должен
быть доступен для чтения пользователями
Интернета. Поскольку в нашем примере это
тот же самый каталог, где находится
исполняемый файл, не исключено, что для
работоспособности этого приложения нужно
внести соответствующие изменения в
настройки каталогов Web-сервера - например,
каталог Scripts Internet Information Services, где обычно
помещают Web-приложения, по умолчанию такого
разрешения не имеет. Однако с точки зрения
безопасности более оправданно размещение
файлов с изображениями в другом каталоге.
Наконец, щелкнем правой клавишей мыши на компоненте TDataSetTableProducer,
выберем опцию Response Editor и изменим вид HTML-таблицы (рис. 19).
Рис. 19. Response editor
Можно, например, изменить свойства Cellpadding,
Cellspacing, Border, BgColor HTML-таблицы,
отвечающие за расстояние между ячейками, их
цвет, толщину линий сетки. Кроме того, мы
можем сгенерировать объекты THTMLTableColumn и
изменить их свойства, что позволит
установить свои правила отображения
колонок таблицы и их заголовков.
Теперь можно сохранить, скомпилировать и протестировать приложение. Результат
изображен на рис. 20.
Рис. 20. Публикация в Интернете таблицы, содержащей графические поля
Выполнение всех рассмотренных выше примеров возможно с помощью Delphi 5 и C++Builder
5 Enterprise и Professional, а также Delphi 4 и C++Builder 4 Enterprise. Пример,
который будет рассмотрен в следующей части статьи, можно выполнить только посредством
Delphi 5 и C++Builder 5 Enterprise, поскольку в нем использованы компоненты
InternetExpress, отсутствующие в других версиях этих средств разработки.
Интерактивные формы для редактирования данных
Вернемся ненадолго к примеру, в котором
реализована форма ввода данных в таблицу,
содержащую список рассылки. Если при работе
с подобным приложеним пользователь введет
в какие-либо поля формы некорректные данные,
узнает он об этом только после отправки
данных формы на Web-сервер и получения
результата их обработки. Иными словами, интерактивность
данного приложения невелика.
Несколько иначе обстоит дело с более интерактивным
Web-приложением, которое позволяет, как
минимум, не обращаться к серверу для
проверки соответствия введенных данных
каким-либо банальным требованиям типа
отсутствия букв в числовом поле, а также
контролирует корректность введенных
данных в момент, когда фокус ввода покидает
данное поле, а не когда вся запись
отправляется на сервер. Пути достижения
этой цели известны, и наиболее
распространенным из них является
применение скриптовых языков (VBScript или
JavaScript). Фрагменты кода на этих языках,
содержащие логику проверки корректности
данных, могут находиться в HTML-странице, и
при отображении в браузере они
интерпретируются им, позволяя произвести
такую проверку без обращения к серверу. В
этом случае наше CGI- или ISAPI-приложение
должно <уметь> генерировать страницы,
содержащие код на одном из этих языков.
В принципе, при наличии времени и знаний
одного из скриптовых языков создать
интерактивный аналог приведенных выше
примеров не так уж сложно. Однако при
наличии Delphi 5 или C++Builder 5 Enterprise добиться
интерактивности можно более простым
способом. Этот способ заключается в
применении компонентов InternetExpress,
которые предназначены для создания MIDAS-клиентов,
являющихся Web-приложениями. Подобные
приложения обмениваются XML-данными с
браузерами, поддерживающими интерпретацию
кода JavaScript. Подробности о MIDAS-приложениях
подобного типа можно узнать из статьи (КомпьютерПресс, №
1'2000).
Отметим, что применение компонентов InternetExpress
не ограничено только <истинными> MIDAS-приложениями
с отдельным сервером доступа к данным - с
помощью этих компонентов можно создать Web-приложение,
являющееся обычным клиентом серверной СУБД.
Однако подобное приложение более
интерактивно, чем традиционное HTML-приложение,
и ниже мы увидим, в чем это выражается.
Итак, создадим простейшее приложение,
иллюстрирующее применение компонентов InternetExpress.
В этом примере мы поместим MIDAS-сервер и MIDAS-клиент
в одно и то же приложение. Для этого
создадим новое CGI-приложение и поместим
компоненты TTable и TDataSetProvider в объект TWebModule - они представляют собой <серверную> часть
этого приложения. Теперь необходимо
установить значения свойств DatabaseName и TableName
компонента Table1 (например, BCDEMOS и Customers.db).
Далее следует установить значение свойства
DataSet компонента DataSetProvider1 равным Table1 - это означает, что компонент Table1
теперь доступен для будущих MIDAS-клиентов.
Теперь поместим в тот же самый объект TWebModule компоненты TXMLBroker
и TmidasPageProducer, представляющие собой <клиентскую> часть нашегоWeb-приложения.
Первый из них отвечает за получение пакетов данных от MIDAS-сервера, а второй -
за генерацию Web-страницы, направляемой в браузер. В данном примере MIDAS-сервер
находится внутри нашего же приложения, поэтому установим значение свойства ProviderName
компонента XMLBroker1 равным DataSetProvider1, оставив свойство
RemoteServer пустым (рис. 21).
Рис. 21. Компоненты InternetExpress в объекте TWebModule
Далее необходимо выбрать пункт Web Page Editor из контекстного меню компонента
MidasPageProducer1. Этот редактор свойств позволяет указать, какие интерфейсные
элементы для отображения и редактирования данных нужно отображать в браузере.
Например, добавим в него компонент DataForm с вложенными в него компонентами
FiedlGroup и DataNavigator. Установим значение свойства XMLBroker
компонента FieldGroup1 равным XMLBroker1, а свойства XMLComponent
компонента DataNavigator1 - FieldGroup1 (рис. 22).
Рис. 22. Создание пользовательского интерфейса с помощью Web Page Editor
Следующим шагом будет установка значения
свойства IncludePathURL компонента MidasPageProducer1.
Это URL, где наше Web-приложение должно найти
JavaScript- и HTML-файлы, используемые для
генерации Web-страниц. Файлы *.js и *.html следует
скопировать из каталога Cbuilder5\Source\Webmidas в
каталог, соответствующий этому URL.
Следует заметить, что каталог Inetpub\Scripts,
являющийся по умолчанию каталогом для Web-приложений
Microsoft Internet Information Services и, следовательно,
потенциальным местом для размещения нашего
Web-приложения, - не самое подходящее место
для данных файлов. Дело в том, что по
умолчанию файлы из этого каталога можно
запускать на выполнение, но они недоступны
для чтения. Поэтому нужно изменить
настройки этого каталога или, что более
предпочтительно, использовать другой
каталог.
Наконец, следует создать объект TWebActionItem,
установить значение его свойства Default
равным true, а значение свойства Producer - MidasPageProducer1. Наше приложение готово.
Теперь можно сохранить проект, скомпилировать его и перенести исполняемый файл
в соответствующий каталог Web-сервера. Результат выполнения данного приложения
показан на рис. 23.
Рис. 23. Результат выполнения приложения с компонентами InternetExpress
Теперь осталось рассмотреть, почему полученное приложение более интерактивно,
чем приложение, результат выполнения которого изображен на рис. 12.
Анализ поведения последнего приложения показывает, что оно позволяет
редактировать одновременно несколько записей, перемещаться между ними, использовать
кнопки Undo или Post, добавлять и удалять записи - и все это без
обращения к Web-серверу. Только нажатие кнопки ApplyUpdates инициирует
новый запуск Web-приложения для того, чтобы сохранить внесенные пользователем
изменения в базе данных. Если внимательно рассмотреть текст Web-страницы, генерируемый
этим приложением, можно увидеть фрагменты кода JavaScript, а также XML-данные,
соответствующие содержимому таблицы или запроса (их объем можно ограничить свойством
MaxRecords компонента TXMLBroker). Поскольку код JavaScript интерпретируется
браузером, а все необходимые данные содержатся внутри Web-страницы, при перемещении
по записям и их редактировании нет необходимости обращаться к Web-серверу, пока
пользователю не потребуется новая порция записей из базы данных. Это означает,
что InternetExpress-приложения более интерактивны, чем HTML-приложения.
Заключение
В данной статье мы рассмотрели создание
наиболее часто встречающихся типов Web-приложений
с помощью C++Builder. Изучили, как динамически
генерировать Web-страницы, обрабатывать
пользовательский ввод и сохранять его в
базе данных, как публиковать данные в
Интернете и организовать вывод графических
изображений. Наконец, мы обсудили, как
создать интерактивное Web-приложение для
редактирования данных.
Следует заметить, что создание приложений
подобного класса возможно с помощью не
только средств разработки Borland, но и
большинства других (Microsoft Visual Basic, Sybase PowerBuilder,
Microsoft Visual FoxPro и т.д.). Названия классов,
применяемых при генерировании таких
приложений, могут быть иными, но основные
принципы остаются примерно теми же, что и в
приведенных примерах.
В заключение отметим, что CGI/ISAPI - не
единственная технология создания Web-приложений,
содержащих код, исполняемый на Web-сервере. В
настоящее время все более популярной
становится технология ASP (Active Server Pages),
позволяющая включать результат выполнения
серверного кода в Web-страницы. Подробнее об
этом можно прочитать в других статьях, в
частности в статье Сергея Трепалина <Создание
серверных компонентов для ASP-приложений> на
нашем CD-ROM.
|